This library contains a reusable module (AuthModule) with guards that can be used to protect other REST controllers and GraphQL resolvers.
There are a couple of guards available.
IdsUserGuard
: validates that the request has a valid JWT bearer authorization from our identity server and checks that it has a nationalId claim, representing an authenticated user. Information from the JWT can be accessed using the CurrentAuth and CurrentUser parameter decorators.IdsAuthGuard
: same asIdsUserGuard
but does not verify thenationalId
claim. Information from the JWT can be accessed using the CurrentAuth parameter decorator.ScopesGuard
: checks if the access token has required scopes. These can be configured using the Scopes decorator.
You should generally add IdsUserGuard
to endpoints that return user resources for the authenticated user and IdsAuthGuard
for endpoints that need to be available for clients authenticating with client credentials. You should always use ScopesGuard
and the @Scopes
decorator to protect endpoints, without it the API would authorise all valid access tokens issued by IAS.
Import and configure the AuthModule, example:
@Module({
imports: [
AuthModule.register({
issuer: 'https://localhost:6001'
}),
where issuer
is the IdS url.
Some older APIs use audience
for access control.Using audience
is no longer recommended, instead use scopes to guard individual methods as shown in the sections below. Only use audience
after consulting with the IDS team, in which case you can do it like this:
@Module({
imports: [
AuthModule.register({
issuer: 'https://localhost:6001'
audience: '@island.is'
}),
Decorate the controller with @UseGuards
:
@UseGuards(IdsUserGuard, ScopesGuard)
@Controller('clients')
export class ClientsController {
and individual protected methods with @Scopes
:
@Scopes('protected_resource/read', 'protected_resource/admin')
@Get(':id')
@ApiOkResponse({ type: Client })
async findOne(@Param('id') id: string): Promise<Client> {
// ...
}
If no @Scopes
are applied to a method, then no access control is enforced for that method.
Information about the logged in user can be obtained by adding @CurrentUser() user: User
as an input parameter to the controller method.
Decorate the resolver with @UseGuards
:
@UseGuards(IdsUserGuard, ScopesGuard)
@Resolver()
export class UserProfileResolver {
and individual protected methods with @Scopes
:
@Scopes('userProfileScope')
@Query(() => UserProfile, { nullable: true })
async getUserProfile(@CurrentUser user: User) {
// ... user.nationalId
}
If no @Scopes
are applied to a method, then no access control is enforced for that method.
Information about the logged in user can be obtained by adding @CurrentUser() user: User
as an input parameter to the resolver method.
If a small subsection of your controller or app has public endpoints you can explicitly opt out of auth for those sections.
Decorate the resolver or controller with @BypassAuth
:
@BypassAuth()
@Controller('clients')
export class ClientsController {