Handling complex authorization in spring security - java

I have a spring MVC web app using pre- and post- authorization method annotations.
I have a particular method in one of my services that needs to apply much more complex authorization logic.
I notice there's a PermissionsEvaluator interface, but that appears to be intended for a more global approach to permissions rather than per-module. I suppose one could write an implementation that delegated to module-specific PermissionsEvaluators, but that seems like a lot of work.
Additionally, I'd be doubling up on a lot of effort. The authorization decision is based on intermediate state during the actual processing. If I used the PreAuthorize mechanism, I'd be generating that state once for authorization, then again "for realsies".
Is there a standard spring exception I can throw from my service layer directly? Is there some other approach I should consider?

Consider using AccessDeniedException. It is thrown internally by Spring Security when a pre- or post-condition evaluates to false. By default it generates a 403 Forbidden page.

Related

How to use caching to improve performance of OAuth2 ResourceServer in Spring Boot

I am trying to use externalized Authorization Server and Resource Server protected with OAuth2. Spring Boot allows multiple ways of securing Resource Server with externalized Authorization Server by using RemoteTokenServices or providing user-info-uri. I am using user-info-uri for validating tokens on the resource server.
With this arrangement whenever a request reaches a ResourceServer it simply makes a REST call to user-info-uri using OAuth2RestTemplate. This will overwhelm Authorization Server when there is increased traffic. That is why I want to cache the results for the first call and in the subsequent calls I will check the presence of Token in the cache. If it is present I want to simply allow the request to reach the controller else I want to call user-info-uri.
How to achieve this. I am using JWT for tokens. I know when I use JWT I could provide public key to the resource server but I am not sure if it is the good way since I have too many Resource Servers.
I tried providing UserInfoRestTemplateCustomizer Bean as suggested in here https://docs.spring.io/spring-security-oauth2-boot/docs/current-SNAPSHOT/reference/htmlsingle/#oauth2-boot-resource-server-custom-user-info but not sure what to do here.
I think you will want to supply a custom implementation of the User Service which is used by the Spring Security Context, when it converts a JWT to the AuthenticationContext. The default behavior will call out to the User Info Endpoint, should you have one configured.
It is possible to provide a custom OidcUserService when configuring the security context. From https://docs.spring.io/spring-security/site/docs/5.1.5.RELEASE/reference/htmlsingle/#oauth2login-advanced-oidc-user-service
Another alternative is apply a custom JwtAuthenticationConverter (see HttpSecurity.oauth2ResourceServer().jwtAuthenticationConverter ), which can deal with issues when converting a jwt to authentication. Check out https://docs.spring.io/spring-security/site/docs/5.1.5.RELEASE/reference/htmlsingle/#oauth2resourceserver-authorization
Hope this helps
I found that the default handling did not give me the control I wanted. These were my requirements:
https://authguidance.com/2017/10/03/api-tokens-claims/
Here is the code I ended up using, since I could not get the claims I wanted into the access token.
My example is a little complex but I hope it helps you understand some options for extending Spring Boot default processing ..

Is it a good practice to authenticate user from Database in Filter?

