I am using keycloak for authentication for the application. I want to remove the realm access from JWT token generated by keycloak.
Is it a bad practice to have realm access (roles) ion JWT token?
Is there a way to remove realm access from JWT token generated by keycloak service?
I may be wrong but I don't see this as a bad practice because the Token is signed. A client won't be able to change the content of the token payload without knowing your secret (The token signature would be false). Just be sure to check the token validity.
If you want to change the information provided in your token, you should have a look at the "Client Scope" section.
From there, you'll be able to change the content of your jwt token.
I think, it depends on your security policies exist in your software boundary or environment. We had a project that existing user or client roles inside JWT token introduced a major security issue by security analysts, although we had launched it many times in other critical environments.
By the way, some software frameworks do some proactive authorization checks by using roles coming inside JWT and so, make them mandatory for these kind of systems based their security design.
So to wrap it up,
Try enquiry security analysts of your deployment s environments about
it.
Related
I have gone through multiple blog posts and StackOverflow questions before writing my own. I have multiple queries and none of the posts answer them.
I am using Keycloak Spring Security Adapter to secure my legacy Spring application. I referred to the keycloak documentation here and was able to have OAuth flow running for me. I am using Client Id and Secret as Client Authenticator.
For eg: Access to localhost:8080/about.htm will redirect me to keycloak login screen and after successful authentication, I will be able to view my page. I am also using the below code to read the user details from the token,
KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>) auth.getPrincipal();
IDToken idToken = kp.getKeycloakSecurityContext().getIdToken();
user.setUsername(idToken.getPreferredUsername());
Now when I test this application using postman and modify the generated access token, obviously the server gives an error. Ref : How to test application using postman.
However, this is the flow :
Client sends a request to the resource server, resource server checks for a token - if it exists, the client does the validation. If it doesn’t exist or is invalid, it redirects to the authorization server (KC).
My question is,
Who is validating this token? How does postman flow throw an error
if I fiddle with the token?
Do I really need to write a JwtTokenValidator in my application for
each request? Won't that be overkill?
If I use Client Authenticator as Signed Jwt with client secret, will this validation still be required? I am not using it as it introduces latency.
Please assist.
Answer to #1:
When you use any Keycloak adapters in your application (in your case the Spring adapter for Keycloak), that's the one who does the validation and redirects to the login if necessary. As part of the validation, it checks the signature of the token issued by Keycloak. So when you fiddle with the token, the signature doesn't match, hence it throws an error.
Answer to #2
No, you shouldn't need to implement a JwtTokenValidator. The adapter does it for you and a request should reach your endpoint/URL only if it has a valid token. You may only need to do that if you have a special requirements about validating the token (e.g. checking specific claim in the token against some service). Otherwise, you can safely use the claims in the token you received from the KeycloakSecurityContext. You can even setup authorization based on your URL patterns and Keycloak will enforce them too and allow the request to pass if user has necessary roles (like this example).
Answer to #3:
That option only changes the method used to authenticate your app to the Keycloak and has nothing to do with the user's token validation inside your app. In your current setup, when your app wants to communicate with Keycloak (e.g. to exchange auth code with auth token), it authenticate itself to Keycloak with a client-id/client-secret pair (otherwise Keycloak would not know it's your app and will reject the request).
If you choose the "Signed Jwt with Client Secret" option, your client can not just use a client-secret to authenticate to Keycloak. It should support the RFC7523 specification. So it's quite complex in compare with a simple clien-secret approach. In an environment in which you trust your clients (e.g. they're all known apps developed inside the company and you're not going to support public clients to join your Keycloak and use its services) it's quite common and safe to use client-secret approach.
We have an already existing system which uses an old Auth0 server for authentication and authorization. My goal is to integrate this system with Keycloak. In the Auth0 server we assign roles to users and these roles are mapped to a group of permission scopes, eg, "account:create", "user:create", etc are assigned to role "admin". We are planning on using keycloak Authorization services to replace Auth0 authorization. For it to work, we need to use keycloak bearer tokens.
Problem is, several users make requests to our API using an api-key (fix token). We basically make a request to the Auth0 server with api-key and it returns permission for that user. As we can't ask user to change the way the interact with our API (managament decision), i'm thinking on creating a custom authenticator, so when I request token endpoint (http://{ip}:{port}/auth/realms/{realm}/protocol/openid-connect/token) with an extra api-key header, I can check if there is an user with that api-key attribute assigned and get a bearer token for that user in return. The idea is to do this internally.
Is it a correct approach? If so, how do I implement the authenticator? Once I have found the user by api-key, how do I tell the authenticator which is the authenticated user?
Better late than never! I resolved this a while ago, but I wanted to share the solution, in case it helps someone:
I saved the API keys as user attributes.
I created a custom Keycloak Authenticator that checks if there is an user with the given API key.
I created a custom direct grant flow to use the custom Authenticator that successfully authenticate the user either if an API key or usual username and password credentials are provided in the token endpoint.
As the user only knows about API keys, I used an eviction cache whose key is the API key and whose value is the bearer token.
You can find an example and more details in the following repo:
I am currently developing a web service with Spring. I would like to provide users the possibility to login via external OAuth-Services, e.g. Google, Github,... as well as a traditional username/password-login. POJO-wise, I have the following setup:
Each User has a One-to-Many relation to AuthenticationMethods
Each AuthenticationMethod has exactly one AuthenticationProvider (e.g. google, github, local) and stores the sub of this authentication method and the corresponding User. In case of a local authentication, it is the User's ID.
Each AuthenticationMethod with AuthenticationProvider == local additionally stores a password.
What already works
Local authentication (username/password) is done through an own OAuth2 authentication server (part of the Spring application) and returns an JWTAccessToken , containing the username (the frontend never sees the client_secret, thus a password grant is acceptible in this situation).
I am also able to retrieve access tokens from the external OAuth Providers (Google, Github,...) via the authorization_request grant process containing their user'S sup from said provider.
Problem
I need to map the external sub to a User object. Since, in theory, two different users could have the same sub at two different, external providers, I would have to check the issuer as well, resulting in a nasty if-else construct. Also, this translation from JWT token to a User must be performed with every access where authorization is required.
Ideas for solutions
What I would like to do is add information to the externally generated JWT. This is obviously not possible since I cannot "re-sign" the external JWT. My idea is to intercept the external JWT and issue a local JWT, containing the username, thus using the external JWT only for initial authentication.
Is there a built-in possibility in Spring to accomplish what I want? Or is there a "best-practice" to solve this problem?
The best practice is to have OAuth2 server to add username as an additional claim to JWT. Spring already has a handle that takes "user_name" claim from JWT and uses it as Principal object.
I have a Spring REST application, and I'm thinking about what type of security to use. I'm considering between two options:
Spring Security with OAuth2
Spring Security with JWT like here https://www.toptal.com/java/rest-security-with-jwt-spring-security-and-java
Any other option?
It must be good and secure enough for nowadays.
Application is going to be a simple service or few small services.
As a database I'm using MongoDB (probably it doesn't matter).
Maybe someone has some pros and cons of each type or any other suggestions what to use.
First of all , your both points are same and point # 2 is incorrect as JWT is only a token format and not the actual security mechanism so both can't be compared.
OAuth2 server is the one which will generate token for you either in JWT or non-JWT format , that is your choice.
I am not sure about all the technologies out there but if you go by popularity, an OAuth2 as Authorization Server and JWT as token format are quite popular.
Application / API Security means lots of things and Authentication plus Authorization prevents lots of attacks. Obviously, not everything is a developer concern and most goes to infrastructure or security teams.
Flow
Set up an Authentication Mechanism
Set up an Authorization Mechanism ( OAuth2 ) connected to same User
Source as Authentication mechanism. From here , you will get a token in JWT or non - JWT format. Getting token in JWT format has advantages that you can read on
Now you set up a mechanism in your API project ( Usually Filters ) to parse and validate JWT token. Requests without valid tokens would be declined. This will force your clients to first authenticate themselves and retrieve a valid token to use your APIs.
You can set up few more security in your API using Spring Security like XSS attacks, Cross Domain etc
I am new to OAuth2 concept.I ahve to implement this in my application. This application provides REST APIs. I follwed some tutorial ,done some research and kind of implemented it in working state in my application.
But while doing some search I read about different type of grant_type in OAuth2. I tried to learn about that but didn't get actual differences and which should I use for securing REST APIs.
So I want to know that for grant_type types "password","client_credential"etc which should be used and in which scenario, or which should be used for securing REST APIs?
Also at some places I found that the request for /oauth/token is different.
Some places the Authorization header is given as Basic 'some_encoded_string' .
And at some place it is Bearer 'some_encoded_string'. Whats the difference in these request?
Summarizing this I have 2 question -
For grant_type types "password","client_credential"etc which should be used and in which scenario, or which should be used for securing REST APIs?
What is the difference in ways of requesting token from /oauth/token .
Enlight my knowledge in implementing spring-security-oauth2.
The grant you need to use depends on your use case and the nature of the client application accessing your resources. There isn't a grant that applies a REST APIresource in general. You'd need to provide more information on what the APIs are and how you interact with them.
If a user has to give their permissions for a client to access an API, then you would normally use an "authorization code" grant. If the client accesses the resource directly without the intervention of an end user then it would normally use the "client credentials" grant.
You should avoid using the password grant in most cases, since it means the user has to provide their username and password to the client application. If the application can use another grant, such as authorization code, then that is preferable. A trusted application, such as a native application which the user installs on their computer, would be one situation where the password grant might be used.
A client would normally use "Basic" authentication to access the token endpoint. "Bearer" authentication is use to access a protected resource (such as your API), passing the access token it obtained from the authorization server.
Why do you think you need to use OAuth2 at all? I'm curious since you say you don't understand what the grant types are for. You really need to understand this before you can make a judgement about how you would use OAuth2 or why.