This directory contains providers contributing additional bindings, for example custom sequence actions.
A provider
is a class that provides a value()
function. This function is called Context
when another entity requests a value to be injected.
These are the optional bindings that can be used to extend the functionality of this service.
This provides a function that is used to verify the Bearer Token for endpoints using the Bearer Token authentication.
Implementation for this can be seen here;
This provides a function that can process the authorization code (used in KeyCloak and Google Oauth authentications) before being verified. This can be used to decrypt a code or to retrieve it from Cache/Redis.
Sample implementation -
export class CodeReaderProvider
implements Provider<CodeReaderFn> {
constructor(
@repository(CodeRepository)
private readonly codeRepo: CodeRepository
) { }
value(): CodeReaderFn {
return async (token) => {
let codeModel = await this.codeRepo.get(token);
if (!codeModel?.code) {
return token;
}
await this.codeRepo.delete(token);
return codeModel.code
}
}
}
Here CodeRepository
is a Redis Repository, implementation for such a key pair repository can be seen here.
This provides a function that can process the authorization code before it is passed to the client, it can be used to store the token in a cache and pass only a key, or to encrypt the token.
Sample implementation -
export class CodeWriterProvider
implements Provider<CodeWriterFn> {
constructor(
@repository(CodeRepository)
private readonly codeRepo: CodeRepository
) { }
value(): CodeWriterFn {
return async (token) => {
let key = uuidv4();
await this.codeRepo.set(key, {code: token});
return key;
}
}
}
Here CodeRepository
is a Redis Repository, implementation for such a key pair repository can be seen here.
uuidv4
is function to from this.
This provides a function that creates the object stored in the JWT token for signup requests.
Sample implementation for this can be seen here
This provides a function that gets the data from the signup token and is responsible for performing all tasks required to signup a user. You can also find an implementation of this provider in auth-basic-example.
Sample implementation -
export class LocalSignupProvider
implements
Provider<UserSignupFn<UserSignupDto, {userId: string | undefined}>> {
constructor(
@service(UserService)
private readonly userService: UserService,
) {}
value(): UserSignupFn<UserSignupDto, {userId: string | undefined}> {
return async (model: UserSignupDto, tokenInfo?: AnyObject) => {
if (!model.userData) {
throw new HttpErrors.BadRequest('userData missing');
}
if (tokenInfo?.email && model.email === tokenInfo.email) {
await this.userService.updateUser(model.userData, model.email);
} else {
throw new HttpErrors.BadRequest('Invalid Email');
}
};
}
}
The provider for this key is used to verify a signup token generated by the signup endpoint.
this.bind(VerifyBindings.BEARER_SIGNUP_VERIFY_PROVIDER).toProvider(
SignupBearerVerifyProvider,
);
export class SignupBearerVerifyProvider
implements Provider<VerifyFunction.BearerFn<UserInviteDto>> {
constructor(
) {}
value(): VerifyFunction.BearerFn<UserInviteDto> {
return async (token: string) => {
let result: UserInviteDto;
try {
result = verify(token, process.env.JWT_SECRET as string, {
issuer: process.env.JWT_ISSUER,
}) as UserInviteDto;
} catch (error) {
throw new HttpErrors.Unauthorized('TokenExpired');
}
if (await this.userOpsService.checkUserSignedUp(result.email)) {
throw new HttpErrors.Forbidden('TokenAlreadyUsed');
}
return result;
};
}
}
You can check out the following resource to learn more about providers, components, sequences, and binding keys.