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.
Related
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?
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 boot web app with spring security integrated with LDAP authentication. This web app internally makes REST calls. These REST calls are having username-password authentication. This username-password is the same used by spring security. Is there anyway I can get the username-password authenticated by spring security, so as to use in the REST calls. If not this way, is there any other way to achieve this.
Thanks in advance.
There is a quite nice way that I think fit your case.
By default Spring Security does not store the password in memory after authentication has been made, so you need to change that. With Java config, add in configure(AuthenticationManagerBuilder) method:
auth.eraseCredentials(false);
Then you can get the username and password for the current user with:
String username = SecurityContextHolder.getContext().getAuthentication().getName();
Object rawPassword = SecurityContextHolder.getContext().getAuthentication().getCredentials();
Spring Security is performed based on the rule in the security properties.
This means that you just need to have spring-security enabled, the only problem is that if not authorised it will go to the Not Authorised Page which a Restful client will not understand. But if the Restful client has authenticated and been granted a valid session then it will be able to get past the Security_check and access the protected page.
I guess Spring security is working like AOP so each protected page has a Security_check crosscut that only allows access to the page if the authentication is there.
Anyway, I solved the problem writing a custom AuthenticationProvider, which will perform the LDAP authentication and get the username-password for the future REST calls.
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().
Is it possible to authenticate a user by checking for an existing HttpSession within Spring Security? I would like users to authenticate via CAS at one URL (http://example.com/auth), but not the other URLs. For example, if they go straight to http://example.com/content, then I'd like to check for the HttpSession and return a 401 Unauthorized code if they haven't logged into CAS yet. If they've already gone to the /auth page and logged in, then going to /content will return the content. The main reason for this is to avoid any redirects that CAS causes during authentication.
I am kind of new to Spring Security and can't figure out if I need a custom AuthenticationManager, AuthenticationEntryPoint, both, or something else. The AuthenticationManager doesn't have a way for me to access the HttpSession, and the AuthenticationEntryPoint doesn't seem to be the right place to implement this functionality.
Any ideas?
Spring Security is not using HTTP session.
Instead, you can easily call to this static method:
SecurityContextHolder.getContext().getAuthentication();
Frankly, I believe that you need to configure Spring security correct in order to avoid checking authentication and redirect manually to other page.