How to join feathersjs jwt with mongoose? - node.js

I try to do login to my application using local users kept in mongodb. My application works on Node.js using feathersjs. After run the app I receive an error like below:
Error: You must provide a 'header' in your authentication configuration or pass one explicitly
This is my config file:
{
"host": "localhost",
"port": 3030,
"public": "../public/",
"paginate": {
"default": 10,
"max": 50
},
"authentication": {
"secret": "My secret key",
"strategies": [
"jwt",
"local"
],
"path": "/authentication",
"service": "authentication",
"jwt": {
"header": {
"type": "access"
},
"audience": "https://yourdomain.com",
"subject": "anonymous",
"issuer": "feathers",
"algorithm": "HS256",
"expiresIn": "1d"
},
"local": {
"entity": "user",
"usernameField": "email",
"passwordField": "password"
}
},
"mongodb": "mongodb://localhost:27017/mydb"
}
What is wrong with this?

This was a bug in a recent version of feathers-cli which has been fixed in v2.3.7 so make sure feathers --version show that version. In an existing application you can fix the error message with by changing src/app.js from
app.configure(jwt(config.jwt));
app.configure(local(config.local));
To
app.configure(jwt());
app.configure(local());

Related

"message": "Invalid login", "code": 401 for #feathersjs/authentication-local in windows while not in linux or mac

When I pulled working code of my project which was working fine in Mac, was giving me this error when authenticating in windows
Error
{
"name": "NotAuthenticated",
"message": "Invalid login",
"code": 401,
"className": "not-authenticated",
"errors": {}
}
post request
{
"strategy": "local",
"username": "demo",
"password": "demo"
}
default.json
"authentication": {
"entity": "user",
"service": "users",
"secret": "2wVrC38R9sUb6Cjhuhoir3oate0=",
"authStrategies": [
"jwt",
"local"
],
"jwtOptions": {
"header": {
"type": "access"
},
"audience": "https://yourdomain.com",
"issuer": "feathers",
"algorithm": "HS256",
"expiresIn": "1d"
},
"local": {
"usernameField": "username",
"passwordField": "password"
}
},
So strategy local was not at all working
From documentation feathers doc
"Important: If you want to set the value of usernameField to username in your configuration file under Windows, the value has to be escaped as \\username (otherwise the username environment variable will be used)"
thus the code change requires in default.json is
"local": {
"usernameField": "\\username",
"passwordField": "password"
}

Getting access denied after keycloak login. I dont have any roles in my keycloak server

