Open valerii15298 opened 1 year ago
Thanks for this suggestion, I will take a look and see if this could be a library to recommend.
@valerii15298 can you post a link to the code of the app you tested it in?
@m1212e sure, I used it in Nest.js app but I can easily give you StackBlitz example with express(or Nest.js), what do you prefer?
Express sounds good, but I thought it may be a public repo you were referring to. Whatever is less work for you <3
@m1212e I thought that simplest example would be easier to give here, since you cannot start keycloak in StackBlitz without docker-compose anyway...
So the simplest authorization would be like this:
import { createRemoteJWKSet, jwtVerify } from "jose";
import express, { Request } from "express";
const app = express();
const auth_server_url = "http://keycloak.localhost:8080";
const realmName = "master";
const jwks = createRemoteJWKSet(
new URL(
`${auth_server_url}/realms/${realmName}/protocol/openid-connect/certs`,
),
);
function extractTokenFromHeader(req: Request) {
const [type, token] = req.headers.authorization?.split(" ") ?? [];
return type === "Bearer" ? token : undefined;
}
app.use((req, res, next) => {
const token = extractTokenFromHeader(req);
if (!token) {
return res.status(401);
}
jwtVerify(token, jwks)
.then(({ payload }) => {
// @ts-ignore
req.authPayload = payload;
console.log({
userId: payload.sub,
useEmail: payload.email,
userRealmRoles: payload.realm_access.roles,
// and so on... simply check what is available in payload
});
next();
})
.catch(() => res.status(401));
});
May be is a dummy question but how is this implemented currently? Is the token checked in the Keycloak service?. I mean after a logout, for example. In this case I don't see any server side check so anyone with that "old"/"not valid" token could use the protected endpoint. Is it? I guess the bearer token from the frontend app should be checked against the server to ensure is not expired/revoked.
@dlaraf There are to ways to verify keycloak token: Online and Offline, both having their own tradeoffs and benefits.
Online validation is quite expensive, you will need to make requests to your keycloak server every time which could slow down your app, but it will always give you the most precise and valid result.
Offline validation on the other hand is less expensive but if the user logged out, the token will be valid in the remaining time(usually 5 minutes depending which configuration you chose for token to be valid for how long).
When using jose
the verification will be valid for most cases except cases like user logout for which jose will verify token without error(while token will be revoked already) until the end of its lifespan.
In the case of token expiration, jwtVerify
will throw an error always stating that token is expired which is correct behaviour, since expiration time is encoded in the token itself(so no need to make requests to the server).
And are you asking about implementation with jose
or about current implementation of keycloak-nodejs-connect
?
Hi @valerii15298!
Thank you for the clarification. Very helpful.
I was asking about the current verification in keycloak-nodejs-connect
. I guess offline method is the one used with the bearerOnly:true
and the other(online) is using the client_secret? If you wants to use both(frontend login with bearer token and check that token online on the API side(backend), you need two clients? one for bearer flow (frontend) and another one using secret code (backend)?
I'm trying to do a secure app with Keycloak so I was following this guide reactjs express rest api Keycloak . Another good example I've seen is this one that I guess uses the offline method as well with Passport Keycloak Nestjs React example
Thank you @valerii15298
@dlaraf You don't need two clients if you just want to verify the token that backend received from frontend. You can do a request on backend to keycloak realm endpoint where you get the public key (jwks endpoint), and with that you can verify the validity of the token.
Sorry if my question seems stupid, I'm new to this. Assuming that I'm using jose, should I check the role permissions using some custom code or is there a standardized way to do this? I was thinking of just checking whether the payload.realm_access.roles contains the necessary role to access a certain resource, but I'm unsure whether this is the correct way to go about it.
@dav-bisc
Hi,
Yes you can just check if the payload.realm_access.roles contains the necessary role. You can check the code from this library too, it's very simple.
Any news about the "official" potential replacement? 🤔
Alternatives recommended or hinted at by the Keycloak team are mentioned in Deprecation of Keycloak adapters.
Alternatives recommended or hinted at by the Keycloak team are mentioned in Deprecation of Keycloak adapters.
From the link you sent btw:
NodeJS We are still looking around for the best candidate for Node.js applications, but it looks like openid-client is a good alternative, that is a lot more feature rich than the Keycloak adapter.
We're currently working on orphaning the Node.js connect adapter from the main Keycloak release cycle, after which I will be starting the evaluation of alternative clients. Once one is selected that matches our expectations we will be writing guides, and quite likely quickstarts on how to use said library with Keycloak.
FYI the expectation here is that we will be dropping support for this library completely starting Keycloak 27. Since we are now supporting major versions of Keycloak for longer periods of time that is still a while away.
FYI the expectation here is that we will be dropping support for this library completely starting Keycloak 27. Since we are now supporting major versions of Keycloak for longer periods of time that is still a while away.
@jonkoops I would like to know why we are dropping support for node js. some context or background for not supporting node js will be appreciated.
Thanks.
Because Keycloak is based on standard protocols that have widely available implementations in various languages and frameworks, thus it makes no sense for the Keycloak team to maintain a library that is exclusively built for Keycloak. It's not that we don't want to support Node.js, it is simply that we don't want to maintain software that does not need to exist any longer.
Description
Since this library is deprecated I would like to propose one of the possible alternatives => jose It contains quite useful functions:
createRemoteJWKSet
andjwtVerify
as described here: https://github.com/panva/jose/blob/main/docs/functions/jwks_remote.createRemoteJWKSet.md#function-createremotejwksetExample verification with jose looks like this:
jose
automatically fetches public keys from endpoint if previous ones are not valid.Jose
library seems to cover significant part ofkeycloak-nodejs-connect
functionality. I already using it in my app and DX is even more enjoyable. I have more control and can create express middleware myself, or integrate it in any kind of app bcs it is not tightly coupled toexpressjs
.@jonkoops @abstractj I would really appreciate your review about using
jose
, seems like it can be recommended askeycloak-nodejs-connect
alternative or at least one of alternatives. In any case would be very helpful to hear your thoughts on it, whether you think it is good replacement or not. Tagging both of you since you guys seem to be active ones in this repo from maintainers.Btw, also, as I checked another library named
jose
is used under the hood in keycloak Java source code too.