Last active
July 10, 2023 20:03
-
-
Save ferrerojosh/653500646a0debf01548d315fe61a773 to your computer and use it in GitHub Desktop.
Keycloak v9.0.0 NestJS Resource Guard
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { FactoryProvider, Logger } from '@nestjs/common'; | |
import Keycloak from 'keycloak-connect'; | |
export const KEYCLOAK_INSTANCE = 'KEYCLOAK_INSTANCE'; | |
export const keycloakProvider: FactoryProvider = { | |
provide: KEYCLOAK_INSTANCE, | |
useFactory: () => { | |
const keycloakConfig: any = { | |
realm: '', | |
clientId: '', | |
secret: '', | |
authServerUrl: '', | |
}; | |
const keycloak: any = new Keycloak({}, keycloakConfig); | |
// We just need it to return next(false) so our guard will be able to latch on | |
keycloak.accessDenied = (req, res, next) => { | |
next(false); | |
}; | |
return keycloak; | |
} | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { SetMetadata } from '@nestjs/common'; | |
export const Permissions = (...permissions: string[]) => | |
SetMetadata('permissions', permissions); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
CanActivate, | |
ExecutionContext, | |
Inject, | |
Injectable, | |
Logger, | |
} from '@nestjs/common'; | |
import { Reflector } from '@nestjs/core'; | |
import KeycloakConnect from 'keycloak-connect'; | |
import { KEYCLOAK_INSTANCE } from './keycloak.provider'; | |
@Injectable() | |
export class ResourceGuard implements CanActivate { | |
constructor( | |
@Inject(KEYCLOAK_INSTANCE) | |
private keycloak: KeycloakConnect.Keycloak, | |
private readonly reflector: Reflector, | |
) {} | |
async canActivate(context: ExecutionContext): Promise<boolean> { | |
const permissions = this.reflector.get<string[]>( | |
'permissions', | |
context.getHandler(), | |
); | |
const [request, response] = [ | |
this.getRequest(context), | |
context.switchToHttp().getResponse(), | |
]; | |
const enforcerFn = createEnforcerContext(request, response); | |
return await enforcerFn(this.keycloak, permissions); | |
} | |
getRequest<T = any>(context: ExecutionContext): T { | |
return context.switchToHttp().getRequest(); | |
} | |
} | |
const createEnforcerContext = ( | |
request, | |
response, | |
) => (keycloak: KeycloakConnect.Keycloak, permissions: string[]) => | |
new Promise<boolean>((resolve, reject) => | |
keycloak.enforcer(permissions)(request, response, next => { | |
if (next !== undefined) { | |
resolve(false); | |
} else { | |
resolve(true); | |
} | |
}), | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@ferrerojosh does it work with GraphQL?