I am implementing Keycloak authorization to my Node.js application. I created a realm and a client inside of it. I don't have any roles either in realm or in client. I have a route "/test" which is protected with Keycloak.
My keycloak.json looks like this:
{
"realm": "demo",
"auth-server-url": "http://localhost:8080/auth",
"ssl-required": "external",
"resource": "myapp",
"public-client": true,
"confidential-port": 0
}
Define roles (realm roles or client roles), assign the roles to your user (user which you use to perform the test), check your role scope mappings (or you can configure your client as full-scope for testing purpouse), and check that you are protecting your '/test' route with those same permissions.
E.g. you can try with keycloak-nodejs adapter (example).
Look at this configuration file (keycloak realm configuration example):
{
"realm": "nodejs-example",
"enabled": true,
"sslRequired": "external",
"registrationAllowed": true,
"privateKey": "...................",
"publicKey": ".....................",
"requiredCredentials": [ "password" ],
"users" : [
{
"username" : "user",
"enabled": true,
"email" : "sample-user#nodejs-example",
"firstName": "Sample",
"lastName": "User",
"credentials" : [
{ "type" : "password",
"value" : "password" }
],
"realmRoles": [ "user" ],
"clientRoles": {
"account": ["view-profile", "manage-account"]
}
}
],
"roles" : {
"realm" : [
{
"name": "user",
"description": "User privileges"
},
{
"name": "admin",
"description": "Administrator privileges"
}
]
},
"scopeMappings": [
{
"client": "nodejs-connect",
"roles": ["user"]
}
],
"clients": [
{
"clientId": "nodejs-connect",
"enabled": true,
"publicClient": true,
"baseUrl": "/",
"adminUrl" : "http://localhost:3000/",
"baseUrl" : "http://localhost:3000/",
"redirectUris": [
"http://localhost:3000/*"
],
"webOrigins": []
},
{
"clientId": "nodejs-apiserver",
"enabled": true,
"secret": "secret",
"redirectUris": [
"http://localhost:3000/*"
],
"webOrigins": [
"http://localhost:3000/*"
],
"serviceAccountsEnabled": true,
"authorizationServicesEnabled": true,
"authorizationSettings": {
"resources": [
{
"name": "resource",
"type": "urn:nodejs-apiserver:resources:default",
"ownerManagedAccess": false,
"uris": [
"/*"
],
"scopes": [
{
"name": "view"
},
{
"name": "write"
}
]
}
],
"policies": [
{
"name": "Default Policy",
"description": "A policy that grants access only for users within this realm",
"type": "js",
"config": {
"code": "// by default, grants any permission associated with this policy\n$evaluation.grant();\n"
}
},
{
"name": "Default Permission",
"description": "A permission that applies to the default resource type",
"type": "resource",
"config": {
"defaultResourceType": "urn:nodejs-apiserver:resources:default",
"applyPolicies": "[\"Default Policy\"]"
}
}
]
}
}
]
}
Explanation:
From this sample, look at how a user has roles assigned (realm roles: "user", account client roles: "account": ["view-profile", "manage-account"]):
{
...
"users" : [
{
"username" : "user",
"enabled": true,
"email" : "sample-user#nodejs-example",
"firstName": "Sample",
"lastName": "User",
"credentials" : [
{ "type" : "password",
"value" : "password" }
],
"realmRoles": [ "user" ],
"clientRoles": {
"account": ["view-profile", "manage-account"]
}
}
],
...
}
Look at how realm Roles are defined:
{
...
"roles" : {
"realm" : [
{
"name": "user",
"description": "User privileges"
},
{
"name": "admin",
"description": "Administrator privileges"
}
]
},
...
}
Look at how this sample uses a 'scope mapping' to map roles from realm to a user authenticated by a client (read more about this here role scope mapping):
{
...
"scopeMappings": [
{
"client": "nodejs-connect",
"roles": ["user"]
}
],
...
}
Look at how clients are defined. Check that 'nodejs-connect' client is public and 'nodejs-apiserver' is secret. In this sample, server is using the 'Authorization Api' to protect resources but you could protect your resources by granted roles only (if you want).
{
...
"clients": [
{
"clientId": "nodejs-connect",
"enabled": true,
"publicClient": true,
"baseUrl": "/",
"adminUrl" : "http://localhost:3000/",
"baseUrl" : "http://localhost:3000/",
"redirectUris": [
"http://localhost:3000/*"
],
"webOrigins": []
},
{
"clientId": "nodejs-apiserver",
"enabled": true,
"secret": "secret",
"redirectUris": [
"http://localhost:3000/*"
],
"webOrigins": [
"http://localhost:3000/*"
],
"serviceAccountsEnabled": true,
"authorizationServicesEnabled": true,
"authorizationSettings": {
"resources": [
{
"name": "resource",
"type": "urn:nodejs-apiserver:resources:default",
"ownerManagedAccess": false,
"uris": [
"/*"
],
"scopes": [
{
"name": "view"
},
{
"name": "write"
}
]
}
],
"policies": [
{
"name": "Default Policy",
"description": "A policy that grants access only for users within this realm",
"type": "js",
"config": {
"code": "// by default, grants any permission associated with this policy\n$evaluation.grant();\n"
}
},
{
"name": "Default Permission",
"description": "A permission that applies to the default resource type",
"type": "resource",
"config": {
"defaultResourceType": "urn:nodejs-apiserver:resources:default",
"applyPolicies": "[\"Default Policy\"]"
}
}
]
}
}
]
...
}
Finally, look at javascript (index.js) file to see how it uses 'keycloak-connect' (adapter) to protect and enforce access policies (usage of Authorization Api).
Tip
In development, you can get an access token and use this page to decode and see the token's content.
JWT.IO
I hope this helps.
I also had a 403 - Access Denied. What helped was stepping through the auth code of keycloak-connect. The token validation happens in the function validateToken in node_modules\keycloak-connect\middleware\auth-utils\grant-manager.js
if (!token) {
reject(new Error('invalid token (missing)'))
} else if (token.isExpired()) {
reject(new Error('invalid token (expired)'))
} else if (!token.signed) {
reject(new Error('invalid token (not signed)'))
} else if (token.content.typ !== expectedType) {
reject(new Error('invalid token (wrong type)'))
} else if (token.content.iat < this.notBefore) {
reject(new Error('invalid token (stale token)'))
} else if (token.content.iss !== this.realmUrl) {
reject(new Error('invalid token (wrong ISS)'))
}
...
For me, the problem was that I configured the url to the keycloak server without the schema (https). token.content.iss includes the schema and so it rejected because of token.content.iss !== this.realmUrl.
Unfortunately they seem to swallow those valuable Error messages without logging or returning them. I opened a question regarding this behavior.

