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.
Related
Sorry for such novice question.
I am fairly new to web security.
Can someone please explain to me, why do we need JWT token authentication for web api (REST) when I could include { username | email } / password for every single API request?
Mostly, it's a separation of concerns thing. JWTs are a way to authorize a request, whereas username/password is a way to authenticate. The key difference is that authentication is something you should ideally only have to do once, and it should be done by a dedicated endpoint responsible for that. For every other request, you're simply confirming the authorization you received from that initial authentication.
If you were to send username and password with every request, every endpoint then would have to handle authentication logic, which would be a nightmare. Using a JWT, the endpoint can simply verify that it's valid and move on to what it's actually responsible for.
JWTs are just one method of authorization. In a traditional website-style application, this would be handled by a cookie. This then enables the user to login once, and then proceed to browse protected areas of the site without having to login again. The equivalent of what you're suggesting would be essentially like forcing the user to login again everytime they clicked a link, just to view that next page.
I am using spring security to authenticate a user. The user is authenticated by a third party and will already be authenticated when he reaches my application.
To implemented this, I have simulated a Authentication object.
I don't have any username and password and instead just have identifier. I check if this identifier is valid or not using my custom code.
My query is as follows:
Do I require a username and password to create a authentication object.
I have done without providing username and password and my application works fine.
I just want to ensure that I am using spring-security correctly.
Is there any impact of not putting username and password in Authentication object. I read below in AbstractUserDetailsAuthenticationProvider:
// Ensure we return the original credentials the user supplied,
// so subsequent attempts are successful even with encoded passwords.
I have also implemented a custom provider.
What does above comments means?
Is my approach correct?
The Authentication interface in Spring Security represents a token for carrying out validations against the configured security rules and the current call context. This interface has six methods of interest - getPrincipal, getCredentials, getDetails, getAuthorities, isAuthenticated and setAuthenticated.
Since you are authenticating users on your own, you should be mostly concerned with calling setAuthenticated(true) at an appropriate stage in the flow so that isAuthenticated starts returning true to indicate an authenticated user. Additionally, you may add GrantedAuthoritys to the Authentication for any role-based checks to work correctly.
However, it will be useful to make sure that getPrincipal (username in the case of form login) returns a unique value per user or per session. This will prevent the possibility of user sessions getting interchanged due to non-unique principal, which is used by the framework to identify users uniquely.
You may leave getCredentials and getDetails unimplemented. In fact, getCredentials (password in the case of form login) should be left unimplemented in your case because your application does not have the credentials used to actually authenticate the user; plus, it is a security risk to keep the credentials around after the user has been authenticated successfully.
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.
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.
I'm a newb to spring security and I'm not sure where to start. I have requirements to have a multi-page authentication. The first page authenticates the username, if the username exists the web app progresses to the password page. (site image) The second page authenticates the password, if successful then the user is authenticated. I'm not sure how to fit this into spring auth. Do I add multiple login-filters and authenticationproviders ? If I add multiple authenticationproviders, will I be authenticated after the first login ?
Page 1: User enters username. Submit this to your own controller where you check if the user exists. If the user exists, display page 2, pass the username in the model. You better not include Spring Security authentication in this step.
Page 2: User enters password. Use a readonly or hidden field to keep track of the username. Submit the form to Spring Security form login filter. You don't need multiple authentication providers.
Note: This approach has an information "leak"; any visitor can check whether a username exists in the system or not.
It depends on the kind of your authentication:
JDBCAuthentication
You can do with #holmis83 suggests.
LDAPAuthentication:
I am afraid tht you can't do that.