I am creating a Rest API (Spring Boot project) for Android App. What should be the ideal way of authenticating User from the database?
1. Querying database in Controller Class
2. Querying database in Filter Class
3. Using Spring Security
public class TokenValidationFilter implements Filter {
Connection connection = null;
#Override
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain chain)
throws IOException, ServletException {
final String accessToken = req.getHeader("accessToken");
final String userId = req.getHeader("userId");
// Do Sql Query to Authenticate User
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
}
You shouldn't be needing to add your own Filter.
When you use Spring security, it works by adding a filter only, for e.g., BasicAuthenticationFilter. And on top of this it allows you to manage things which otherwise you'd need to do on your own.
For e.g., it allows you to use the Authenticated principal by simple means of SecurityContextHolder.getContext().getAuthentication() as it works on the basis of ThreadLocal you can use this anywhere in your code.
What about managing Authorization for different URLs? Or managing CORS config?
All these things are achievable through a simple builder pattern for you while configuring Spring security using the framework.
Plus, if you want to go for OAuth later on, the security framework is integrated with it, you can get it working very easily by using AuthorizationServer and ResourceServer
Even for the simplest of configurations for a basic authentication you should go with using the security framework, rather than authentication using a be-spoke solution.
Also you can think that there are other things integrated with the security framework like Auditing your database transactions modified by which user, etc.
What you'll be writing (and going to refactor in future) in your own Filter is already written in the framework for you to use.
You should definitely avoid authenticating users in a Controller class.
Spring Security is the most recommended way for authenticating users in a Spring Boot application.
It is relatively easy to use and based on standard servlet filters. This way you can avoid writing your own custom filter.
Allows fine-grained control over endpoint and HTTP method combination.
Allows for different types of authentication - Basic Authentication, OAuth2, MTLS, etc.
Allows you to ignore security for certain endpoints.
To configure spring security, create a custom security configuration class which extends WebSecurityConfigurerAdapter.
It's relatively easy to configure the database with Spring security by writing a custom AuthenticationProvider. You make the calls to the database within this provider.
Querying database in Controller Class
No, doing like this will make your business controller tighly coupled with the authentication mecanism which is not the purpose of such kind of components
Querying database in Filter Class
I assume you talk about Servlet Filter class. This way you'll probably reinvent the wheel and end up with a lot of home-made boilerplate code. And as you talk about Spring Security point 3, I assume that you have a Spring backend.
Using Spring Security
Definetely the way to go if you have a Spring Backend. Spring security provides some standard authentication mecanism (BASIC auth for instance). You can add some Spring Security extension like OAuth2 or SAML if have such requirements. It is a widely used framework, so finding help should not be a problem.
Besides, Spring Security allows you to create your own Security Configuration in case none of the standard is ok for you.
From a mobile app point of you, setting a Basic Authentication to get Json Web token and then access the API with the token should be pretty straight forward and maintenaible with Spring Security. Or you can rely on some standard like OAuth2 - OpenIdConnect. Either way should be ok with Spring Security.
I believe this is not a good software design practice to connect to the database on either the Controller or the Filter. This is not market practice. The most usual is to create a Data Access Object (DAO) that will be responsible for doing the queries properly. You can check out more details of this design pattern here: https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm
The connection data, such as UserID, Password, Token, etc. are usually stored in an application configuration file (web.xml, AndroidManifest.xml or persistence.xml) and must be retrieved at run time. And the connection can be made via a parent class, for example GenericDAO, and be retrieved as an inherited attribute. Take a look here: How do I implement a DAO manager using JDBC and connection pools?
Organizing your code this way will help you split the responsibilities of your system, depending on the nature of each layer.

Play Framework with Spring Security?

I'm new to the Play framework and want to implement some authentication for my webapp.
I have already some experiences with Spring and Spring Security and want to use this, but I'm not sure if this makes sense, because the Spring Security is mainly for the ServletAPI.
Does it makes sense to integrate Play with Spring Security?
Thanks.
After further searches I have found this post:
https://groups.google.com/d/msg/play-framework/K7l6vHa0UUA/MYDlsaIfJEMJ
It seems to be possible, but still a lot of Play specific implementations (filter, etc.) have to be done.
You should - perhaps - look on Deadbolt 2. It is dedicated solution, so it will run out of the box.
Yes, it makes sense to use spring security with play. Spring security has been used in lots of projects, and writing secure code is much harder than it looks.
You have two problems. One is authentication. You need to do something to achieve authentication. This means either twiddling play so it becomes a stateful container (but then again, why would you use play at all in this case?) or throwing spring-security-web and deadbolt very hard at each other so you use spring for authentication, but integrate with the cookie goodness of play so you don't have to store stuff in a session object on the server side. I would suggest you fetch the authorities that drive authorization from somewhere for every request, though. You want to keep the session size down.
The Security object also has some good hints on how to go about doing this.
Authorization in spring is not hard to handle as long as you have got an authentication object stored in a threadlocal or something. Create something that calls the spring access decision voters in a wrapper - something like
def handleRequest ... {
withAuthorization(<list of roles necessary>) {
service code
}
}
should do the trick. For added goodness, add a flag in a threadlocal when you do this - the presence of the flag makes it easy to write assertions in your tests that require authorization to have taken place. This is one of the biggest security issues for developers out there - see https://cwe.mitre.org/data/definitions/862.html
Hope this helps.

