Set-up
We have a set of microservices and we use Spring-cloud for service registry(Eureka) and API gateway(ZUUL). We are doing the authentication in ZUUL itself, once authenticated the ZUUL would add a request header with a value (say "Authenticated"). All the request to the core services comes through ZUUL so the authentication is done in ZUUL.
Problem
Each core services are running in different ports and if some request comes to the core services directly not through ZUUL then we wanted to check whether the request header contains "Authenticated".
If it contains "Authenticated" then the request should go through.
If it does not then the response should be 403
Our Approach
We are planning to create a custom annotation #validateAuthentication and check whether the request headers contains the "Authenticated" for each value. We do not want to add any spring security dependencies to the core services.
Question
Is our approach / design doable, can you please suggest how this can be done.
can you point me to some reference material to do this.
I already raised some question [Custom Annotation in Spring with BeanPostProcessor on this subject, but could not proceed further.
If you need further details please let me know.
Thank you!
We created a library which would process the custom annotation #validateAuthentication, we created Intercepter class extending HandlerInterceptorAdapter.
We implementing our validation of the request header in preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) method.
Related
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.
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.
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.
I'm using System.Net.Http.HttpClient to talk to a RESTful service in an MVC4 application on the back end. Depending on the user making the request the authentication header will be different for communication with the RESTful service, so the values to set in the header should be cached for each user. These values may change during a session's lifetime.
I am using StructureMap for DI. Some questions:
According to this it sounds like there should be a single instance of HttpClient for all requests. Although some say directly injecting the HttpClient may be a bad idea due to it being IDisposabe, others say that it's not necessary to dispose it. So, what is the best way to inject HttpClient?
Is it possible that the single instance of HttpClient can become disposed of or invalidated during run time (maybe the REST server reboots)? If so, then I think there is no choice in directly injecting HttpClient and it must be wrapped in a manager class that will check if the HttClient instance is valid and instantiate a new client if there's a problem. The issue is that I don't see a way make that test.
Where is the best place to cache the user specific authentication header information? I don't think that passing the information to the service layer from the controller is clean, as it seems to be suggested here, so I'm thinking an HttpSession scoped injected object in the data layer is the way to go here, but would love to hear other ideas.
Create the HttpClient when your MVC4 application starts and dispose it when it shuts down. If the server you are calling with the HttpClient reboots that will not require you to create a new instance of HttpClient. TCP connections are managed independently under the covers by the ServicePointManager.
I don't understand your question regarding user specific auth information. Are you trying to get your MVC site to impersonate the user when you call to the RESTful service? If so, then just set the Auth header on each request.
I'm looking for a way to secure a web service whereby the user id is to be got from the request headers.
The ssl handshake is taken care of so I'm not sure if I need to use a subclass of org.springframework.ws.soap.security.AbstractWsSecurityInterceptor
Once the user id is got from the request then I'd like to use the standard spring security to authenticate the user as I am already doing this for spring mvc projects.
Thanks
I have used XwsSecurityInterceptor (one of the implementations of AbstractWsSecurityInterceptor) succesfully for a few projects. I'm not sure if the way of passing the userId is already defined or that you can propose using xws-security instead.
If the way of passing the id is already defined, creating a new implementation of AbstractWsSecurityInterceptor shouldn't be too much trouble. Take a look at the handleRequest method where you can access the soap request and check for the header.
You can simply wire up the new security interceptor in the endpoint mapping to debug it.