Keycloak API keys support - java

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:

Related

Keycloak JWT Validation using Java Spring Security + KC Adapter

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.

auth on twitter for access to another site

I work on application, which try to get and parse information from site was named "Super-site" for instance. Access to data I needed is restricted and is necessary user authentication. I cannot ask user to send login\password from super-site, but Super-site have possibility authentication across social-auth (twitter). I can get access token from twitter, but I am unable to understand how to auth on Super-site using twitter access-token?
You will use the 3-legged OAuth with Twitter. Here is the link from Twitter that gives you steps. How you do this is by logging to your twitter account on developer.twitter.com, from Twitter Application Dashboard click on the Twitter App to create a Access Token and Access Token Secret. Your user accessing the Super-site will be prompted to authorize access to the Application, user grants access (clicks Yes) and finally your Super-site collects the OAuth token (user need not send username/password) and accesses the site.
Your super site must use oauth flow.
Every api should have oauth authentication and it is done at server end.
https://blog.restcase.com/4-most-used-rest-api-authentication-methods/
If they have twitter you can use twitter auth flow. They have to write code to understand twitter user account linking and authorization. So you login as a twitter user if thatuser is found in database you receive token and you can call api based on twitter user authorization.
The previous versions of this spec, OAuth 1.0 and 1.0a, were much more complicated than OAuth 2.0. The biggest change in the latest version is that it’s no longer required to sign each call with a keyed hash. The most common implementations of OAuth use one or both of these tokens instead:
access token: sent like an API key, it allows the application to access a user’s data; optionally, access tokens can expire.
refresh token: optionally part of an OAuth flow, refresh tokens retrieve a new access token if they have expired. OAuth2 combines Authentication and Authorization to allow more sophisticated scope and validity control.
OAuth 2.0 is the best choice for identifying personal user accounts and granting proper permissions. In this method, the user logs into a system. That system will then request authentication, usually in the form of a token. The user will then forward this request to an authentication server, which will either reject or allow this authentication. From here, the token is provided to the user, and then to the requester. Such a token can then be checked at any time independently of the user by the requester for validation and can be used over time with strictly limited scope and age of validity.
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/twitter-logins?view=aspnetcore-3.1

Spring OAuth2 + JWT, how to map external access token to local user

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.

Do I need an OAuth server implementation for a web application with a login system?

If I'm creating a web application with a RESTful back end, is OAuth 2.0 really necessary given that I don't want to connect with social media (Facebook, Google+, etc.)? I'm thinking about ditching OAuth2.0 and doing the following:
Generate JWT tokens upon successful login
Store this token in redis (or database, haven't decided)
Have a filter that checks for the JWT token and matches the token with the one in redis/db.
If the token exists, allow the user to access the resource
You can manually generate JWT tokens if you wish but it would be better to let an oAuth 2.0 implementation handle the JWT generation.
You don't need to persist the token. Just check the signed signature of the JWT, there is no need to check a database as the point of a JWT is for stateless authentication.
OAuth 2.0 3 legged flow is mainly used to address a third-party application to gain resource owner access without sharing resource owner's credentials with the third party application.For example, a photo print application wants to access resource owner's (user) flicker account on behalf of resource owner without sharing the resource owner flicker account credentials.
In the traditional client-server authentication, you may consider to use OAuth 2.0 2 legged resource owner grant where OAuth 2.0 client application can request OAuth 2.0 Server to create OAuth Access Token. In this case, you can use JWT Token for OAuth Access Token. This flow is almost you have mentioned but only standard OAuth 2.0 resource owner request and response. Please refer resource owner request and response details at https://www.rfc-editor.org/rfc/rfc6749#section-4.3.2. If you use standard 2 legged OAuth flow, then client and server integration will be easy and interoperable.
If you don't want to support terminate(revoke) token operation, then you don't need to store the token in the database or any other place. In this case, the token can be self-expired but not terminated.
Even if you have a requirement for terminate token, then don't store the entire token and just store token uuid (random id) and set the token uuid in one of JWT Token Claim.

Appengine Custom Authentication

I am planing to write an API for a mobile app. To lower the barrier for first time users i do not want a login screen on the first start. So what I want is, if the app notices it is it's first start it should register itself:
/register
A standard User should be generated like Name: GuestXX43, Authtoken XX43-58asda5-54asd, some additional Data
The user is now able to make other endpoint request due to its auth token.
But how do I check for the correct auth token on every Request?
/user [Update]
the user is also able to update his username and password to reloggin on another Device.
Which auth method will suite these thoughts, is there any doubt using this kind of auth flow?
Thanks guys
Are you using Google Cloud Endpoints? If the user credentials is set in some header, you can retrieve it in the backend via injecting HttpServletRequest in Java or check HTTP_YOUR_HEADER_NAME environment variables in Python.
Also you can try custom authenticator if you uses Java; this post can be relevant: Google Cloud Endpoints and user's authentication.

Categories

Resources