How can I validate a user exists in the kuzzle database given only <kuid> and a <jwt> of that user? - node.js

I am using kuzzle (2.6) as a backend to my app. I'd like to encrypt data stored to Kuzzle by the users of the app, and organize encryption keys separate from the database. The key holding entity (keyStore for short) should give keys only to users that are truly registered in the database, without becoming able to access the user data itself.
So I'm trying to pass, from the app, when the user is logged in, a <kuid> together with a corresponding <jwt> obtained e.g. via kuzzle.auth.login('local', {username: <username>, password: <password>}) to the keyStore via https. The keyStore should send the information to the Kuzzle database, where a Kuzzle plugin can verify the user exists. If Kuzzle confirms the identity of the user to the keyStore, the keyStore will hand out a key to the user such that the user can encrypt/decrypt its data.
In short:
Is there any way I can let a plugin validate that a given <jwt> and a given <kuid> belong to the same user? <username> and <password> would both not be available to the plugin.

Kuzzle core developer here.
Right now we don't have a public API to get the user linked to an authentication token.
Still, you can use the auth:checkToken API action to verify the token validity and the jsonwebtoken package used by Kuzzle to retrieve the user kuid from the token.
const { valid } = await app.sdk.auth.checkToken(token);
if (valid) {
const kuid = require('jsonwebtoken').decode(token)._id;
}
Anyway, that's an interesting feature and we will discuss it in our next product workshop.
I will update this answer accordingly.

Related

Method Creating custom tokens will create uid if not exist in firebase

I using firebase. I using method: Creating custom tokens. When i look document in firebase https://cloud.google.com/identity-platform/docs/admin/create-custom-tokens .
const uid = 'some-uid';
admin
.auth()
.createCustomToken(uid)
.then((customToken) => {
// Send token back to client
})
.catch((error) => {
console.log('Error creating custom token:', error);
});
I have a question
If i don't have uid in firebase, it will create it ? If i have uid, i only create custom token and send back to client. I look document and i don't see document specific it. Thanks
There is no need to make an API call to create a user in Firebase when you're using custom authentication. Calling createCustomToken on the server, and then signing on the client with the resulting ID token, is all that is needed.
There is no separate step to create the UID for a custom provider. You create the custom token with the UID and other claims you want, send it to the client over a secure connection, and the client can then sign in to Firebase with that token.
For Firebase services the ID token, and the UID in it, are ephemeral - since it is your server (where you run the Admin SDK), and the client that maintain them. That's the reason a separate step to create the UID in Firebase is not necessary.

Generate unique api keys for user in node js application for access to your apis

how to generate API Keys for the user of your nodejs application on the basis of different parameters of the user in the database for giving access to our server endpoints.
You can use randomUUID which is part of node's crypto module. Then you can take the generated uuid, hash it using bcrypt and store it in db.
const saltRounds = 10;
const token = crypto.randomUUID();
const hashedToken = await bcrypt.hash(token, saltRounds);
And in subsequent requests, you can validate it like so:
const token = req.body.token // this is an example
bcrypt.compare(token, hashedToken, function(err, result) {
// result == true
});
You can also store the creation date and use it to invalidate tokens if they've passed certain time.
Hashing the token protects it in case a malicious use was able to access the database. Combined with time
and scope restrictions you have a pretty solid solution.
When we talk about generating API keys, I always preferred to use uuid or crypto library.
To securing your keys, encrypt the keys before saving them into the database.
To encrypt the keys, you can use Google's Key Management Service (KMS) and JWT but I will prefer to use KMS.
You can use different parameters to generate an API key and store it in the database for different users.
Example :
You have the username and email of the user in the database.
Add Both Of them to make a new string and store it in a variable
Then convert it to Base64 and store it in your database in apiKey column of the user.
Code
data = req.body.email+req.body.username;
let apiKey = Buffer.from(data).toString('base64')
Update your database column of that user with this API Key which the user can use to access to your server endpoints.

JWT authentication with two different services

