Spring Security 4 2FA - spring

so I am trying to secure a web application that I built using spring mvc and security. I currently have the basic username and password from a normal custom login page working using a custom authentication provider to provide the populated authentication object that is verified against a database. What I am wondering is how do I implement a second phase of logging in that uses TOTP? I can get the the TOTP issuing and verification to work, but am unsure how to modify spring security to accept a change to authorization via a form submission of the token on a page other then the login page I've specified.

So basically what I ended up doing was using the authy api(http://docs.authy.com/) to do the TOTP delivery and verification. After the initial login I grant them ROLE_PRE_AUTH and then send them to a protected page to process the TOTP. I then used
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(auth.getAuthorities());
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), authorities);
SecurityContextHolder.getContext().setAuthentication(newAuth);
to update the roles for the user once I verified that they had a valid TOTP.

Related

How do I use OAuth2AuthorizationCodeGrantFilter to associate an email address with its corresponding OAuth2AuthorizedClient?

I have a Spring-based webapp that uses JavaMail to send and process mail via SMPT/IMAP.
I now need to add support for OAuth2 authentication, initially for GMail.
The webapp already uses Spring Security, so I've tried to integrate spring-security-oauth2-client 5.8.1
The objecive is:
user enters mail server details, and indicates that it should connect using OAuth2
on completion, a new browser window opens with a Spring Security URL e.g. http://localhost:8080/myapp/oauth/gmail
Spring Security redirects to Google to perform the authentication
Google redirects back to http://localhost:8080/myapp/oauth2/code/gmail
The access token and refresh token are received and stored, with the email address of the GMail account used as the principal
This works up to a point. In step 5, the OAuth2AuthorizationCodeGrantFilter uses securityContextHolderStrategy.getContext().getAuthentication() to get the principal prior to storing the token. In my case, this is the app user.
How can I make it the email address of the GMail user?
Is there a way to populate the OAuth2AuthorizationCodeGrantFilter with a different SecurityContextHolderStrategy via Spring-XML?
OAuth2AuthorizationCodeGrantFilter.processAuthorizationResponse():
...
Authentication currentAuthentication = this.securityContextHolderStrategy.getContext().getAuthentication();
String principalName = (currentAuthentication != null) ? currentAuthentication.getName() : "anonymousUser";
OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(
authenticationResult.getClientRegistration(), principalName, authenticationResult.getAccessToken(),
authenticationResult.getRefreshToken());
this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, currentAuthentication, request,
response);
...

Fetch user role from oauth app in authentication response

We are using Okta as a OAuth login provider.
What we wish to achieve is to fetch user role information in the authentication response itself. We are using spring security.
Currently we get following details in org.springframework.security.oauth2.core.oidc.user.OidcUser object
[Edit]
Adding content of authorities
This does not include user role information. Is there a way to get the user role information in the authentication response itself?

Auth0 with Authorization Extension not passing roles to Spring Security JWT object

I have an Auth0 project that I am using for authentication. I have modeled my Spring code based on this example.
I am trying to limit an area like this...
.antMatchers(ADMIN).hasRole(Role.ADMIN.getRoleName())
But when I add my Admin role to my user and try to log back in the JWT does not show any roles when I run...
Collection<SimpleGrantedAuthority> authorities = (Collection<SimpleGrantedAuthority>) SecurityContextHolder.getContext().getAuthentication().getAuthorities();
It is empty. How do I pass the roles to my application using Auth0
More Information
I tried decoding the JWT token and I don't see the role information even being passed....
Header
{"typ":"JWT","alg":"RS256","kid":"<Removed>"}
Body
{"iss":<Removed>,"sub":<Removed>,"aud":<removed>,"iat":<removed>,"exp":<removed>}
So why is Auth0 not passing this information.
Groups, roles and permissions won't be added to the jwt automatically. You have to
create a new rule or modify the default rule which is created after enabling (publishing) the authorization extension.
Adding roles and permissions to a JWT access token in Auth0
You should provide the granted authorities to your principal when you're authenticating it.
I assume you have a custom class that implements UserDetails and you overwrite getAuthorities(). This method should return an authority called ROLE_ADMIN. Notice that the role should be prefixed with ROLE_

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.

Two factor authentication with Spring Security like Gmail

Here, my scenario is bit similar to two-factor authentication of Gmail. When a user logs in successfully(SMS code is send to user) then he is challenged with another page to enter the SMS code. If user gets the SMS code correctly he is shown the secured page(like Gmail Inbox).
I did this bit of research on this and suggestion is to rather than giving ROLE_USER upon login, gave him PRE_AUTH_USER and show the second page where he enters the SMS code; upon success give them ROLE_USER.
However, my question is Spring has InsufficientAuthenticationException and in this scenario we won't make use of it. Will there be other better ways of implementing two factor authentication in my scenario?
P.S. I have bit of customized spring security configuration. In my Login page apart from username and password I have Recaptcha validation as well, also my authenticationProviderm authenticationSuccessHandler, logoutSuccessHandler, accessDeniedHandler all are customized.
Upon SMS code validation success, you could grant ROLE_USER authority as follows.
private void grantAuthority() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(auth.getAuthorities());
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
Authentication newAuth =
new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(),
authorities);
SecurityContextHolder.getContext().setAuthentication(newAuth);
}
The code is from copied from a blog post ,and sample application which has implemented two-factor authentication. If I had found it bit earlier it would save a lot of time !!!
Try to throw InsufficientAuthenticationException if the first level of authentication passes, then catch it with ExceptionTranslationFilter and forward to the second level of authentication page.
The two factor authentication page can resubmit the user name and password in hidden fields, together with the two factor token. In this second time the custom authentication provider would be able to authenticate successfully the user.

Resources