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.
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.
We would like to have users authenticate to a Slack app by providing their current Keycloak JWT as a one-time authentication procedure. This would allow us to associate their Slack user ID with their Keycloak user ID.
However, I can't find any endpoint like AWS' GetCallerIdentity within Keycloak. I have combed the docs, and the closest thing I can find is an identity token mentioned here. However, I can't find anything about how to unravel that identity token to securely gain information about its owner.
Can anyone point me in the right direction?
Thank you!
Open ID Connect defines userinfo endpoint, which is similar to AWS GetCallerIdentity endpoint. But that requires to fire request. I would prefer to read user details from the token.
Standard JWT (OIDC) libraries support token decoding. Access/ID token has 3 parts: header, payload, signature. You can use base64 decode on the payload part and you will get json with user details. Of course proper implementation will read also header to get used algorithm and it will validates token signature with used IdP public key and algorithm. Otherwise someone can tamper token.
https://jwt.io/#debugger-io provides nice visual interface, which will help you to understand and also decode token structure:
Keep in mind: what is returned in the userinfo response depends on OIDC client configuration in the Keycloak
I am using AWS AppSync with keycloak as the OIDC provider and left the clientID blanked. This means that I can generate an access token using any clientId and client secret and start making requests (query or mutation) to my AppSync GraphQL endpoint.
However, I have to ask...how do I define fine grained access control with the scopes in the jwt token. I don't really understand what benefit this authorisation flow provides apart from just leveraging existing clients previously setup in keycloak or any other oidc providers.
So...what's the real benefit of using oidc auth for AppSync? Am I missing anything important here? Any feedback appreciated!
Thankyou!
You get access to the OIDC claims in the $ctx.identity.claims map within the resolver mapping templates which you can basically use to do your fine grained access control logic. Imagine if you have a groups claim meaning your user belongs to a group such as Admin then you can write custom logic in your mapping template based on that.
Here is an example of how to do this (it uses Cognito but OIDC should be pretty similar).
https://adrianhall.github.io/cloud/2018/06/01/how-developers-can-auth-with-aws-appsync/
When you authenticate with an OIDC provider you get back an id token and if you specified scopes for an API you get back an access token so that client applications can make requests to protected resources on the end user's behalf. Typically the access token is also a JWT.
But what is to stop someone from spoofing one of these access tokens, and creating one and passing it to an API? I understand there are safeguards to prevent modification because the signature will be different than what any validation logic is expecting, but what if a malicious user created a brand new one manually? Especially because these tokens can be validated 'in place' by any API that requires an access token (not all API's use the introspection endpoint... especially with a JWT). I do understand there is metadata around the signing keys for JWT's from OpenID Connect providers and that it is available in the OIDC discovery document. For example, here is Google's JWK metadata. Given that you have signing information publicly available, and JWT access token's can be validated without any requests to the OIDC provider, how are JWT's secure? What is preventing a person from creating one and passing it as a bearer token to an API that requires an access token?
But what is to stop someone from spoofing one of these access tokens, and creating one and passing it to an API?
Spoofing and reconstruction of signature is nearly impossible without the private key (assuming you are using asymmetric signing algorithm like RS256) that used for signing the original JWT.
The JWK information available via OIDC discovery document only contains the public key.
Also Use HTTPS for authorization / token exchange to avoid token sniffing.
I'm almost figuring out how the different pieces of an Authentication and Authorization server architecture work. I really think that IdentityServer is a great piece of software.
I'm trying to summarize my discoveries, to settle a base for my questions.
IdentityServer issues tokens using OpenID Connect. Issued tokens are ID Tokens and Access Tokens.
Tokens are requested - as stated by OpenID Connect protocol - to clients by using OAuth 2.0 flows. One flow for each client.
During the flow beginning, client requests a collection of scopes (at least "openid", that's because he has to state that an OpenID Connect flow has been activated)
A client may ask all the scopes that he is authorized to ask. Using the Entity Framework plugin for IdentityServer, this information is contained in the ClientScope table. If the client requests a scope that he isn't authorized to request, the flow is interrupted.
Scopes may "contain" claims. This means that if a scope contains a group of claims, whenever the client is issued a token, this token contains also all the corresponding user's claims. For example: let call "roles" a scope that contains "role" claim. As soon as the client is authorized, the received token will contain all the user's roles (as claims).
Each requested scope, if authorized, is "translated" in a claim with the name "scope". This means that if a client requests, for example, a defined "api" scope, the generated identity will have at least a claim called "scope" with value "api".
If all of what I've written is more and less correct, here are my questions:
how are claims defined on asp.net identity tables (i.e. AspNetUserClaims) connected to the IdentityServer ones. For what I've seen the matching is made on the name. Is this conclusion correct? In other words, if my client has to receive a "role" claims (because he has asked for the "roles" scope), will the "Asp.Net Identity" plugin for IdentityServer just release the "role" claims defined for the authenticated user?
referencing the "EntityFramework" plugin tables, what's the meaning of the "ClientClaims" table? I cannot get how claims can be directly connected to client... What am I missing?
let's suppose that in my resource server I've an action protected with a ResourceAuthorize attribute like this:
[ResourceAuthorize("Read", "Orders")]
In my AuthorizationManager I check for the presence of a claim "order_read" or a claim "api". Those are two different scopes defined in my AuthorizationServer, one just for "order reading" and the last for a complete API access. The first may be asked by third-party clients, while the latter no. Is that a good practice?
I cannot understand what my client should do with the id_token. Should I ignore the problem, as I'm using the js library OIDC Token Manager? Are the security controls performed by this library?
Last question: when my application presents the Access Token, how is the ClaimsIdentity generated? Is right to say that it's generated after validating the token on the Identity Server? Does this means that IdentityServer will get the access token and translate it in a set of claims?
Thanks for your clarifications!
Marco
Yep, you got the gist of it. As for your questions:
how are claims defined on asp.net identity tables
That's up to you. IdentityServer doesn't mandate an identity management library. The IUserService extensibility point is where you bridge that gap. We have a starter version of IUserService, but it's a code-based NuGet so you can change it to really do what you need.
I cannot understand what my client should do with the id_token
It is mainly used to pass back to IdentityServer at signout time (to authenticate the signout request).
when my application presents the Access Token, how is the ClaimsIdentity generated
There is middleware (AccessTokenValidation) to validate the access token. The result is the claims form the token, which are then turned into a ClaimsIdentity and then made available to any processing downstream (such as your Web API code).
what's the meaning of the "ClientClaims" table
The Client configuration has a Claims property if you'd like to issue claims on behalf of the client. Check the docs: https://identityserver.github.io/Documentation/docsv2/configuration/clients.html
let's suppose that in my resource server I've an action protected with a ResourceAuthorize attribute like this
This is unrelated to IdentityServer, and is part of the IdentityModel library. ResourceAuthorize is a framework for using the user, the resource, and the action being performed into account when trying to decide the authorization outcome.