@dan.woda
CONTEXT:
Iām using @auth0/auth0-spa-js
.
As I said before, the Webstask logs on the rule only
RULES:
Here are my rules:
CODE OF THE RULES:
- Rule āSet default role to a user on first loginā
async function setDefaultRoleToUser(user, context, callback) {
// Only we add the role 'agent' if user is sign up.
let count = context.stats && context.stats.loginsCount ? context.stats.loginsCount : 0;
if (count > 1) return callback(null, user, context);
try {
const ManagementClient = require('auth0@2.19.0').ManagementClient;
var management = new ManagementClient({
domain: auth0.domain,
// User API
clientId: '...',
clientSecret: '...',
scope: 'read:roles update:users'
});
// https://github.com/auth0/node-auth0/blob/master/src/management/index.js#L2692
let roles = await management.getRoles();
// If user hasn't the that role yet, we want to prevent to call the Management API if the rule is called multiple times during the first login (loginsCount = 1).
if (roles.some(el => el === 'agent') === false) {
let roleId = roles.find(({name}) => name === 'agent').id;
await management.assignRolestoUser({id: user.user_id}, {roles: [roleId]});
// We have to add the role added to context for the next rules after this.
if (context.authorization.roles) {
// Only add the default role on the authorization if it doesn't exist.
if (context.authorization.roles.some(el => el === 'agent') === false){
context.authorization.roles.push('agent');
}
return callback(null, user, context);
}
else context.authorization.roles = ['agent'];
console.log(`setDefaultRoleToUser - User ${user.user_id} has the new role 'agent'`);
}
} catch(err) {
console.error(err);
}
}
- Rule āAdd user roles on id and access tokenā
/**
* Documentation:
* - https://auth0.com/docs/authorization/concepts/sample-use-cases-rules#add-user-roles-to-tokens
* - https://auth0.com/docs/api-auth/tutorials/adoption/scope-custom-claims
*/
function addRolesOnTokens(user, context, callback) {
// Namespace constraints: https://auth0.com/docs/api-auth/tutorials/adoption/scope-custom-claims#custom-claims
const namespace = 'https://guillemau-dev.com';
console.log("addRolesOnTokens - context.authorization", context.authorization);
const assignedRoles = (context.authorization || {}).roles;
let idTokenClaims = context.idToken || {};
let accessTokenClaims = context.accessToken || {};
idTokenClaims[`${namespace}/user/roles`] = assignedRoles;
accessTokenClaims[`${namespace}/user/roles`] = assignedRoles;
context.idToken = idTokenClaims;
context.accessToken = accessTokenClaims;
callback(null, user, context);
}
- Rule āSave new user on external dbā. Iām using custom claims (set before by other rule) for the condition. Itās not optimal condition, but it seems is working.
/**
* Register the user on the external database only continue if he signs up for the first time. Else, exit the rule.
*
* IMPORTANT: the rule will be skipped if the authorization hasn't any role assigned.
*/
async function saveUserOnExternalDatabase(user, context, cb) {
//if (context.stats.loginsCount > 1 || context.protocol === 'oauth2-refresh-token' || context.request.query.prompt === 'none')
//if (context.stats.loginsCount > 1 || context.protocol !== 'oidc-basic-profile' || context.request.query.prompt === 'none')
if (context.stats.loginsCount > 1 || context.authorization.roles.length >= 1)
return cb(null, user, context);
console.log("saveUserOnExternalDatabase - Saving user on external db...");
try {
const axios = require('axios');
await axios.post('https://guillemau-dev.ngrok.io/user/create', {
name: {
displayName: user.given_name || user.name
},
emails: {
auth: user.email
},
roles: context.authorization.roles,
auth: {
auth0Id: user.user_id
}
}, {
headers: {Authorization: `Bearer ${context.accessToken}`}
});
console.log(`saveUserOnExternalDatabase - User ${user.user_id} has been saved on an external db.`);
return cb(null, user, context);
} catch(err) {
console.error(err);
return cb(new UnauthorizedError('Not able to save the user correctly.'), user, context);
}
}
PROBLEMS:
- The conditions on the first two rules are
if (count > 1)
arenāt very optimal because when context.stats.loginsCount == 1
, the rules are executing a lot of times because getting access token on the SPA (during the first login) is making them execute every time.
- The condition on the rule of save user on an external db isnāt working every time (neither your code Dan).
What condition has to be to execute one time and only when the user is signing up?