HttpServletRequestWrapper and Filter lifecycle in tomcat

I am coding a Tomcat application and am authenticating against Google's oauth2 services. I was originally going to write a simple Filter to do the authentication but there is no way to set the user principal in a Filter. From my understanding you have to have the Filter call an implemented HttpServletRequestWrapper and set it inside of that class as seen in this post
I'm pretty sure Tomcat only instantiates one Filter of each type you may have defined and all requests go through this single object down the Filter chain (correct me if I'm wrong).
In the linked to code, is it correct for the code to call
next.doFilter(new UserRoleRequestWrapper(user, roles, request), response);
where every request is instantiating a new UserRoleRequestWrapper? Should this Filter instead have one request wrapper instatiated that gets shared amonsgst all requests? I'm having a hard time finding documentation on the specs of classes such as these.
I don't think that a Filter is what you're looking for. Doesn't seem right for this purpose... Filters weren't created for such use cases; they were created for pre/post processing requests and responses, with emphasis on manipulating the actual request/response data, rather than other aspects of the client-server communication (such as security). Remember, authenticating a user may have further repercussions than just handling HTTP request cycles. Security ties into the JavaEE framework in a lower level than HTTP cycles.
If you want to authenticate against oauth2, you should be far better off implementing some sort of a JAAS implementation for it, and plug it into Tomcat.

Securing a stateful web service

We are planning on developing a layer of REST services to expose services hosted on a legacy system. These services will be used by a classic web application and native mobile phone applications.
This legacy system is secured in such a way that an initial username + password authentication is required (a process that can take 5 to 10 seconds). After the initial authentication, a time-constrained token is returned. This token must then be included in all further requests or else requests will be rejected.
Due to a security requirement, the legacy security token cannot be returned outside of the REST service layer. This means that the REST service layer needs to keep this token in some form of user session, or else the expensive username + password authentication process would need to be repeated for every call to the legacy system.
The REST service layer will be implemented using a Java 6 + Spring 3 + Spring Security 3 stack. At first sight, it looks like this setup will run fine: Spring-based REST services will be secured using a rather standard Spring Security configuration, the legacy security token will be stored in the user's HTTP session and every call will retrieve this token using the user's session and send it to the legacy system.
But there lies the question: how will REST clients send the necessary data so that the user's HTTP session is retrieved properly? This is normally done transparently by the web browser using the JSESSIONID cookie, but no browser is involved in this process. Sure, REST clients could add cookie management to their code, but is this an easy task for all Spring RestTemplate, iPhone, BlackBerry and Android clients?
The alternative would be to bypass the HTTP session at the REST service layer and use some other form of user session, maybe using a database, that would be identified using some key that would be sent by REST clients through a HTTP header or simple request query. The question then becomes, how can Spring Security be configured to use this alternative session mechanism instead of the standard Servlet HttpSession?
Surely I am not the first dealing with this situation. What am I missing?
Thanks!
There's nothing magical about cookies. They're just strings in HTTP headers. Any decent client API can handle them, although many require explicit configuration to enable cookie processing.
An alternative to using cookies is to put the JSESSIONID into the URL. I don't know anything about spring-security, but it seems that that's actually the default for at least some types of URL requests, unless disable-url-rewriting is explicitly set to true . This can be considered a security weakness, though.
Unfortunately authentication is highly problematic -- a bit of a blind spot in terms of web standards and browser implementations. You are right that cookies are not considered "RESTful" but purists, but even on fully-featured browsers avoiding takes quite a bit of hackery, as described in this article: Rest based authentication.
Unfortunately I haven't done any mobile development, so I can't suggest what the best compromise is. You might want to start by checking what authentication models each of your targetted platforms does support. In particular, two main options are:
HTTP authentication (ideally "digest", not "basic")
Cookies
One possibility would be to provide both options. Obviously not ideal from a technical or security point of view, but could have merits in terms of usability.

Categories

Resources