Auth Module
The Auth Module is a combination of an HTTP middleware (compatible with express and restify) and a Typescript decorator.
Used together, they allow to protect all the routes of your application, handling user authentication and authorizations.
Disclaimer
You can find the full list of changes in the CHANGELOG.md
but the TLDR is that +2.0.0 of this lib requires node>=14.18
.
How to use
Add the AuthModule middleware
You first have to load the AuthModule middleware to protect all your application's routes.
Example usage:
import { Server } from 'restify';
import { AuthModule } from '@ssense/auth';
const server = restify.createServer();
const authModule = new AuthModule({
authServerHost: 'test.ssense.com',
authServerSecure: false,
publicRoutes: [
/^\/+$/,
/^(\/robots\.txt|\/favicon\.ico)$/,
],
publicHttpMethods: [
'DELETE',
],
onForbidden: (req, res, next) => {
res.send('You are not allowed to access this page');
next();
},
});
server.use(authModule.authenticate());
Just by adding this middleware, all your application's routes will be protected from anonymous requests (a valid ssense.com email address is required).
The user's authentication is also fully managed, you can focus on your business case without having to take care about authentication.
Retrieving user's information at the controller level
After loading the AuthModule middleware, all the controllers of your application will have an extra auth
param in the request
object.
This param is an instanceof of AuthInfo
, giving the currently logged in user's information, as follows:
interface AuthInfo {
id: string;
type: string;
scopes: string[];
token: string;
hasScope(scope: string): boolean;
hasScopes(scopes: string[]): boolean;
}
Let's take an example:
public async myControllerFunction(req, res, next): Promise<any> {
res.send('You are currently logged in as ' + req.auth.id + ', you are logged in as a ' + req.auth.type + ' account');
res.end();
}
Automatically protect controller functions based on current user's scopes
You can automatically protect your controller's function by allowing access only to users that have the appropriate scopes.
To enable this feature, you can use the requireScope()
typescript decorator, as in the example below:
import { AuthModule } from '@ssense/auth';
@AuthModule.requireScope('scope1')
public async myControllerFunction(req, res, next): Promise<any> {
res.send('You are currently logged in as ' + req.auth.id + ' and you have at least one required scope to access this function');
res.end();
}
Using the @AuthModule.requireScope('scope1')
line, logged in users need to have the specififed scope to access your function.
You can also allow access to a function for several scopes, using @AuthModule.requireScope(['scope1', 'scope2'])
, in this case the authenticated user needs to have at least one of the scopes passed in parameter to be able to access this function.
If they don't have any of the possible scopes, they will get a 403 error page, the response will automatically be sent and your function will not even be called.
If you want to check for several scopes, you can use the @AuthModule.requireAllScopes()
decorator, which takes a string[] as parameter.
In this case the authenticated user needs to have all of the scopes passed in parameter to be able to access this function.
Alternatively, you can use the same functionality as a middleware:
import { AuthModule } from '@ssense/auth';
@Get('/something', AuthModule.scopeMiddleware(['resources:operation']))
public async myControllerFunction(req, res, next): Promise<any> {
}
The scopeMiddleware
function have an optional 2nd parameter where true
is "all of the scopes" and false
is "at least one of the scopes". default to true
This has the advantage to be usable on the controller level:
import { AuthModule } from '@ssense/auth';
@injectable()
@Controller('/somethings', AuthModule.scopeMiddleware(['resources:operation'])
export class SomeController extends BaseController {
}
And can be chainable :
import { AuthModule } from '@ssense/auth';
@Get('/something')
public async getSomething(req: Request, res: Response, next: Next): Promise<void> {
if(req.query.something){
AuthModule.scopeMiddleware(['resources:operation'])(req,res,next)
}
next()
}