Use JWT to authorize microservices - java

I'm trying to build a reservation system for a sports hall. I have divided it into multiple microservices, such as Equipment and Location. One of them is called "Authentication", where I check the user's credentials. There I have a UserDetailsService where I check whether the user exists and what role it has.
I am using JWT (io.jsonwebtoken more precisely), and I have a request filter that checks if the token is valid. So, right now the authorization works for the authentication, but I'm not sure how to pass the JWT token to the other microservices and authorize them as well.
I was thinking of simply calling that filter form Authentication in each microservices whenever I need something, but then I believe that defeats the purpose of having microservices.
Is there a better alternative? How do I actually check the JWT token in those microservices?

Related

Keycloak API keys support

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:

Use fusionauth for authentication through spring boot microservices

I'm creating microservices with spring boot using this tutorial
https://medium.com/omarelgabrys-blog/microservices-with-spring-boot-authentication-with-jwt-part-3-fafc9d7187e8
So I have actually 4 microservices:
eureka-server
gateway-service (with #zuulproxy)
auth-service
gallery-service
Following the tutorial linked, the scenario is:
I can, with success, register and login user on gateway-service using auth-service routes, obtain a jwt token. This token is used on gateway-service to invoke gallery-service routes.
The problem is that only gateway-service implements spring-security. So gallery-service doesn't use the same securityContext and I can't obtain the information about logged user in a gallery-service's controller.
Is this a valid solution or I have to use spring-security in each microservices? In this case, how use the same jwt given by auth-service, in all microservices?
On top this problem, there is the fusionAuth question. In the auth-service, db is simulated with a list. Instead of list, I have to call fusionAuth login API with username and password and get user's token and roles.
I'm new in spring-security world and in general in developing with microservices. Is all this a valid approach?
My purpose is create a mobile application with thousands of users, so I want to develop an efficient and secure way to login them and add more logic on other microservices based on user's role.
Thanks in advance for helping!

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.

Spring Security - UserDetailsService for oAuth2 implementation?

So, using a basic authentication, I can see the value in simply using an implementation of the UserDetailsService which basically just loads a user and confirms they are authenticated.
However, I would now like to use oAuth2 and am not sure if my thinking is completely wrong on this subject. Wouldn't using oAuth2 eliminate the need for a UserDetailsService implementation? Because essentially the authorization server is the one who is checking to make sure the user exists (using Resource owner password flow) and then sends the user a JWT.
Once the user has this access token and can send it with every request, there has got to be another way to get the user authenticated into the AuthenticationManager rather than duplicating the effort and checking to make sure the credentials are correct again within the UserDetailsService (which the Authorization Server from oAuth2 would have already one).
What is this other way? What would be a solid implementation for this?
Thanks.
Actually UserDetailsService required for getting user information with his permissions. This is normal behavior. If user passed authorization he receive access token and Spring store his authentication data into SecurityContext. When user sends requests to protected resources with token - Spring validates token and puts into SecurityContext authentication data from DB or from memory. Its depends on the type of TokenStore (jdbc, memory, etc). Spring security using UserDetailsService once for user authorization.

Access data from other spring security filters

Is it possible to access the credentials and authorities granted by a previous filter in spring security?
Background:
I am developing a Java RESTful API using Spring and Spring Security with token-based authentication.
However, some calls have an additional protection with the user's password.
Currently I have my own implementation of a GenericFilterBean that filters out the token from the HTTP-Header and checks if it is present in the database. Depending on the permissions associated with this token, the user is granted different roles. The permissions are stored in the my database and can be retrieved with the token.
There are several calls in the API which need an additional authentication with the user's password.
I thought of creating a second custom filter that extractes the password from the header.
The problem with this approach is that I don't want to identify the user just by his password but rather by the user extracted from the the token in the first filter.
The SecurityContextHolder always holds the current authentication object. You can retrieve the authentication placed there by authentication filters by calling SecurityContextHolder.getContext().getAuthentication(), which returns an object that has the methods getAuthorities(), getCredentials(), and getPrincipal().

Categories

Resources