Integrate Shiro with pac4j jax-rs implementation - java

I am using pac4j's jsx-rs implementation to enable only AUTHENTICATION for my application. For authorization, I want to use Shiro. But I am not sure how to integrate Shiro with pac4j.
Currently, I have a Feature which does the necessary JAX-RS Configuration and I have made it a Provider
The following are the features and providers that I have registered.
featureContext
.register(new JaxRsConfigProvider(config))
.register(new Pac4JSecurityFeature())
.register(new Pac4JValueFactoryProvider.Binder())
.register(new ServletJaxRsContextFactoryProvider())
.register(new Pac4JSecurityFilterFeature(false, null, "keycloakoidcclient", "callback", false))
I am using Shiro's AuthorizationFilter to do the authentication part. By this I mean I am creating a token based on the logged in user. I have registered this filter using Guice's ServletModule. But I am unable to get a hold of the logged in user. I am trying to inject Jersey's SecurityContext using #Context. But the filter ordering is messed up. The AuthorizationFilter gets invoked before authentication is complete. Hence the SecurityContext is always null.
Is there a better way to integrate Shiro with pac4j?

Shiro provides its own Feature implementation to be used with JAX-RS. Adding that module dependency to the project does the trick.
And to get the user context from pac-4j, I implemented an Authorizer where I get the OIDC profile injected. I created a custom user profile and provided it to Shiro like this:
SecurityUtils.getSubject().login(new DemoToken(profile));
This way Shiro gets the user profile and then can carry on the authorization.

Related

External SSO with spring security

I am working on an application which requires an integration of a proprietary SSO with spring security. The application uses spring boot, and the requirement is that we use the authentication from internal proprietary SSO module and authorization from the existing application. The existing application's authentication system has to be replaced with internal proprietary SSO's authentication module. I went through a few documents and understood that it is possible as the spring is module based.
While working on the application I noticed that we are using FilterRegistrationBean to initialize one filter, and another filter is added to the chain via WebSecurityConfigurerAdapter's configure(HttpSecurity http) method.
Can someone please let me know if this will be treated as two different chains? If so, how are the chains checked for filtering out the details?
Can I just remove the filter we are adding via WebSecurityConfigurerAdapter's configure(HttpSecurity http) method and replace the existing filter that is registered via FilterRegistrationBean with the filter (with highest precedence) from internal proprietary SSO?
OK so we do exactly what you're asking for in one of our systems. We have this working in Spring boot 1 and 2. These are the steps to take.
Create a bean extending AbstractPreAuthenticatedProcessingFilter. Implement getPreAuthenticatedPrincipal and getPreAuthenticatedCredentials to extract the authenticated user and optional credentials (e.g. a certificate) from your SSO system. Create a FilterRegistrationBean for this filter bean otherwise thanks to spring boot's component scanning it'll end up in the main filter chain as well as the security filter chain.
Create a user details (authorization) service bean implementing AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken>. Override loadUserDetails to take your authenticated token and use it to add permissions in the form of GrantedAuthority lists.
In your WebSecurityConfigurerAdapter bean subclass do the following:
Inject your subclass of AbstractPreAuthenticatedProcessingFilter and also your subclass of AuthenticationUserDetailsService.
Add a class member of type PreAuthenticatedAuthenticationProvider and initialise it with new (it's not a bean).
In configure(HttpSecurity) initialise your filter bean with an authentication manager: yourBean.setAuthenticationManager(authenticationManager()) then ensure your filter is included:
http.addFilter(yourBean)
.authorizeRequests()
.requestMatchers(...)
Override configure(AuthenticationManagerBuilder) and initialise the PreAuthenticatedAuthenticationProvider you created in step (2) with your implementation of the authentication and authorization beans.
this.preAuthProvider.setPreAuthenticatedUserDetailsService(this.userDetailsService);
this.preAuthProvider.setThrowExceptionWhenTokenRejected(true);
authBuilder.authenticationProvider(this.preAuthProvider);
That should be all. Hope that helps.

Requiring password even when logged in for certain resources in Spring Boot webapp

There is plenty of documentation online for how to secure Spring webapps and microservices, but I haven't found a way to add an extra password request for a few limited pages in an app.
For example, Amazon knows who I am and I can buy something with one-click from my laptop. But if I want to look at my account page, I have to log in.
How can I have multiple levels of user access in my Spring Boot app, with different expiry for each level? Do I need to apply this to the microservices that back my app, as well?
Spring security has fine-grained configuration support per resource, so you can add your custom authentication manager to challenge user once again.
You can use spring custom security and configure some endpoints which needs to pass the spring security authentication and some you can configure to be invoked without authentication check.
you can extend AbstractAuthenticationProcessingFilter of spring security and override the requireAuthentication method of the above filter to configure which endpoint you want to skip authentication.
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
if (request.getRequestURI().toLowerCase().contains("ToBeSkipped")) {
return false;
}
return true;
}

Spring OAuth2 explain Authorization server configuration

