Skip to content

Authentication guards

Danny SMc edited this page May 13, 2021 · 5 revisions

Authentication Guards

An authentication guard is used to create authentication for your platform, and is based on the Symfony's security package. The idea is that you create guards that can be used to authenticate a user, but allow you to define many guards, so one could be to authenticate a user via API tokens, think other applications, or using login and password, from a front-end. Each guard manages it's own state.

There is a default guard that is included which is the AbstractGuard, see the documentation on how to use this, this actually logs the different states of what is called. We suggest you either extend the AbstractGuard or implement the IGuard interface to make sure you write the correct code.

NOTE: All methods are fully commented in the code if you are more interested to read code.

Remember that if no default guard is available, and all guards fail to respond, then a user could access the platform without authentication, so we suggest for production you always have a default guard, even if that guard just triggers the onAuthenticationFailed method to stop users from getting access.



Create Guard

import { Guard, AbstractGuard, IGuard } from 'rewyre';

// The guard takes the guard name, and then whether it is the default guard.
@Guard('default', true)
export class FormLoginGuard extends AbstractGuard implements IGuard {}



Guard Methods

The below defines the methods in each guard, the required parameters and then response.


Method: supports(request: Request): Promise<boolean>

The supports method will be called on every request to the API, this will take the request and check for available information from the raw request object from Express, and if it can find the right information, then it will return true or false, depending on whether that guard supports that request. Example could be if you are using login and password authentication, then checking if that request is a POST request to a /login path with the username and password data given.


Method: getCredentials(request: Request): Promise<any>

This method is used to actually get the data from the request, this is where you actually aggregate the data to be given to the next step, we suggest this is where you do more, as remember the supports function is called every request, where as this request is only called if the supports function suceeeds.


Method: getUser(credentials: any): Promise<any>

This method is called after the getCredentials function and is passed the result of that method, this function should be where you attempt to call your user class or the place in which you want to verify an account to the given credentials, but do not do any validation in here, that is done in the next step, this should only return the object. You can return false, to trigger the onAuthenticationFailed method.


Method: checkCredentials(request: Request, credentials: any, user: any): Promise<boolean>

This method is called after getUser and passed all the data, here you should do all of the verification of a user, to checking passwords, or API tokens, and validating the user. Depending on the outcome you should respond with true or false, of course responding false will call onAuthenticationFailed and returning true will call the onAuthenticationSuccess method.


Method: onAuthenticationFailed(request: Request, credentials: any, user?: any): Promise<void>

This method is called when either the getUser or checkCredentials methods fail, and therefore you will have access to the request, the credentials and a user if you got that far in the authentication flow. Here you can log any errors, by default we will respond with a 401 Unauthorised automatically, but this allows you to collect the data and log it, by default the Logger module is included in the AbstractGuard class.


Method: onAuthenticationSuccess(request: Request, credentials: any, user: any): Promise<void>

This method is called when everything returns correctly and no errors are found, by default the application will execute this function, but keep on processing, and therefore this function is simply to add logging, add audit logs or any clean-up you need to do. The user object is stored against the context object that is given to every controller, so you can access the output of that (if logged in and passed a authentication guard) in the authentication property of the context object, see demo below.



Access User (After Authentication) - Example

import { Controller, AbstractController, Route, IContext, IReturn } from 'rewyre';

@Controller('/test', 'test')
export class MyController extends AbstractController {

	@Route('GET', '/foo')
	public example_method(context: IContext): Promise<IReturn> {
		console.log(context.authentication);
	}
}