Rest call requires JSESSIONID (Spring boot, Spring Security, OAuth2, Zuul) - spring-security

I have two spring-boot processes. I have Spring Security enabled on both, and I'm using Spring Security OAuth2 SSO setup. I'm also using Eureka and Zuul to allows calls into Boot1 to call into services in Boot2. UI is using Angular with REST calls into the services, and the token being used is a Json Web Token.
This all seems to work, certainly in the UI. All the requests use the Authorization header (which contains the JWT) and the spring security filter in the services successfully parse the JWT and extracts the Security Context from it. As part of the Spring Web processing, it adds a JSESSIONID value to the client's cookie.
Recently, I only had Spring security on Boot1. When calling rest services into Boot1, which end up using Zuul to forward requests to Boot2, all I required in the rest client was to include the Authorization header with the JWT and it all worked fine.
However, I have recently added Spring Security to Boot2 (using the #EnableResourceServer annotation) and now rest calls fail unless I have both the Authorization header as well as a Cookie header that contains a JSESSIONID value. Calls don't fail, but they return empty values.
I've enabled logging to Spring Security, and it validates all correctly in Boot1. It's going into the same ZuulFilter. But there's no activity on Boot2.
Is there something in Zuul that requires a JSESSIONID value to be defined in order for it forward the request? Or is this in Boot2, where it is expecting a JSESSIONID header value due to the introduction of Spring Security filters?
--- update ---
I've stepped through boot1. From what I can see, code in the OAuth2TokenRelayFilter is throwing an exception. Specifically, the method getAccessToken is calling restTemplate.getAccessToken().getValue (line 90, version 1.1.0-RELEASE) which throws a UserRedirectRequiredException.
So, while the TokenRelayFilter has a token, it's attempting to refresh it. When it receives an exception, it's throwing a BadCredentialsException instead of using what's already been defined.
--- update 2 ---
Putting a breakpoint in OAuth2RestOperationsConfiguration, making rest calls without the JSESSIONID always ends up with a new DefaultOAuth2ClientContext to be created, as it's trying to create session-scoped beans. With the JSESSIONID, it's using a persisted DefaultOAuth2ClientContext, which will have the context.
So, is it possible to, when constructing the DefaultOAuth2ClientContext, to see if the request contains the token and uses it? Or something like this? We're trying to move to stateless services, and this seems to be a hurdle towards this.

This turned out to be an issue with the client-id values used by the different parts of the system.
Looking at OAuth2TokenRelayFilter, it is attempting to refresh the token if the client-id defined for the resource server (boot1) matches that which is defined as part of the token contained within the token provided with the request. In my case, this was true: the token was defined using the same client-id.
That really is not correct. When I update my rest client to use a token, but using a different client-id when requesting the token, then the request is forwarded correctly as expected, without the need for a jsessionid. This is exactly what I want.
I suspect that this was caused, in the end, by incorrect use of client-id values by the components of my system.

Related

How to implement custom 'OAuth2TokenIntrospectionEndpointFilter' in Spring Aauthorization server 1.0.0?

I have a default Spring authorization Server implementation. i want to modify it as per my project requirements.
I want to implement customized introspection endpoint in new spring authorization server.
I will be having different kinds of tokens, based on token type I want to validate them differently.
So I found out by default spring authorization server uses 'OAuth2TokenIntrospectionEndpointFilter', is there a way to use this class or we have to write a new class and add it to server configuration?
Thank you.
I tried doing the following.
authorizationServerConfigurer.tokenIntrospectionEndpoint(
t -> t.authenticationProvider(customTokenAuthProvider)
.introspectionResponseHandler(successHandler));
I want to know if this the right way to do or any other method exists.
It seems you have two goals:
Customize a jwt, by adding custom claims.
Obtain those claims via the introspection endpoint from a resource server.
There is actually nothing to code for on the authorization server side to achieve #2, as the introspection endpoint returns all claims for a jwt by default. I’m not clear on what you mean by “validate” here, so I’m assuming you mean validate the token and then obtain claims from it. This is what the introspection endpoint does, no customization required. Do note however that the introspection endpoint is not usually called if the resource server is decoding the jwt locally. This would only happen if the resource server is treating the token as opaque.
In order to achieve #1, simply provide an OAuth2TokenCustomizer #Bean as demonstrated in the reference documentation.
Note: I don’t see a need for a custom AuthenticationProvider. If you feel you do have a need for one, then I think some details of your use case are missing.

How to implement multiple authentication methods in Spring WebFlux Security?

I'd like to provide two ways to authenticate in my application, one is basic auth (users), and the other is some kind of token based (technical users). I understand that I need a custom ReactiveAuthenticationManager but I can't find clues on the big picture. (Actually, there are a very few insights for MVC, and none for WebFlux.)
1) How do I populate the Authentication's name and credentials in the token based approach? If I configure Spring Security to use httpBasic it's already populated. Some kind of filter needed?
2) How do I distinguish in the authentication manager where the credentials are coming from? Do I have to lookup in the userRepository and (if not found) in the technicalUserRepository too?
3) Do I have to override the SecurityContextRepository? All the tutorials do it but I don't see any reason to do so. What is it exactly? This source states that "SecurityContextRepository is similar to userDetailsService provided in regular spring security that compares the username and password of the user." but I think he means ReactiveUserDetailsService (neither UserDetailsService nor ReactiveUserDetailsService does that by the way, it's just for user lookup).
Since i am decent at Webflux and i have worked a lot with oauth2 i'll try and answer some of your questions.
1) How do I populate the Authentication's name and credentials in the
token based approach? If I configure Spring Security to use httpBasic
it's already populated. Some kind of filter needed?
A token never contains credentials. A token is something you get issued after an authentication has been done. So usually you authenticate against an issuing service. After you have authenticated yourself against that service you will be issued a token.
If its an oauth2 token the token itself is just a random string. It contains no data about the user itself. When this token is sent (using the appropriate header) to a service using spring security. Spring security has a token filter that will basically check that the token is valid, usually by sending the token to the issuer and asking "is this token valid?".
If using a jwt, its different, the jwt must contain some information like issuer, scopes, subject etc. etc. but its basically the same thing, there is a built in filter that will validate the jwt by sending it to the issuer (or using a jwk that the service fetches from the issuer so it can verify the integrity of the jwt without doing an extra request).
2) How do I distinguish in the authentication manager where the credentials are coming from? Do I have to lookup in the userRepository and (if not found) in the technicalUserRepository too?
You don't You usually define multiple SecurityWebFilterChains for different url paths. I have not done this in Webflux Spring Security, but thats how you do it in regular Spring Applications, and i don't see any difference here. Unless you are doing something crazy custom.
3) Do I have to override the SecurityContextRepository? All the tutorials do it but I don't see any reason to do so. What is it exactly? This source states that "SecurityContextRepository is similar to userDetailsService provided in regular spring security that compares the username and password of the user." but I think he means ReactiveUserDetailsService (neither UserDetailsService nor ReactiveUserDetailsService does that by the way, it's just for user lookup).
The answer here is probably no. You see Spring security 4 had very bad support for oauth2 and especially JWT. So people got accustomed to writing their own JWT parsers. When spring Security 5 came, Spring implemented a jwt filter that you can configure and use built in. But there are a lot of outdated Spring Security tutorials out there and foremost there are a lot of developers that don't read the official documentation.
They mostly google tutorials and get the wrong information and then work on that.
But easy explained:
SecurityContextRepository
If you have session based authentication (server establishes a session with a client) it will store the SecurityContext (session) in ThreadLocal during a request. But as soon as the request ends, the session will go lost unless we store it somewhere. The SecurityContextPersistenceFilter will use the SecurityContextRepository to extract the session from ThreadLocal and store it, most common is to store it in the HttpSession.
AuthenticationManager
Override this if you want to do a custom authentication process. Example if you want to validate something, call a custom LDAP, database, etc etc. It\s here you perform you authentication. But remember, most standard logins (like ldap, sql-servers, basic login etc.) already have prebuilt configurable managers implemented, when you select what login type like .httpBasic() you will get a pre-implemented AuthenticationManager.
UserDetailsManager
You override this when you want create a custom UserDetails object (also usually called Principal) In the UserDetailsManager you do you database lookup and fetch the user and then build and return a UserDetails object.
Those two interfaces are the most regular custom implementations, and are used if you need to to basic authentication/session based authentication.
If you wish to do token, you have to think about, who is the token issuer? usually the issuer is separate and all services just get tokens and validate them against the issuer.
I hope this explains some of the questions. I have written this on the bus so some things are probably wrong and not 100% correct etc. etc.