I am trying to implement OAuth security and met a problem that for me is not clear enough configuration class.
While implementing AuthorizationServerConfigurer i have three configurers:
ClientDetailsServiceConfigurer used to provide the way how and from where to get client details. As an example, it can be service which provides registered clients from the database.
When it comes to AuthorizationServerSecurityConfigurer and AuthorizationServerEndpointsConfigurer I am not sure what they do or how they should be configured. In the documentation it said only:
AuthorizationServerEndpointsConfigurer: defines the authorization and
token endpoints and the token services.
Maybe someone can explain in simple words what these two configurers do, or what they are used for.
AuthorizationServerConfigurer's javadoc is more informative than the linked documentation. AuthorizationServerSecurityConfigurer, as its name suggests, configures the security of the Authorization Server itself. For example you can override the OAuth endpoints security such as /oauth/token, provide an access denied handler or restrict to SSL access. Here are what the documentation says about it:
Configure the security of the Authorization Server, which means in
practical terms the /oauth/token endpoint. The /oauth/authorize
endpoint also needs to be secure, but that is a normal user-facing
endpoint and should be secured the same way as the rest of your UI, so
is not covered here. The default settings cover the most common
requirements, following recommendations from the OAuth2 spec, so you
don't need to do anything here to get a basic server up and running.
As for AuthorizationServerEndpointsConfigurer:
Configure the non-security features of the Authorization Server
endpoints, like token store, token customizations, user approvals and
grant types. You shouldn't need to do anything by default, unless you
need password grants, in which case you need to provide an
AuthenticationManager.
Here is a sample from one of my projects:
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.tokenStore(jwtTokenStore())
.tokenEnhancer(tokenEnhancer());
}
Here I provided a JwtTokenStore as my TokenStore and a AuthenticationManager since I was using Password Grants.
I am using spring-security-oauth, there is a helpful documentation maybe help you :
projects.spring.io/spring-security-oauth/docs/oauth2.html

Spring security #PreAuthorize("hasAnyRole('....')")

I am using spring security #PreAuthorise to check who and who cannot access methods in my service layer. It works really well. Usually my service methods are annotated with
#PreAuthorize("hasAnyRole('MY_USER_ROLE')")
My problem is that I have a war file made up of several jar files. Each of these jar files is responsible for a segment of business logic. I now want one of the services in one jar file to access another service in another jar file. This gets rejected because of the permissions. If I comment out the permission then everything works.
Is there anyway I can authenticate via spring before calling this service? (Perhaps with a dummy user?) Or perhaps turn off the security for jars within the same application? Or is my design wrong?
Anyone else has this sort of problem? What design should I use instead?
You need to give the thread that invokes the service (in the other jar) the permissions that are required by #PreAuthorize (for the invoked service).
If the thread is triggered in an web application by an user request, then this are normally the users permissions.
But if the thread is triggered by some timer service then you need to give them the right authentication
Authentication authentication = new UsernamePasswordAuthenticationToken("dummy", "password");
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(authentication);
I believe this is a good example where you should use Spring security #Secured annotation
What is #Secured annotation?
From version 2.0 onwards Spring Security has improved support substantially for adding security to your service layer methods. It
provides support for JSR-250 annotation security as well as the
framework's original #Secured annotation.
Source: Spring Security 3.1 Reference 2.4 Method Security
#Secured annotation allows you to put restrictions in your methods. For example, you can authorize a get() method to be accessible by all
registered users. But for the edit() method, you can mark it be
accessible by admins only.
Check out some tutorials at:
http://burtbeckwith.com/blog/?p=1398
http://krams915.blogspot.in/2010/12/spring-security-3-mvc-using-secured.html

spring authentication provider VS authentication processing filter

both spring authentication provider and authentication processing filter also need to register with authenticationManager?
authentication provider i can use custom-authentication-provider tag
but what is different spring authentication provider and authentication processing filter ?
The authentication manager uses all authentication providers to authenticate authenticationtokens it has to authenticate.
The authentication processing filter just adds a token (username password). Other filters add tokens too. For example the AnonymousProcessingFilter.
The idea is to seperate token generation from token authentication. That way you could implement stuff like authentication against multiple sources easily.
The regular case is one provider per token generator.
According to Spring Security Architecture the process is:
Filters are used to intercept the http request and do some checks
Some filters are doing the check for authorization information in the request headers, body, cookies, etc. You can call them Authentication Processing Filter
The actual job for authentication is done by another partie called Authentication Provider, because a filter will call a provider if the implementation needs it.
It can happen that between the filter and provider can stay a Provider Manager, that can call all providers one by one and see if some of them can handle it, if so: then do so.
See an example here: a filter is calling a provider manager to find a provider who supports this authentication and if so the do authenticate
RememberMeAuthenticationFilter
ProviderManager
Here you can find a nice example on how to implement a custom filter: Custom filter #Baeldung
Please consider that filters are calling Provider Managers or Providers only if they are coded like that. There's no rule to enforce that.

Categories