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); | |
} | |
}), | |
); |
@ferrerojosh did you make it work?
@ferrerojosh did you make it work?
I made a library for it.
@ferrerojosh does it work with GraphQL?
@ferrerojosh does it work with GraphQL?
It should, some guy made a PR for it.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Passport is an authentication middleware, this gist if for keycloak authorization, they are two different things.
If you are using Keycloak and want to use the
@nestjs/passport
authentication guard, you can use the following package: https://www.npmjs.com/package/passport-keycloak-bearerAnd implement the passport strategy:
If you want to use the library you referenced, you could also do that:
Then just call
AuthGuard('keycloak')
in Nest and you're good to go.P.S I use
passport-keycloak-bearer
for authentication in my Nest app but not for keycloak resource authorization which this gist is about.You should be using keycloak-js in your Angular application (I use it too) if you want PKCE flow.
Also the Angular and Nest app should be two different clients in Keycloak, they can't be the same.