Q: Token based auth API and Javascript, can you protect other clientside files from being accessed?

Question
If you would use a similar setup as the following examples:
Simple WebAPI
Javascript OIDCClient and usermanager
Would it be possible to protect other clientside files from being accessed? Say for example i have a directory with certain files which you need a certain role to be able to access them.
Would it be possible to protect my SPA from being accessed before logging in?
Or is there a better solution which would have you end up with a protected api, folders/files on a server, SPA and a silent renew mechanism like there is in the OIDCClient?
#dmccaffery helped me out by answering my question, here is his answer for those of you who are interested.
To summarize using the OIDCClient for an SPA is certainly the way to go. Exposing stuff which needs authorization should be done by using an API. Protecting parts of your Angular App can be done using a Route guard.
The way it works is as follows:
The access token is either a JWT or a bearer token (usually) and is
added by the oidc client to every HTTP request in an authorization
header — when a web API receives a reques, the bearer token
authorization middleware will parse this HTTP header and will call the
token introspection endpoint (and potentially the user info endpoint)
to have the token validated and the users claims retrieved… if the
token was manipulated by the client, it will not be valid, and an HTTP
error will be returned (usually a 403). If the token was valid, a
claims identity is created and assigned to the http request context.
The API will now have a thread with an identity already assigned to it
that represents that user.
Also he pointed out 2 pluralsight courses which would probably be useful:
https://www.pluralsight.com/courses/building-securing-restful-api-aspdotnet
https://www.pluralsight.com/courses/oauth2-openid-connect-angular-aspdotnet