Connect to mLab mongoDB database using nodeJS Strapi

I just got started using strapi framework and I would like to use mLab as my mongoDB database, so I go to configure strapi and fill the following details:
{
"defaultConnection": "default",
"connections": {
"default": {
"connector": "strapi-mongoose",
"settings": {
"client": "mongo",
"host": "localhost",
"port": 27017,
"database": "development",
"username": "",
"password": ""
},
"options": {}
}
}
}
The details I get from mLab are:
mongodb://myUsername:myPassword#ds047891.mlab.com:41365/myDatabase
Here is my final config:
{
"defaultConnection": "default",
"connections": {
"default": {
"connector": "strapi-mongoose",
"settings": {
"client": "mongo",
"host": "ds047891.mlab.com",
"port": 41365,
"database": "myDatabase",
"username": "myUsername",
"password": "myPassword"
},
"options": {}
}
}
}
When I try to start strapi, I get the following error:
DEBUG (2748 on DESKTOP-HAL1ATE): Server wasn't able to start properly.
ERROR (2748 on DESKTOP-HAL1ATE): (hook:mongoose) takes too long to load
I think that I did not setup my configuration right, but I can't pinpoint where the problem is. I hope someone could, thanks.
I am Pierre, on of the creators of Strapi. I tried with the following configuration and it worked well:
{
"defaultConnection": "default",
"connections": {
"default": {
"connector": "strapi-mongoose",
"settings": {
"client": "mongo",
"host": "ds135777.mlab.com",
"port": "35777",
"database": "myDatabase",
"username": "myUsername",
"password": "myPassword"
},
"options": {}
}
}
}
Our configurations files look quiet similar.
What file did you updated (/config/environment/development/database.json or /config/environment/production/database.json)?
Are you sure you entered the correct username and password? Did you try to login to your MongoDB instance through the command line mongo ds135777.mlab.com:35777/myDatabase -u <dbuser> -p <dbpassword>?
UPDATE
In version >= 3 for mlab don't forget to specify authenticationDatabase
"options": {
"authenticationDatabase": "your_mlad_database_name",
"ssl": false
}

Loopback Login a user with REST as datasource

I have a UserModel that has a base model USER and a REST datasource
"UserModel": { "dataSource": "mock", "public": true }
Data Source
"mock": { "name": "mock", "baseURL": "http://localhost:3000/", "connector": "rest" },
The UserModel
{ "name": "UserModel", "base": "User", "idInjection": true, "options": { "validateUpsert": true }, "properties": {}, "validations": [], "relations": {}, "acls": [], "methods": {} }
The problem when I call /UserModel/login with a post and a body like
{"username": "test", "password": "123"}
in the mock server I only get a call without even the password to:
/UserModels?where%5Busername%5D=test&limit=1&offset=0&skip=0
I want to handle the login through REST and a backend that receives the Username and password check for them and return 200 or 401
Try defining the login endpoint in datasources.json using a POST method
"operations": [{
"template": {
"method": "POST",
"url": "http://localhost:3000/MockedUsers??",
"headers": {
"accepts": "application/json",
"content-type": "application/json"
},
"query": {
"username": "{username}",
"password": "{password}"
},
}
}]
Haven't tested it though, let me know if it's helpful. Documentation could be more clear on this topic IMO.
Finally got the issue. It was a misunderstanding.
Loopback tries to log in on his own so he needs the user model so in his tier it can hash the input password and try to assert the two data.
So it needs to get the user as it did.

Configure node.js chat

I am trying to install and run this node.js chat: https://github.com/dual3nigma/Mejorando.la-Chat.
When I type "npm install" and "node server" it starts, but with an Express error. I think the reason is in the config.json file.
This is my config.json file. I've only changed the db name and port of the config.sample.json file and added my twitter / facebook keys:
{
"port": 721,
"host": "localhost",
"db": {
"name": "V1chatCCI"
},
"twitter": {
"consumerKey": "XXXXXXXXXXXXXXXXXXXXXXXXXX",
"consumerSecret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
},
"facebook": {
"appId": "XXXXXXXXXXXXXXXXXXXXXXXX",
"appSecret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
},
"session": {
"secret": "",
"key": ""
},
"cookie": {
"secret": ""
},
"secure": false,
"loginsecure": false,
"key": "",
"cert": "",
"sentry": "dsn"
}
What do I need to put in the session secret/key section? The error on localhost:721 is:
Express
500 Error: secret option required for sessions
You should be able to put anything in those sections, as they're used used internally by express handling sessions. Any values (even just random strings) should fix your problem.

Resources