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

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.

Related

Spring boot API with both Oauth 2.0/OpenID Connect and internal authentication?

I'm having a hard time figuring a good way to implement Oauth 2.0 and OpenID Connect authentication alongside an existing internal email+password authentication for a B2B Web app's API using Spring security.
We have a backend REST API that is a Spring Boot servlet application which currently authenticates users with OAuth 1.0 and the password grant. The front-end is an Angular single-page app through which users must log in with their username and password. The API's /oauth/token endpoint then delivers an opaque access token to be used for fetching secured resources that are then displayed within the app.
We'd like to add the possibility to log in using external authentication with OpenID connect, which is a perfect opportunity for switching to OAuth 2.0 and JWT tokens. Our API would then accept JWT tokens it delivered as well as external JWT tokens emitted by accepted issuers.
Reading and validating JWT tokens won't be a problem using Spring security's OAuth Resource Server. However things get complicated with how to make the classic username+password login flow work with JWT tokens.
We thought about delivering JWT access tokens the same way we used to with our old OAuth 1.0 tokens. The thing is, newer OAuth specifications advise against using the password grant, plus it simply isn't supported in the Spring authorization server project we're planning to use. The authorization-code flow w/ PKCE seems like too much for this case as we do not want the back-end API to render a login form but use credentials entered in the existing login form that is part of the single-page app.
I've read a lot about not using OAuth for 1st party login since its primary use is for external authentication, but again, that doesn't apply since we also want 3rd party authentication.
What would be a secure way to implement a Spring boot authorization server that can deliver JWT access tokens to a 1st party client in exchange for a user's credentials, all this using the existing log in page, and given the password grant type no longer being supported?
I thought about implementing a preliminary step that would be a POST request with Basic authentication to a /login endpoint that just returns a 200 HTTP status, then proceeding to the /oauth2/authorize request that would deliver the authorization code immediately without redirecting since my session is authenticated.
I'll be happy to provide more details if needed. Here are the resources I'm using for this project.
What about setting up an authorization-server capable of identity federation?
In such configuration, the authorization-server is responsible for providing with identities, proxying one or more sources (your existing user database for instance, plus maybe Google, Facebook, Github, etc.)
Keycloak does it for instance.
From the client point of view (your Angular app), the authorization-server is used to get:
access-token: put in Authorization header of requests to secured resource-server(s) (can be a JWT or an opaque string, doesn't matter, clients should not try to extract data from access-tokens)
refresh-token: send to authorization-server to renew access-token before it expires
id-token: get user-profile data (email, username, profile picture, etc.)
You should have a look at https://github.com/damienbod/angular-auth-oidc-client for connecting an Angular app to an OIDC authorization-server.
From resource-server point of view, access-tokens are the source ofr setting-up security-context, either by decoding and validating a JWT locally or with token introspection on authorization-server.
Have a look at those tutorials for such resource-servers configuration.

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

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

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.

Spring OAuth2 Password Flow , Return JWT inside HTTP Only Cookie?

I am using AuthorizationServerConfigurerAdapter to configure my OAuth2 password flow where I am successfully creating a JWT token. I am using my OAuth2 within my Spring REST backend and pairing it with my Angular 2 fronted.
I have read several articles (eg. https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage) where people are putting the JWT inside a HTTP only cookie returned to the Angular front end to prevent XSS scripting and it is of interest to me. I am confused how to integrate or intercept my jwt being returned and place this inside a http only cookie and return it.
Any Suggestions?
John
I wouldn't recommend using password flow at all, especially in a browser client. OAuth2 was designed so that you can avoid that, and thus avoid giving user credentials to an untrusted agent. If you let go of password grants, you will find that a session cookie is just as secure as your JWT cookie proposal, and it works out of the box with no funny business on client or server.

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.

Resources