In our current system, the security context of principals invoking the REST APIs is stored in a ThreadLocal variable. The SecurityContext can be retrieved at any level of the execution path and any method signature in any service does not need to explicitly declare a SecurityContext parameter.
Now we would like to introduce OSGi Remote Service Admin (RSA) to distribute services across different OSGi runtimes and I'm wondering what is the right approach to follow: from the RSA specs I cannot see any support from RSA service in distributing the SecurityContext, am I right? On the other hand it would be nice to propagate the context without polluting the service method signatures.
Is there any pattern to follow to achieve this?
Related
Scenario: The application sits behind an NGINX that terminates the TLS connection and does the mutual authentication with the client. The NGINX then forwards the client certificate in an X-SSL-CERT header to the spring-based application. In the application I want to access the information provided inside the certificate and also based on this create an Authentication.
Current Approach: To get it up and running, I implemented a custom Filter that extracts the header, parses the string into an X509 certificate, extracts the required information into a custom Authentication and then uses the SecurityContextHolder to add the Authentication into the SecurityContext. This works and I can access the Authentication inside my controller methods with #AuthenticationPrinciple annotation.
However, while reading the documentation I felt that this approach might not be secure and also not as it is intended by spring since there is already an X509AuthenticationFilter to use in pre-authentication scenarios.
I then came up with the idea to just place the parsed X509Certificate inside the ServletRequest attribute and use the provided X509AuthenticationFilter. I quickly ran into issues, since I do not provide an UserDetailsService.
Questions:
Is the first approach I described considered to be valid/secure?
How can I use the X509AuthenticationFilter for pre-authentication use cases
and without providing a UserDetailsService since I don't require anything to get those information
Is it secure to directly use the SecurityContextHolder to add my custom Authentication from inside the filter
How do you manage your Private / Public Keys for signing / validating JWTs in Spring Cloud environment?
The "problem":
At the moment I generate a Key Pair. Then copy Private + Public Key to my auth-server application. And also copy the Public Key to each and every Resource Server.
When I now want to implement "Key Rotation" I have to somehow populate the new keys to every service.
The idea:
Maybe I could use the spring-cloud-config-server to store and distribute the Key Pairs?
The config server already provides database login credentials. So why not store even more sensitive information there?
Question(s):
If this is the way to go: How would you implement the key pair distribution with spring-cloud-config-server?
Do you have any security concerns?
How did you solve this problem? I guess there are better solutions.
EDIT:
Maybe there's some solution using Spring Oauth's security.oauth2.resource.jwt.keyUri property for JWKs?
First of all, I would had a gateway to hide the JWT mechanism. It will allow you to revoke tokens from the gateway. If an user know about his token, you can't revoke it without revoke the public key. It will look like this :
It's easy to implement with zuul's filters and session-scoped beans.
Secondly, has you said it in comments, you can simply create a new private key to generate new tokens. But all your resource servers must be able to read all the previously generated tokens. So you need to have a list of public key on each resource servers, and each time you receive a request, you must try to verify it with each public key. Maybe you can had a public key id (and put the id on each generated token) to avoid to do dumb look for this task.
For key distribution, use spring cloud bus and rabbit mq seems right to me.
You should consider the use of Spring Cloud Consul Config instead:
Consul provides a Key/Value Store for storing configuration and other
metadata. Spring Cloud Consul Config is an alternative to the Config
Server and Client. Configuration is loaded into the Spring Environment
during the special "bootstrap" phase. Configuration is stored in the
/config folder by default. Multiple PropertySource instances are
created based on the application’s name and the active profiles that
mimicks the Spring Cloud Config order of resolving properties.
You can POST to /refresh to update your key, or watch for changes:
The Consul Config Watch takes advantage of the ability of consul to
watch a key prefix. The Config Watch makes a blocking Consul HTTP API
call to determine if any relevant configuration data has changed for
the current application. If there is new configuration data a Refresh
Event is published.
I am new to spring. My requirement is:
I need to get the user name and password in my component class. validate it with by invoking the webservices available at my client.
So I want to provide security to my password which can not be directly visible anywhere.
So how to implement this?
Please give suggestions
Spring Security can participate in many different authentication environments. While we recommend people use Spring Security for authentication and not integrate with existing Container Managed Authentication, it is nevertheless supported - as is integrating with your own proprietary authentication system.
What is authentication in Spring Security?
Let's consider a standard authentication scenario that everyone is familiar with.
A user is prompted to log in with a username and password.
The system (successfully) verifies that the password is correct for the username.
The context information for that user is obtained (their list of roles and so on).
A security context is established for the user
The user proceeds, potentially to perform some operation which is potentially protected by an access control mechanism which checks the required permissions for the operation against the current security context information.
The first three items constitute the authentication process so we'll take a look at how these take place within Spring Security.
The username and password are obtained and combined into an instance of UsernamePasswordAuthenticationToken (an instance of the Authentication interface, which we saw earlier).
The token is passed to an instance of AuthenticationManager for validation.
The AuthenticationManager returns a fully populated Authentication instance on successful authentication.
The security context is established by calling SecurityContextHolder.getContext().setAuthentication(...), passing in the returned authentication object.
This could help: http://www.viddler.com/v/c596114a
I am working on a application with a layered architecture:
Presentation - Service - Data Access
Many of the modules at this service layer need access the currently logged in user. Is it a good idea to have these modules directly access the security context to obtain the UserDetails object?
I'm thinking that if in the future modules from the Service layer need to be exposed to other application as a Web Services, getting the Security Context may not work.
You'd need to be more specific, but you generally shouldn't have the whole stack directly accessing authentication information. Instead, if it's an operation where using aspect-oriented method security isn't applicable, pass the user information to service layers as ordinary method parameters. Use appropriate mechanisms (such as #AuthenticationPrincipal) to cleanly supply authentication information to your top-level facade (Web tier or what have you).
In my spring MVC application i want to access Principal object created by spring security in my service layer. I thought about injecting it in my service classes, but I am sure it will not be thread safe.
Other option I am thinking, is to pass it to all service methods as argument but this do not look very clean to me.
What would be the better way to do this?
I think that the best approach would be to use the SecurityContextHolder.
Principal principal = SecurityContextHolder.getContext().getAuthentication();
Spring explains how it works in the documentation:
The most fundamental object is SecurityContextHolder. This is where we
store details of the present security context of the application,
which includes details of the principal currently using the
application. By default the SecurityContextHolder uses a ThreadLocal
to store these details, which means that the security context is
always available to methods in the same thread of execution, even if
the security context is not explicitly passed around as an argument to
those methods. Using a ThreadLocal in this way is quite safe if care
is taken to clear the thread after the present principal's request is
processed. Of course, Spring Security takes care of this for you
automatically so there is no need to worry about it.
Since it uses a ThreadLocal to store the current authentication, you will not have any thread safety problem.