At my company, we need to extract the roles of the logged in user from the REST API that Keycloak provides. We have looked through the Keycloak documentation but can't find the answers we are looking for. Let me explain the flow we want to implement: A user logs in to a client defined in Keycloak and receives a JWT which is stored in the applications web client. The user is not an admin in Keycloak. When the web client makes a request to the backend server, the backend server queries Keycloak for the user's roles. And, this is the point where we have trouble. We can't figure out the correct URL for the REST API or which token to add to the authentication header.
To summarize: we need help with the URL which is needed to query for user roles and what token to send to authorize against the API. I'm aware that the roles can be retrieved from the JWT, but we are afraid that the payload will become to big over time. A user may have multiple roles in different departments.
The roles should be in the JWT payload, this should be configured in the keycloak service. The flow should be something like this:
User is authenticated by the front end and the JWT token returned by keycloak is stored
The front end hits the back end including the token in the request header
The back end takes the token, validates it using the public key (the public key is provided by keycloak), if the token is valid, the roles are taken from the token payload and the authorization process is executed
Related
I'm new to keycloak and would like to check what is the common design on the said architecture.
I have 1 backend(quarkus) 1 frontend (angular) and 1 flutter.
I would like to see if I could leverage the features of client. My idea is to have a separate client within the realm. For example
REALM = MyAppRealm
Client = backend-client and front-endclient
Is it possible that the token i got from front-endclient can be use to access the api from the backend?
Reason I have this setup is that the front-endclient has a public accesstype while the backend has confidential
to sum up. I would like to see if i can reuse the token i got from front-endclient to my backend-client
Yes of course you can do that.
The purpose of openid is to share authentication and authorization between a diversity of clients without needing to share credentials (no password is known by any of the clients). A trusted third party (here Keycloak) will give back a signed token in exchange for credentials. And this token will be a proof of who the user is and what he is allowed to do in the communications between the frontend and backend.
To sum up :
Your angular frontend authenticates an user using a public client and an implicit flow. When successfully authenticated, the frontend obtains an access token and a refresh token.
When making a REST call to the backend, your frontend needs to set the header Authorization using the access token as a bearer token ('Authorization: Bearer insert access token here'). You can automate this by using an interceptor (example)
Finally, when your backend receive an API request it can check the Authorization header to ensure the request is authenticated and authorized. For how to do that with Quarkus, everything is explained in this documentation page : https://quarkus.io/guides/security-openid-connect
So I build a RESTful API. It has an /account/{id} endpoint to return user data. The API is secured via an identity server that issues the requester a JSON Web token (JWT) with access to the /account/{id} endpoint. The user sends a request with username and password and receives a JWT in return on successful authentication. Now the user sends a request for their account information to /account/{id}. The request is sent with a token in the header and returns a 200 response with the user data in the payload.
How would one go about authorizing the {id} in the endpoint? In other words, an authenticated user could just add any {id} in the endpoint and potentially receive another user's data. How is this prevented using the JWT?
You can store data in a web token. If you store the ID of the user, then you can identify them for each request they make. This is safe, because the contents of the token are signed with the private key of the server. Therefore their contents cannot be changed.
After that you can either limit the API so that each user can only query their own record, or you can also implement a complex role system, where each user has a set of roles (e.g. read-only, guest, maintainer, admin, client, etc.) that define which endpoints and how they can use.
I have 3 services (in the real much more):
Authorization service (uses OAuth 2.0)
Frontend service
Resource service
and client (web-browser).
I store session_id, access_token and refersh_token in cookies of the user's web-browser. The user goes to Auth service, signs in and gets these tokens. After his web-browser is redirected to Frontend.
Frontend and Resource services can't validate tokens because they know a nothing about it, so they must make a request to Auth service.
The current scenarios:
The user (web-browser) sends a request to Frontend service, the Frontend sends a request to Auth service to validate access_token. If it's invalid the Frontend sends a request to refresh token using refresh_token.
If the Frontend needs an access to Resource service to process a request then the Frontend sends its client_id and access_token to Resource service. The Resource service sends a request to the Auth service to validate an access_token too.
Are my thoughts right? Or it has simpler schema?
P.S. All services use RESTful architecture.
OAuth talks about how the tokens be exchanged. What you have mentioned it seem liek you are talking about using implicit grant, which is little less secure and you may think of opting for authorisation flow.
Other than that, in microservices when you have many services and one user request pass through many downstream services, verifying the token with auth provider at each and every step might become a bottleneck.
There are ways out there by which you can skip this call to auth server and still validate the sanctity of the token without making an explicit call.
One way is to make use of JWT. These tokens are signed by the Auth provider and your services have keys which can help you validate if the token is modified on it way, and token itself has all the information you need to ensure validity of it, like expiry time, intended audience, clients, roles etc.
On login you get AT and RT. AT could be passed along to downstream for authentication and authorization and RT could be used when AT is expired.
You only need to talk to auth provider at the time of login and when you need to refresh the token.
You can read more about the JWT OAuth2.0 with JWT and OIDC to get more information around it
I have a question regarding Keycloak and obtaining an Access Token.
Our setup is as follows:
· users are created and maintained in Keycloak
· resources, policies and permissions are also maintained in Keycloak
Our use case is:
As a third party application, I want to obtain authorization information (e.g. resource- and scope-based permissions) for a specific user by only providing the username to Keycloak, so I can allow or prohibit further actions.
To be more specific:
In our application the need to validate each request to other services based on the access token.But we have only the user name with us.
The question is now:
> How can we obtain an access token for the user by only knowing the username ?
>
Is there a solution to obtain an access token for such a user?
You don't specify in your question if the current user is logged in. Are you validating user specific actions, or you want to retrieve user roles for the application instead?
The user is logged in and he is performing some action
I suppose you're using some keycloak adapter. Then just retrieve the session object and you should have the extra info somewhere in there.
If not, you can just parse the request yourself. When using OpenId Connect, the access token is always sent for each of the requests, in the Authorization header. The token is base64 encoded, you can decode the token yourself.
The application is performing some action for some registered user, without him logged in
User access tokens are meant to provide permissions for users. As you say in your question: As a third party application, I want... so here you are not acting as a logged user, but as an application, so you need to go with client credentials instead. Just give the client permissions to list all the users and their roles (probably it's enough with the view-users role, see the link below) and log in with client credentials grant. Then you can handle fine grained permissions in your application business logic.
See also:
Keycloak Client Credentials Flow Clarification
Keycloak spring security client credential grant
How to get Keycloak users via REST without admin account
For those who really needs to impersonate a user from a client, there is a new RFC for this : token-echange.
Keycloak loosely implement it at the time of this answer
See particularly https://www.keycloak.org/docs/latest/securing_apps/#direct-naked-impersonation
I'm developing an Android app that consumes a REST service that uses OAuth protocol. In the first activity, app shows a login screen. This is the flow:
1) User puts her username and password.
2) App makes a request to REST service, providing username and password.
3) REST service check the credentials and if are correct, ask for an access_token to my OAuth2 provider server.
4) REST service answers to the app providing the access_token and the refresh_token
5) In the next requests to the REST server (to get data like people, articles...) app will provide the access_token and the refresh_token.
6) When REST service process a request, will validate the access_token (using an token info endpoint of my OAuth server).
7) If the access_token is correct and has not expired, REST service will return the data that the app were asking for.
When REST service detects that access_token has expired, asks for another with using the refresh_roken.
Now, my questions:
When REST service retrieve a new access_token after the old one expires, has the REST service send it to the app in that response?
If so, has the app check, in each request/response, if new a new access_token has been sent from the REST service?
I don't know if I'm in the right way, I'm trying to understand the flow.
Thanks.
Assuming there's no browser involved and the app (aka. Client) uses what is called the Resource Owner Password Credentials grant, the flow is:
the User (aka. Resource Owner) provides his/her username and password to the Client
the Client makes a Token Request to the Authorization Server, providing username and password
the Authorization Server checks the credentials and if they are correct, it provides an access token and optionally a refresh token to the Client in the response
in the requests to the REST server (to get data like people, articles...) the Client will provide the access token
when the REST service process a request, it will validate the access token calling the token validation endpoint of the Authorization Server or by validating the token locally (e.g. if the access token is a JWT).
if the access token is correct, has not expired and has the right permissions (aka. "scopes"), the REST service will return the data that the Client was asking for
when the Client detects that access_token has expired (e.g. because the REST server returns an error), it asks the Authorization Server for another access token using the refresh token using the so-called Refresh Token grant/flow
OAuth 2.0 flows:
An application registers with the auth provider e.g. Facebook, Google, etc with app name, website and callback/postback URL
The application receives the client id and secret from the auth provider
The application user accesses the auth provider for authentication and user approves the resource permissions
The auth provider returns the auth token with respect to the user permissions to the application
The application accesses the resource provider using the auth tokens
The resource provider returns the protected resources after validating the auth tokens to the application
Do comment if you need more understanding!