Skip to main content

Auth

This service allows you to authenticate users with an OIDC or CAS server, or with a local account.

Features​

  • Handle OIDC, CAS or local authentication in a single package
  • Integrate easily with Moleculer's ApiGateway

Dependencies​

Sub-services​

  • AuthAccountService
  • AuthJWTService
  • AuthMailService

Install​

$ yarn add @semapps/auth

Usage​

Local accounts​

const { AuthLocalService } = require('@semapps/auth');
const path = require('path');

module.exports = {
mixins: [AuthLocalService],
settings: {
baseUrl: 'http://localhost:3000',
// Path where the JWT keypair will be saved
jwtPath: path.resolve(__dirname, '../jwt'),
// Usernames you don't want users to signup with
reservedUsernames: [],
// User data you want to be available in the webId
webIdSelection: [],
// If false, user account must be created manually with a foaf:email field. True by default.
registrationAllowed: true,
// Dataset where the account data will be stored (email, hashed password...)
accountsDataset: 'settings',
// If true, a capabilities service is created and capabilities auth is enabled
podProvider: false
}
};

OIDC​

const { AuthOIDCService } = require('@semapps/auth');
const path = require('path');

module.exports = {
mixins: [AuthOIDCService],
settings: {
// See above for the descriptions
baseUrl: 'http://localhost:3000',
jwtPath: path.resolve(__dirname, '../jwt'),
reservedUsernames: [],
webIdSelection: [],
registrationAllowed: true,
// OIDC-specific settings
issuer: 'https://myissuer.com/auth/realms/master',
clientId: 'myClientId',
clientSecret: 'myClientSecret',
// Return data for the creation of the webId profile (FOAF Person).
// Available fields: uuid, nick, name, familyName, email, homepage
selectSsoData: authData => ({
email: authData.email,
name: authData.given_name,
familyName: authData.family_name
}),
// Dataset where the account data will be stored (email)
accountsDataset: 'settings',
// If true, a capabilities service is created and capabilities auth is enabled
podProvider: false
}
};

CAS​

const { AuthCasService } = require('@semapps/auth');
const path = require('path');

module.exports = {
mixins: [AuthCasService],
settings: {
// See above for the descriptions
baseUrl: 'http://localhost:3000',
jwtPath: path.resolve(__dirname, '../jwt'),
reservedUsernames: [],
webIdSelection: [],
registrationAllowed: true,
// CAS-specific settings
casUrl: 'https://my-cas-server.com/cas',
// Return data for the creation of the webId profile (FOAF Person).
// Available fields: uuid, nick, name, familyName, email, homepage
selectSsoData: authData => ({
email: authData.email,
name: authData.given_name,
familyName: authData.family_name
}),
// Dataset where the account data will be stored (email)
accountsDataset: 'settings',
// If true, a capabilities service is created and capabilities auth is enabled
podProvider: false
}
};

API routes protection​

To protect the different routes, you will need to configure the authenticate and authorize methods of the ApiGatewayService to call AuthService's respective actions.

const { ApiGatewayService } = require('moleculer-web');

module.exports = {
mixins: [ApiGatewayService],
methods: {
authenticate(ctx, route, req, res) {
return ctx.call('auth.authenticate', { route, req, res });
},
authorize(ctx, route, req, res) {
return ctx.call('auth.authorize', { route, req, res });
}
}
};

For more information, please see the official Moleculer documentation about authorization and authentication.

You can enable authorization of routes based on capabilities. For more details, see the documentation on Verifiable Credentials

It is important that you do not put the AuthService as a dependency of the ApiGatewayService, because the ApiGatewayService is a dependency of AuthService, and you will get a circular dependencies loop.

Client login​

From the frontend, redirect the user to this URL:

http://localhost:3000/auth/?redirectUrl=...

After login, the user will be redirected to the provided redirectUrl, and to this URL will be added the JWT token as a query string. You should store it and remove it like this:

const url = new URL(window.location);
if (url.searchParams.has('token')) {
localStorage.setItem('token', url.searchParams.get('token'));
url.searchParams.delete('token');
window.location.href = url.toString();
}

Client logout​

From the frontend, redirect the user to this URL:

http://localhost:3000/auth/logout?redirectUrl=...

If you wish to logout the user remotely (on the SSO), you can do:

http://localhost:3000/auth/logout?global=true&redirectUrl...

Actions​

The following service actions are available:

impersonate​

Generate a JWT token for a given user.

Parameters​
PropertyTypeDefaultDescription
webIdStringrequiredURI of the user to impersonate
Return​

A JWT token you can use in your app.

Events​

auth.registered​

Sent when a new user registers.

Payload​
PropertyTypeDescription
webIdStringURI of the user
profileDataObjectUser's data

auth.connected​

Sent when an user logins.

Payload​
PropertyTypeDescription
webIdStringURI of the user