Getting rid of code/state URI parameters when using OAuth2RestTemplate

I have built a simple Spring Boot application that acts as an OAuth 2.0 client using the #EnableOAuth2Client annotation. My application is creating an OAuth2RestTemplate and the OAuth dance succeeds nicely.
The problem is that when I access my application e.g. at http://localhost:8080/someRequest (where the method serving this resource uses the OAuth2RestTemplate#getObject method to retrieve some remote resources, I end up with sth. like http://localhost:8080/someRequest?code=ABC&state=DEF in my browser.
Is there a way to get rid of these parameters using some Spring configuration magic or do I have to do that myself? I saw that the sample Tonr application suffers from the same problem.
The issue is that you have to handle the callback url that u have registered with OAuth2 provider. when you transfer code and state parameter to the provider Server for access token and refresh token, the provider sends request back to ur callback URL with access token. In callback URL u now have to check if access token is available, you redirect to the original request(u need to save original request before OAuth2 dance).
I know this stuff theoretically, but didnot find Spring-Security-OAuth2 example for handling the callback URL.
I asked same question, but didnot get any answer.
OAuth2 Dance With Spring Security
However without using spring security, i found one link which shows handling callback url manually.It will help u in understanding the flow.
Google Handle callback URl
If u found any example of spring secrity handling callback url , Share with me.
I found this as an issue with spring security oAuth2. Check this JIRA Issue

Spring Session + REST and x-auth-token

I am newbie using Spring Session.
My intend is to use Spring Session on REST API. I followed an example, however have some unclear points.
The flow I tried to make is:
1. Request to login, providing in the http header user and password.
As I've seen, the information about session saved to the Redis.
2. Request to any resource of REST API providing sessionID. It throws an exception saying, a full authentication should be given.
I thought that if I provide sessionID in the header it would be enough? But it's not so.
Is it possible to achieve the mentioned afore flow using Spring Session?
Thanks in advance.

Resources