OpenId-Connect (OIDC) with Spring Security but without sticky sessions or central storage - spring

We want to configure our service with OIDC authentication against a keycloak server.
We are using spring security 5.2.0 with spring boot 2.2.0.
There are multiple instances of our service and we do not want to share any state between them with central storage (e.g. databases, distributed caches, ...), nor use sticky sessions. That's why we already implemented two custom cookie-based repositories for authorization info that would normally reside in the server-side session. (CookieBasedRequestCache and CookieBasedAuthorizationRequestRepository). That way the oidc redirect flow works except for the last step where the user is redirected to the original url:
After successul login, keycloak redirects back to our instance with a code. This instance (let's call it 'A') validates the OAuth2AuthorizationResponse against the initial keycloak authorization request. It gets the information from a cookie we saved earlier in the login process to avoid Spring Security's session management.
Now, if the authorization response is successfully validated, instance 'A' sends a final redirect to the original URL that the user requested before logging in. If this request is answered by the same instance 'A', everything works fine. But if a different instance (say 'B') answers the request, it doesn't work because B doesn't know anything about the user's authentication state.
Questions:
Is there a cookie-based JWT repository we could use to save the access token across instances? Or how would one implement it?
Where in spring security's code (filter chain?) is the check whether the user is authenticated? This would be helpful for answering the final redirect to the original url.

Related

JwtAuthenticationToken is not being saved to HttpSessionSecurityContextRepository: spring authorization server 0.4.0, spring 5.7

I am using spring authorization server for oauth2 authentication, with resource server configuration for handling authentication outside of the server. My use case is as follows:
user makes a request to authorize end point
since the session is not authenticated, system caches the request and redirect the user to an external end point for authentication.
Once authentication is successful external system creates a short lived jwt token.
Jwt token is sent to authorization server, which it will validate and redirect the request to the saved previous request (which is the authorize end point call in step 1)
Since the jwt token was authenticated, I want the authorize call to succeed this time.
With spring version 5.6, the securitycontextholder was able to save the authentication, and any subsequent requests in the same session was able to use the jwtauthentication. Now since the transient check is added on the HttpSessionSecurityContextRepository.java, jwtauthentication is not saved between requests and my functionality is broken.
How can I handle this scenario? I would like to use the jwt authentication from an external source in conjunction with spring authorization server. Any suggestions are appreciated.
I already have checked a similar question- JwtAuthenticationToken is not being saved to HttpSessionSecurityContextRepository after upgrading to 5.7 version which didnt have any inputs. I also have checked the github discussions for both spring 5.7 release and authorization server 0.4.0 release and was not able to find any guides.

Securing rest and actuator endpoints using custom token and http session

I have a spring boot app where the API #Controller endpoints are secured using a token that is contained in the http header. The token needs to be extracted from the header and validated against an internal cache to make sure it is valid. If the token is valid then the request can proceed to the controller and if it is not valid then it should return a 401 to the caller.
I also have another requirement to secure some of the actuator end points. When the user tries to use the browser to access the respective actuator endpoint, it will check for a user session if no session exists then the request is redirected to the spring login page. When they login I need to extract the username and password and validate using an external service. If valid a session can be created for the user and they can then use the hawtio endpoint. The session needs to store role based information so that when the user tries to perform JMX operations it will only allow them to perform the appropriate read only / write if they have the requisite role.
Any pointers regarding how you'd try and tackle this would be most welcome. I am unsure whether this is achieved by specifying addFilterBefore or addFilter and I don't understand how having authenticated the user for the actuator I go about creating a session that can be stored in the context and checked later on for subsequent requests.
Thanks

What is the advantage of providing a Tokenized Authentication in an application with Spring Boot Backend over SecurityContextHolder?

I was getting started with Spring Boot and Angular 7 and I came across user authentication.
Let's assume the following: I have a frontend with Angular 7 and a Backend with Spring Boot that offers API's that can be accessed via HTTP.
So I know that usually the frontend authenticates the user with e.g. JWT that stores all necessary information about the user that might be needed. But I came across the SecurityContextHoler of Spring Boot Security:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
This allows me to simply access granted Authorities and so on. So I thought about the following:
Using JWT for the frontend grants the following advantages (as far as I know):
* Users can identify when using API's
* Users may be prevented from certain UI-Elements (based on roles stored in JWT)
* Modification prevention due to checksum (invalid token afterwards)
Now I could also add a check in my Controller in the Backend that checks the SecurityContextHolder for user permission (something like a Service that checks the current context permissions vs the needed permission and returns true/false). Wouldn't that be even more save, since it is in the backend (so in my inmagination everything that runs server-sided is always a little more save than what runs client-sided)?
I can store information in the frontend (like roles and a username) to use them for the UI-based-access prevention to still have the same advantages as JWT provides, but I do not have the "effort" of implementing the JWT creation.
But obviously it is not common to do it that way (at least I never saw it), so what is the advantage of the Tokenization?
They are not mutually exclusive. You would use what you call "Tokenized Authentication", like an oAuth2 Bearer token most likely in a JWT when the Authentication is performed by a separate system from your Spring Boot backend. For example, you may be using Okta, Keycloak, Google or Facebook to authenticate the user.
At a minimum, your Spring Boot backend stores the username extracted from the JWT in the Authentication. You can get Spring Boot to extract any roles in the token and add those to Authentication::grantedAuthorites. If your backend system, has it's own set of roles in addition to what's in the token, then the backend could implement a PrincipalExtractor to load a UserDetails object for this user from the database as the Principal and merge the roles in the token with those store in the local database.
You'll probably want to security certain methods in your backend with method security annotations like #PreAuthorize(), since you shouldn't trust the front end. The method security will check permissions, like hasRole("ADMIN") or hasPermission(object, 'READ') using the Principal object in SecurityContextHolder.getContext().getAuthentication();
In the end, the token assures the backend the user accessing it is who they say they are, i.e. Authentication, but does not necessarily tell the backend what they are Authorized to do. Yes, if you control the Authentication server you can include roles in the JWT, but roles don't usually provide as fine a grained control as is required.
Independent of what level of security you implement, the token is translated into an Authorization so you can use the Spring Security framework to manage access within your backend code.
There are 3 type of token in spring security OAuth2:
1. InMemory token Store
2.JWT token store
3.JDBC token store
So now you’re talking the JWT token store. The most powerful of JWT token store is prevent the authorization server load against to the database for checking such as role,token expired so it is related database load performance. Since all the information such as: role,username, token expire ,etc include in token itself. So the authorization server or other resource sever may using the public key to verify this token itself without invoke to data store.
Hope helpful! ☺️

How does spring basic authentication works for subsequent requests after login via basic authentication

I am implementing REST services using springMVC. Now i have added basic authentication entry point in my spring security file. But i don`t know that, Once user authenticated by passing credentials in Authorization header does he need to pass those credentials for all subsequent requests?
for example,
I have two URLs:
1) localhost/apppName/login
// Here user passes credentials in Authorization header. So, user authenticated successfully.
2) localhost/appName/getUsers/1
//Here, client need to pass those credentials in Authorization header?
if it is needed, then why spring kept prinicpal object in the SecurityContextHoder after authentication done via BasicAuthenitcationEntryPoint?
Clients of this services can be any thing like Android, java, .Net
Any suggestions will be appreciated.
Pure REST is stateless, which means that no client context is being stored on the server between requests. That means you need to send the Authorization header for each request.
You don't need to hit the login URL when using Basic auth, that's the point.
However, you can use sessions in combination with Basic auth, and in that case you should pass session cookie between requests. It may have some performance advantage, but generally I would not recommend it.

Spring library with Service provider login page

I have a requirement that needs to have login page at the service provider and I use java web app. Is there any way to use the spring SAML libraries to achieve this behaviour ? If so, what could be the steps? (it seems the default behavior of spring library is to redirect to IDP login page and I am not sure if we can configure to host login page on the service provider and relay that request to IDP)
I think what you're looking for is having two different ways to authenticate, one locally and one through SAML. I believe for having a login form, you would want to separate configurations with different AuthenticationEntryPoints, i.e. go to /login for local or /saml/login/alias/" + spAlias+ "?idp=" + spEntityID for direct login to SAML.
It sounds like right now you have SAML protecting any URL, which by default redirects you to the IDP since it's configured. The first step that I would take is getting user name and password authentication working with logins independently of SAML, then add SAML back in. Be sure to list whatever URL the login form uses as permit all so SAML doesn't kick in.

Resources