We have a service architecture that currently only supports client authentication. A Java service based on spring boot and spring security issues long lived JWT based on tenants for other services to authenticate against each other. For example a render service needs to get templates from the template service.
We now want to build a user service with node.js that issues short lived tokens for users to also access some of those services and only access the resource visible to the user. For example the user wants to see only their templates in a list.
My question is: what do I need to watch out for when implementing the /auth resource on the user service? I have managed to issue a JWT with the required information and obviously the same secret in the user service to access the template service. But I'm not sure if it is secure enough. I had to add a random JID to the user JWT to get it accepted by the template service (which is also implemented with spring boot).
Is there a security issue I need to watch out for? Is this approach naiive?
This is my javascript code that issues the JWT:
const jwt = require('jwt-simple');
const secret = require('../config').jwtSecret;
const jti = require('../config').jti;
// payload contains userId and roles the user has
const encode = ({ payload, expiresInMinutes, tenantId}) => {
const now = new Date();
payload.jti = jti; // this is a UUID - spring security will otherwise not accept the JWT
payload.client_id = tenantId; // this is required by the template service which supports tenants identified through their clientId
const expiresAt = new Date(now.getTime() + expiresInMinutes * 60000);
payload.expiresAt = expiresAt;
return jwt.encode(payload, secret);
};
I think of adding some type information to the user JWT so that those java services that do not allow any User access can directly deny access for all user JWTs. Or maybe I can use the JTI here? Will research how spring boot handles that. I'll probably also have to add #Secured with a role distinction to all the services that allow user access to only some resources.
But those are technical details. My concern really is that I am unsure about wether the entire concept of using JWTs issued from different sources is secure enough or what I have to do in the user service to make it so.
Yeah your concept is right since you are the owner of jwt that means only you can write the jwt, others can read it but can not modify it.
So your userservice will create the token with certain information like userid and another service will decode that jwt fetch userid and validate that userid

How to authenticate hyperledger user from webportal?

I can successfully run the fabrics example to query/insert to ledger.
I want to build a nodejs web portal and I already directly wrapped query.js in my web app code.
Now the question is, how to authenticate a user the webportal? Since the example query.js has code like:
...
return fabric_client.getUserContext('user1', true);
}).then((user_from_store) => {
if (user_from_store && user_from_store.isEnrolled())
//successfully authenticated user1
I noticed the cert/private key/pub key files in
/hfc-key-store
user1-cert
user1-private.key
user1-public.key
Do I need to post any of the keys through parameters or do I create a separate regular username password control?
In my opinion you can create a normal login system for the web portal using a database to store the credentials of the users.
In this database you can associate the user to a specific key, which is retrieved each time the user successfully login in the web portal.
In this way, you will have two different levels of authentication:
one associated to the web portal (username and password)
and the other one associated to the blockchain (the certificate to
write and read).

Azure App Service Easy Auth

I have an Azure mobile backend set up with easy auth for facebook and google authentication and it works as expected.
Every time a user signs in with any of the supported providers, I want to be able to verify if it's a new user or not (e-mail not in database), without make an additional call from client. Is this possible?
Every time a user signs in with any of the supported providers, I want to be able to verify if it's a new user or not (e-mail not in database), without make an additional call from client. Is this possible?
As far as I know, we couldn't directly verify if it's a new user or not.
No matter you use server flow or client flow, easy auth will just return access token for the client to access the mobile backend resources, it will not check the user is new or old.
If you want to achieve this requirement, you need write your own logic.
You could write codes after the user login successfully.
For example, facebook login.
If you the use have login successfully,you could call GetAppServiceIdentityAsync extension method to get the login credentials, which include the access token needed to make requests against the Facebook Graph API.
// Get the credentials for the logged-in user.
var credentials =
await this.User
.GetAppServiceIdentityAsync<FacebookCredentials>(this.Request);
if (credentials.Provider == "Facebook")
{
// Create a query string with the Facebook access token.
var fbRequestUrl = "https://graph.facebook.com/me/feed?access_token="
+ credentials.AccessToken;
// Create an HttpClient request.
var client = new System.Net.Http.HttpClient();
// Request the current user info from Facebook.
var resp = await client.GetAsync(fbRequestUrl);
resp.EnsureSuccessStatusCode();
// Do something here with the Facebook user information.
var fbInfo = await resp.Content.ReadAsStringAsync();
}
Then you could check the database according to the user information.
More details about how to get user information in server side, you could refer to How to: Retrieve authenticated user information.

Resources