Spring Security Recommended Design To Request User Login to Different User With Different Role - spring

I have the following use case and need recommendations on the proper implementation. To be clear can this be done through configuration or do I need to implement new code?
Business Use Case
The business wants to allow a user to login via social media sites and access some of their pages. But in order to access pages that deal with $$ the user must login via the applications local account.
Technical Use Case
Allow users to login via Facebook or other provider and provide role USER_PARTIAL_RIGHTS
If user accesses a page with role USER_FULL_RIGHTS prompt the user to login to an account that is a local JDBC stored account.
This authentication must also ensure that the page is protected by USER_FULL_RIGHTS role and not other roles.
I am using grail spring security plugin, but I am expecting to have to customize the plugin.
So what are recommendations for doing this? A couple of ideas that I have are:
Technical Ideas
custom spring access denied handler
custom access denied controller instead of the stock jsp page

From what i understand from your question, here is my suggestion.
For login via Facebook use Spring Social. Here is the documentation. The implementations are straightforward. Write a custom signin method and set the authorities for partial rights, something like this:
public void signin(String userId) {
authorities = new ArrayList<GrantedAuthority>();
//set your partial rights authority
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(userId, null, authorities));
}
And do a method level security implementation using the #secured annotation to access the page that needs full rights. Something like this
#Secured("USER_FULL_RIGHTS ")
yourMethod(){
//code
}
This would prompt for a login where can use authentication from applications local account.

What we ended up implementing is a controller that looks at the role and redirects the user to the correct landing page. Kinda messy, but it works.
Collection<GrantedAuthority> inferred = SpringSecurityUtils.findInferredAuthorities(SpringSecurityUtils.getPrincipalAuthorities());
if(ifAnyGranted('ROLE_FOO', inferred)) {
redirect(controller: 'foo',action: 'home')
return
}

Related

Authorization on Dynamic Web API Controllers

How to use AbpAuthorize or AbpAllowAnonymous attributes?
What's the default behaviour for these controllers?
Could not find in docs.
AbpAuthorize is just used to check for permissions. This for example:
[AbpAuthorize("Administration.UserManagement.CreateUser")]
public void CreateUser(CreateUserInput input)
{
//A user can not execute this method if he is not granted for "Administration.UserManagement.CreateUser" permission.
}
Checks if he has the Administration.UserManagement.CreateUserpermission. Before allowing the user to execute the method.
AbpAuthorize, if left without parameters just checks if the user is logged in.
[AbpAuthorize]
public void SomeMethod(SomeMethodInput input)
{
//A user can not execute this method if he did not login.
}
This for example, will check if the user is logged in before he can execute the method.
Try reading here for more detailed stuff:
https://aspnetboilerplate.com/Pages/Documents/Authorization#DocCheckPermission
It will explain it better than me.
You can add these attributes to your Application Services or Controllers derived from AbpController. Basically it uses interception and checks the current user has the required permission or not. (Hence an authenticated user is needed to check a permission). So first you have to authenticate the user to dive into these permissions.

How to bypass the login form page in spring security?

I am using a custom UsernamePasswordAuthenticationFilter (which is called before the login page). I am considering the session id of the already logged in user in this filter. If the auth_token exists for the corresponding session id I want to bypass the login page.
How can I do that ?.
You just have to populate the security context with an authenticated Authencation once you have checked the auth_token. Something like that (in your custom filter):
... // first check the existence of the auth_token and extract some information from it like user name and roles
String login = ...
String role = ...
PreAuthenticatedAuthenticationToken preAuthenticatedAuthenticationToken
= new PreAuthenticatedAuthenticationToken(login, auth_token, Collections.singleton(new SimpleGrantedAuthority(role)));
SecurityContextHolder.getContext().setAuthentication(preAuthenticatedAuthenticationToken);
//At this point : the security context contains an authenticated Authentication and other security filters won't have any impact anymore
I don't say it is the best approach for your needs, but it will works with a more or less standard spring security configuration.

Escaping a few views from authentcation (Guest Users) in Django-rest-framework

