We are building an application where multiple clients can register and have their own user bases. For example a client "CompanyA" can register and then allow their users to access to our system with their own usernames (some from LDAP). "CompanyB" can also do the same, the usernames will be unique for one client but can be duplicated across clients.
We are using keycloak for this and have used the concept of realms to achieve this. When a new client registers we create a new realm for them and do the required configurations. This works as expected but we are having issues with our middleware.
Our middleware is Kong which has an OIDC plugin which we integrate with keycloak, however the plugin requires the realm name which in our case is actually going to be dynamic.
For example:
When a user signs in from our UI he receives a token from their client's realm. Now when a user requests a resource from our backend, this request will go through kong.
Kong will introspect this token using its configured client and realm, however this cannot be selected dynamically so ideally I would want to have a configured client on the master realm for each client realm and use this magic client to introspect their tokens.
Is something like this possibel? If not what other avenues can I look into?
You can inspect the Access Token to see from which realm it was created.
If you decode the JWT token with something like https://jwt.io/ you will see a property on the token called issuer. That is the url of the realm that created the token.
So to get the realm, you do something like this:
import org.keycloak.TokenVerifier;
import org.keycloak.representations.AccessToken;
...
AccessToken token = (AccessToken)TokenVerifier.create(tokenString,
AccessToken.class).parse().getToken();
String realm = token.getIssuer().substring(token.getIssuer().lastIndexOf(47) + 1);
Related
Is there a way of using Keycloak only to Authenticate user, but with own mapping to roles with Spring?
I would like to authenticate API Gateway in keycloak first, but then provide internal JWT Token with authorized roles inside my microservice world.
In this article, I do map Spring authorities from roles that Keycloak sets in JWTs. Is that what you are looking for?
If what you want is having a hand on access token claims, two cases:
the claim is already in the token but with a different value than what you expect (missing roles, outdated email, ...). Then, it is very likely that Keycloak admin API exposes what you need to update users data. Check that a "confidential" client with required roles is declared with client-credentials flow enabled (or declare a new one) and have relevent resource-server call admin API for updates (with WebClient, RestTemplate, #FeignClient or whatever is capable of using client-credentials flow).
the claim does not exist yet. Then, define a new Keycloak "mapper" to add a private claim. Here is a sample. You can have a look at security module to figure out how this new private claim is parsed (by ProxiesClaimSet) into an Authentication custom implementation.
In any case, the authorization-server (Keycloak) is the only place to define claims, issue JWT and sign it. JWT validation by JWT decoder on resource-server involves much more than just checking expiration date: issuer, issued-at, token integrity (server signs the payload with a private key and exposes a public one to ensure the token content was not modified), and more are verified too.
You want to make access control inside resource-servers? Great! Ensure that authorization header with Bearer access-token is forwarded by the gateway from client(s) to resource-server(s) and configure your resource-server(s) as described in the article above.
P.S.
In the article you'll also find a way to test security rules (both unit and integration) with mocked authentication. This is what, in my opnion, makes resource-server(s) a better place to implement access-control: security rules are of primary business importance and fine grained unit-testing is essential.
Other note, if you go for additional private claim(s) with Keycloak mapper(s), pay attention to pom.xml file, java/main/resources and implemented interfaces of ProxiesMapper into proxies-keycloak-mapper module.
Last, you should also follow the first 3 of those tutorials (for real: write the code and run the tests), it will take you less than an hour and will save you many more hours struggling with your resource-server(s) security implementation.
I have some questions regarding the Quarkus oidc extension for validating access to a service (not an oidc client, so I am not calling OIDC flows, only validating tokens):
In addition to validating the JWT access token (authorization bearer token), is it possible to validate the id token, defined in another header? (in my case x-id-token)
Would additional claims in the ID token be accessible somehow, for example through SecurityIdentity or something else?
I would like to avoid having to call the userInfo endpoint every time.
Also, in my case, the id token contains "groups", that I would have liked to be mapped to roles to be used in #RolesMapping: is this possible? In Microprofile JWT, for non-OpenID Connect cases, it seems like the groups claim is defined on the access token, but in OIDC from my interpretation, it seems logical that this kind of information is on the id token, isn't it?
I tried adding "quarkus.oidc.roles.source=idtoken" on my app, but this seems to be limited to oidc client applications.
Also, perhaps it's just me, but I am confused by the doc for OIDC for services (https://quarkus.io/guides/security-openid-connect), regarding what is client OIDC and what is server-side validation for services: this page seems to be focused on services, but then the configuration part references a lot of configuration properties that concern client applications that must call the OIDC endpoints, OIDC flows, etc. Am I missing / misunderstanding something?
(Note: otherwise the extension is great! And multi-tenancy is very useful…and is also the first reason why we initially preferred using this extension instead of the Quarkus Smallrye JWT)
Thank you.
I'm trying to validate (and read roles from) a JWT Token. Sadly I can't use any adapter or auto configuration due to my overall application architecture.
It's no problem to decode the token like any other JWT Token, but I wonder if there is a library from Keycloak to archive this goal. (For example Just Parse the token to something like a KeycloakJWTToken and verify it by grabbing the secret from Keycloak Server or so)
Any easy-to-use client or so?
I'm using the Jose4J library:
https://bitbucket.org/b_c/jose4j/wiki/Home
Reading the claims inside a JWT token is straightforward:
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
public void parseJWT(String token) throws Exception {
JwtConsumer consumer = new JwtConsumerBuilder()
.setSkipAllValidators()
.setDisableRequireSignature()
.setSkipSignatureVerification()
.build();
JwtClaims claims = consumer.processToClaims(token);
System.out.println("* Parsed token: "+ claims.getRawJson() );
System.out.println("* Expiration date: " + new Date(claims.getExpirationTime().getValueInMillis()) );
}
More examples are available on GitHub:
https://github.com/pvliesdonk/jose4j/blob/master/src/test/java/org/jose4j/examples/ExamplesTest.java
Last remark: you do not need a key nor a secret to parse the JWT, but if needed, you can use the server (public) key to verify the token was signed by the keycloak server you are trusting.
The JWT website is listing all libraries for Token Signing/Verification:
https://jwt.io/#libraries-io
Keycloak access tokens are indeed JWT tokens. So, you can make full use of existing JWT libraries, including for validation as stated in the Keycloak official documentation:
If you need to manually validate access tokens issued by Keycloak you can invoke the Introspection Endpoint. The downside to this approach is that you have to make a network invocation to the Keycloak server. This can be slow and possibily overload the server if you have too many validation requests going on at the same time. Keycloak issued access tokens are JSON Web Tokens (JWT) digitally signed and encoded using JSON Web Signature (JWS). Because they are encoded in this way, this allows you to locally validate access tokens using the public key of the issuing realm. You can either hard code the realm’s public key in your validation code, or lookup and cache the public key using the certificate endpoint with the Key ID (KID) embedded within the JWS. Depending what language you code in, there are a multitude of third party libraries out there that can help you with JWS validation.
Besides, in Java EE, using the Keycloak Java adapter, the roles are typically mapped on the user Principal and i.e. allows isUserInRole(). That's one of the goals.
Also it is possible to cast the Principal from the SecurityContext as a KeycloakPrincipal, then obtain in turn a KeycloakSecurityContext from it. Using the KeycloakSecurityContext you have access to both ID and Access tokens (when applicable) and can read their properties, attributes and claims.
Note that it is also good practice, and simply useful, to use the Keycloak UI to "evaluate" your tokens. For instance, you can see the generated token in the Client Scopes tab (under Evaluate), as well as evaluate your policies and permissions in the Authorization tab of your Client(s) (under Evaluate).
Cf. https://www.keycloak.org/docs/latest/server_admin/#_client_scopes_evaluate
That's probably the best way to debug and test, while setting up your Client(s).
If you select a user in the Evaluate screen, the following example data is generated:
Generated Access Token (...)
Generated ID Token (...)
Generated User Info (...)
All examples are generated for the particular user and issued for the particular client, with the specified value of scope parameter. The examples include all of the claims and role mappings used.
Source: https://www.keycloak.org/docs/latest/server_admin/#generating-example-tokens-and-user-info
I'm looking for a way to restrict user access to specific clients in a realm.
I know I can do it with client where Authorization is enabled (fine-grained authorization support) but it doesn't work when trying to connect from front (client need to be public and not confidential).
I'm using a javascript application to login from front-end.
Is there a way to enable Authorization for public client or a work around ?
Thanks.
I'm not sure if this will totally answer your question because it's still not specific enougth but it may give you some further help.
In case you're new to the topic, please see difference between public and confidential clients here.
The current best practice for public clients like HTML/Javascipt applications is to use OpenId Connect with the Authorization Code Flow + PKCE. HTTPS is of course a must have. I recommend you use a javascript openid connect adapter for this like the following for example:
https://github.com/panva/node-openid-client
Basically your authentication / authorization flow is shown here:
When the user wants to login from your frontend client application first a unique verifier is generated which is only available to the exact user / browser session. This value get's hashed as a code challege. Then the user gets redirected to the login page of your authorization server (Keycloak for example) passing some parameters like a redirect uri and the challenge.
With successful login the user get's a session at the keycloak server which also stores the hashed challenge. Then the user gets redirected to given redirect uri (a path in your application) together with a code to obtain an access token. Back in your application you application uses the original value together with the code to get the actual token. The authorization server ckecks the value against the stored challenge and geturns the access token if it matches. You see the extra verifier is to prevent that anybody compromises your code fragment to obtain a token on your behalf.
Now you have an encoded access token in your browser app. Note the token itself is normally only encoded not encrypted but it can be signed. Those signatures can later be used from your backend to ckeck the token integrity but we will come to that soon. Roles, claimes, scopes and so on included in your access token tell you the privileges of the user/identity. You can of course use them to enable/disable functions in your app, block routes etc. but in the end client protection is never really effective so your real authorization ande resource protection happens at your resource server which is your backend (node, .net core, java etc.) maybe a restful Web Api. You pass your access token as a part of the http request header with every request to the backend. Now your backend checks the token integrity (optional) expiration time etc. analyzes scopes, claimes and roles to restrict the resource access.
For example a simple GET myapi/car/{1} may only need a token or can even be annonymous while a POST myapi/cars or PUT myapi/car/{1} may need a special role or higher privileges.
Does that help you out?
I'm working on a project with a RESTful Java backend and a Vue SPA front-end. Whilst figuring out how to do user authentication I came across JWT-tokens and since it (sorta) was what I was looking for I recklessly implemented it.
Few weeks later I realize that because the content being shown on the client side, depends on the users role, the client of course needs to know the users role. For obvious reasons I don't want to store the users role inside my client.
My question: I could create a request on the server that looks at the Authentication header and returns the role, but would this be save? If not are there any common strategies when it comes to roles and JWT-tokens? Or should I forget the JWT way of doing things and implement another kind of authentication entirely?
JWT is the common way to Authenticate users with SPA as Frontend + REST Api as backend.
You definitely should not store your Token Secret in frontend app.
You definitely can do kind of /user/roles endpoint in your API which will return the list of user's role.
Point 2 solution is 100% safe. Why? Even if someone will hack your frontend app to show the content which they should not see, your backend is checking Authorization at endpoint, so they will not get/put/change any data which they have not privilege to access in their JWT.