I've set a default authentication class as I needed most of apis to be authenticated before being accessible. However, I need login api to be available to all user.
I don't see negative authentication class in django-rest-framework.
How do I let my login api to be available to guest users while not making view level authentication_classes declarations?
This problem arose because I'm not using django's User model. How do I create AnonymousUser instance for my custom User model (not inherited from django's user model) and then permit that user to interact with the apis?
EDIT
Mark Galloway reminded me of mentioning the same issue with permission_classes.
Authentication alone does not prevent a user from accessing resources. A combination of authentication and permissions is the actual determiner for this. For example, if your permissions are set to 'permissions.IsAuthenticatedOrReadyOnly' then users who fail to authenticate (eg/ no valid token) can still access the retrieve and list endpoints.
How exactly you want to define your permissions is up to you. For most of my implementations I use a global permissions setting but tag my log in endpoint with view-level AllowAny permissions. Additionally, view-level authentication for a specific is the only way to override global authentication settings.
For example:
class login(viewsets.GenericViewSet):
permission_classes = (permissions.AllowAny,)

JSP/Tomcat secure login with sessionstorage

I have a system running on Tomcat, with HTML/JSP in front-end, and java/Spring/Struts in backend.
I made a login-feature where the user enters his username and password.
In backend, I validate the username and password to the stored user in DB.
If match, I store the username in HTTPsession:
session.setAttribute( "username", name );
Then, on every class-action in backend, I add the following code:
HttpSession session = request.getSession();
if(session.getAttribute("username") == null) {
return mapping.findForward("invalidUser");
}
the invalidUSer-mapping redirects the user back to the login-page.
How secure is this?
Is there a way to check the httpsession without adding my validation-code to every class?
Do you guys have tips (or examples/tutorials) on how to do this differently? The system is already created and in production, so I do not want to do too many architecural changes.
As you are already using Spring in your project, you may want to look into Spring Security to replace your bespoke security mechanisms. You can configure it to protect certain resources within your application, authenticate against bespoke database back-ends, LDAP directories, etc. This will allow you to remove all manual checking of the session to see if the user is authenticated, and will redirect anonymous users to the specified login page when they attempt to access protected resources.
Along with the spring security filter definition in web.xml, the configuration can be specified in a single spring-security.xml file (imported into your root app config) using the security:http namespace to define the login page, protected resources, logout page, security headers etc. You could use a org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl instance configured as a bean to define the user service which can be referenced by the authentication-provider - see the docs, its very flexible.
Hope that's useful.

Spring Security privacy policy message after successful login

I'm looking for a way to include a warning page after a successful login in my spring security app. The warning page will display a message to the user who has already successfully logged in that by pressing "Yes" they agree to the terms and conditions bla bla... I want to ensure that they can't access any resources unless they click "Yes".
How can I include this in my journey? I've already implemented a custom success handler if that would help.
Thank's in advance.
This will be a matter of choice to implement it.
You can do so by creating custom implementation of UserDetailsService. This interface has only one method namely loadUserByUsername, which returns instance of UserDetails which is again an interface from Spring Security. By implementing UserDetails interface to your User POJO/Entity you can have access to some useful messages which can check user is active or enabled or credentials are non expired, etc. Have a look at javadoc. From there you can handle this that the user has accepted terms and conditions or not.
Another way is to create custom SpEL to check whether user has accepted terms or not.
So the solution is actually somewhat simple. Unfortunately, took a couple of days trying to get to the simplest solution.
Essentially what I did was: In my custom UserDetailService class, I overrode the createUserDetails method and set the combinedAuthorities to be:
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new GrantedAuthorityImpl("ROLE_NEEDS_TO_ACCEPT_POLICY"));
combinedAuthorities = authorities;
So at the moment, this is their only role, i.e. they aren't authorised to access any of the other resources as mapped in my spring security xml.
In my custom success handler, I forwarded them onto /policy, which can bee seen by users with role ROLE_NEEDS_TO_ACCEPT_POLICY, which is mapped to a Controller which returns a jsp for them to accept/decline the terms and conditions etc...
If they clicked yes, their response is captured in the same controller's post method which then load's their actual roles and grants them.
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(auth.getAuthorities());
authorities.add(new GrantedAuthorityImpl('FETCH_ACTUAL_FROM_ROLES_TABLE'));
Authentication newAuth = new UsernamePasswordToken(auth.getPrincipal(),auth.getCredentials(),authorities)
SecurityContextHolder.getContext().setAuthentication(newAuth);
And that's it... Hope this helps someone.

Resources