Spring security auto login after registeration - spring-security

I create a spring MVC application that uses spring security for authentication, here's the spring-security.xml
<http use-expressions="true">
<form-login login-page="/homepage.jsp" default-target-url="/homepage.jsp" authentication-failure-url="/homepage.jsp?login-success=false" />
<logout logout-success-url="/homepage.jsp" />
</http>
<authentication-manager alias="authenticationManager" >
<authentication-provider>
<password-encoder hash="sha" />
<jdbc-user-service data-source-ref="marketDataSource"
users-by-username-query="
select email_address, password, '1'
from user where email_address=?"
authorities-by-username-query="
select email_address, 'ROLE_USER' from user
where email_address=?"
/>
</authentication-provider>
</authentication-manager>
when a new user try to register, he fill in registration from and press submit, that will create a new user, if the registration successfully completed, I try to authenticate the registered user using this method:
private void authenticateUserAndSetSession(User user, HttpServletRequest request) {
List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
grantedAuthorities.add(new GrantedAuthorityImpl("ROLE_USER"));
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
user.getEmailAddress(), user.getPasswordSha(), grantedAuthorities);
request.getSession();
token.setDetails(new WebAuthenticationDetails(request));
try {
Authentication authenticatedUser = authenticationManager
.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authenticatedUser);
} catch (Exception e) {
e.printStackTrace();
}
}
I checked this post Auto login after successful registration to make the previous method, but when I try to use it, it throws Bad Credential Exception, what's wrong with this solution?

I had been faced with the similar problem. In legacy code the password was hashed by hand.
The better choice is to store object of User class (may be it is a plain form binding) with the plain password and clear it later. Clearing credencials is the responsibility of spring-security too (interface org.springframework.security.core.CredentialsContainer).
If it isn't possible remove tag of encoder or use the plain text encoder <password-encoder hash="plaintext"/>.

Related

LDAP authentication without managerDN and manager password

I am writing an application in Java Spring framework to perform Active Directory LDAP authentication.
I am succeeding in connecting to my organization LDAP.
Here is the configuration settings:Spring-security.xml
<!-- This is where we configure Spring-Security -->
<security:http auto-config="true" use-expressions="true"
access-denied-page="/oops">
<security:intercept-url pattern="/auth/*"
access="isAuthenticated()" />
<security:logout invalidate-session="true"
logout-success-url="/" logout-url="/logout" />
</security:http>
<security:authentication-manager>
<security:ldap-authentication-provider
user-search-filter="(&(sAMAccountname={0})(objectCategory=user))"
user-search-base="DC=am, DC=example, DC=com" group-search-filter="(&(sAMAccountname={0})(objectCategory=group))"
group-search-base="DC=am, DC=example, DC=com">
</security:ldap-authentication-provider>
</security:authentication-manager>
<security:ldap-server url="ldaps://myserver.am.example.com:4567"
manager-dn="CN=Johnson \, Mitchell, OU=San Francisco,DC=am,DC=example,DC=com"
manager-password="sdvsdvsvs" />
My question here is that,is there any way to authenticate LDAP without supplying manager-dn and manager-password in security:ldap-server tag.
Please provide a solution to this.Thanks in advance.
Yes it is possible: you can let the user who is actualy logging in connecting to the LDAP himself to test his credential and fetch its userdata.
AuthenticationManager configuration:
#Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider = new ActiveDirectoryLdapAuthenticationProvider(domain, url, rootDn);
activeDirectoryLdapAuthenticationProvider.setSearchFilter(searchFilter);
auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider);
}
Spring security does two things:
Let the user log in with his username and password
Find the user to fetch user info, groups, etc. For this step, you must specify a searchFilter that can find a user based on it's username, like "userPrincipalName={0}" where {0} is the provided username.
Define an administrative user who has the necessary permissions, and use that. You certainly shouldn't use the managerDN for anything in your application.

Automatically create new user account on login

I managed to get my application working with Active Directory (basically LDAP) using spring-security, like this:
<authentication-manager>
<authentication-provider ref="ldapActiveDirectoryAuthProvider" />
</authentication-manager>
<beans:bean id="grantedAuthoritiesMapper" class="mypackage.ActiveDirectoryGrantedAuthoritiesMapper"/>
<beans:bean id="ldapActiveDirectoryAuthProvider" class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<beans:constructor-arg value="xxxx.xxx.xxxx" />
<beans:constructor-arg value="ldap://xxx.xxx.xxx.xxx:389" />
<beans:property name="authoritiesMapper" ref="grantedAuthoritiesMapper" />
<beans:property name="useAuthenticationRequestCredentials" value="true" />
<beans:property name="convertSubErrorCodesToExceptions" value="true" />
</beans:bean>
But by doing only this I need to have the users registered both in my application and in the Active Directory before-hand. I would like to be able to before the user logs in (but after the Active Directory validation) to see if he exists in my database and if he doesn't create a new user in my application and then proceed as normal.
I believe I need to create a preAuthentication provider, but I don't know exactly where I can insert my own class to code the checking and registration of the user.
Optimally I would also like to check for a specific authority before creating the user.
Can anyone give me a hand?
In the end I had to change my authentication handler onAuthenticationSuccess. In spring there are authentication and login in the lifecycle of the login process. During authentication the user is, well, authenticated, but not yet logged into the application (ie only its credentials were deemed valid, but the rest of the application is not aware of the user yet.)
I changed my security.xml to:
<beans:bean id="authHandler" class="mypackage.activedirectory.ActiveDirectoryAuthenticationHandler"
...
<form-login login-page="/login" authentication-failure-handler-ref="authHandler"
authentication-success-handler-ref="authHandler" />
And here is the class:
public class ActiveDirectoryAuthenticationHandler extends MyAuthenticationHandler {
#Autowired
private UserService userService;
#Override
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication auth)
throws IOException, ServletException {
String username= auth.getName();
User user= userService.findByUsername(username);
if (user == null) {
user= new User();
//set user properties
}
try {
userService.save(user);
} catch (EntityException e) {
System.out.println(e.getMessage());
}
super.onAuthenticationSuccess(req, resp, auth);
}
}
I still haven't figured out how to handle AD specific errors (like user is blocked, or password expired), right now it shows my application default login error message.

Spring security access denied message when accessing login page after login successfully.It should redirect to default page

Configured spring security successfully
Authentication properly working
Problem is that after login successfully if user access login page, access denied message appears.It must redirect to default page as user already login.
When i access login.html after login successfully , access denied message appears.
Here's my code
<http auto-config="true">
<intercept-url pattern="/login.html" access="ROLE_ANONYMOUS" />
<intercept-url pattern="/services/**" filters="none"/>
<intercept-url pattern="/**" access="ROLE_ADMIN" />
<form-login login-page="/login.html" default-target-url="/stations.html" always-use-default-target="true" />
<logout logout-url="/logout" logout-success-url="/login.html"/>
<intercept-url pattern="/css/**" filters="none"/>
<intercept-url pattern="/js/**" filters="none"/>
<intercept-url pattern="/images/**" filters="none"/>
<intercept-url pattern="/common/**" filters="none"/>
</http>
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="
SELECT USERNAME,PASSWORD,USER_STATUS as ENABLED
from USERS where USERNAME=?"
authorities-by-username-query="
SELECT USERNAME, USER_ROLE from USERS
where USERNAME =? "
/>
</authentication-provider>
</authentication-manager>
When the user successfully loggs in this means he/she has some role (admin for example). This is different than ROLE_ANONYMOUS. You can try:
<intercept-url pattern="/login.html" access="ROLE_ANONYMOUS, ROLE_ADMIN,..any other role" />
or even better
<intercept-url pattern="/login.html" filters="none" />
One suggestion: Spring Security evaluate the intercept-url elements in the order you write them in the xml, so you should put the most "greedy" intercept-url at the end. E.g. <intercept-url pattern="/**" access="ROLE_ADMIN" /> will catch everything. The intercept-url for css, js... will never be reached. You should place them first.
I face the same problem,
I have already search many resources and did not found what I looking for.
At last, I'm doing this:
public class SSOInit extends HandlerInterceptorAdapter {
private static final Logger logger = Logger.getLogger(SSOInit.class.getName());
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.info("### SSO : doInit, read page");
logger.info("### SSO : request url = " + request.getRequestURL());
logger.info("### SSO : request method = " + request.getMethod());
CredentialVO credential = SSOService.getUserCredential();
if (credential != null) {
logger.info("### SSO : credential found, do check point");
String status = SSOService.checkSSOSessionKey();
if (status == null || status.equals("T")) {
logger.info("### SSO : Check point didn't passed, redirect");
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
new SecurityContextLogoutHandler().logout(request, response, auth);
}
SecurityContextHolder.getContext().setAuthentication(null);
} else {
logger.info("### SSO : Check point passed");
if (request.getServletPath().equals(SSOConstant.getREDIRECT_URL())) {
logger.info("### SSO : Check point passed, user trying access login form but already authenticated, redirect");
response.sendRedirect(request.getContextPath() + SSOConstant.getMAIN_URL());
return false;
}
}
}
return super.preHandle(request, response, handler);
}
}
and add this xml configuration to dispatcher-servlet.xml
<mvc:interceptors>
<bean class="ptpn4.rawi.sso.client.authentication.SSOInit" />
</mvc:interceptors>
In class SSOInit, I do some checking to database, I'm trying to build Custom SSO Solution.
I hope another better solution regarding my current approach.

Spring Security Get Authentication on Session TimeOut : Authentication object is returning NULL on session timeout

I'm using spring/spring-security 3.1 and want to take some action depends on the authorities in ATHENTICATION object whenever session is timed out.AUTHENTICATION object is null on session timeout.
Here are the files for reference:
security config:
<logout invalidate-session="true" logout-url="/j_spring_security_logout" success-handler-ref="logoutSuccessHandler"/>
<!-- Custom filter to deny unwanted users even though registered -->
<custom-filter ref="blacklistFilter" before="FILTER_SECURITY_INTERCEPTOR" />
<!-- Custom filter for username, password and domain. The real customization is done in the customAuthenticationManager -->
<custom-filter ref="authenticationFilter" position="FORM_LOGIN_FILTER" />
</http>
Note: tried with "invalidate-session="false"" as well.
and my custom LogoutSuccessHandler:
public class EnterpriseLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler{
#Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
for(GrantedAuthority authority: authentication.getAuthorities()){
if(authority.getAuthority()!=null)
logger.debug("THE CURRENT AUTHORITY FOR THE SESSION IS : {} ",authority.getAuthority().toString());
else
logger.debug("THE CURRENT AUTHORITY FOR THE SESSION IS authority.getAuthority(): NULL ");
if(authority.getAuthority()!=null && authority.getAuthority().equalsIgnoreCase(Operational.SPRING_SECURITY.LOGIN_SOURCE_BEACON)){
loginSource = authority.getAuthority().toString();
break;
}
}
}
}
So, there is the question how I can obtain Authentication object on the session timeout.
Can some help me to find out the solution for the above problem.
Thanks in advance.

Spring Security Remember me with custom authentication provider

I am using GWT with spring security. I have a custom authentication provider where I perform all my authentication. How can I configure the remember me feature without using the UserDetailsService? I am not using LDAP.
My AppliationContext_security.xml
<http auto-config="true" entry-point-ref="UnauthorizedEntryPoint"
create-session="always">
<form-login authentication-success-handler-ref="authenticationSuccessHandler"
authentication-failure-handler-ref="authenticationFailureHandler" />
<logout success-handler-ref="logoutSuccessHandler"
invalidate-session="true" />
<intercept-url pattern="/**/myapp.rpc" access="ROLE_USER" />
<custom-filter before="CONCURRENT_SESSION_FILTER" ref="XSRFAttackFilter" />
</http>
<authentication-manager>
<authentication-provider ref="myAuthenticationProvider" />
</authentication-manager>
In my custom authentication provider,
#Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
String username = (String) authentication.getPrincipal();
String password = (String) authentication.getCredentials();
boolean response = loginmanager.authenticateUser(username, password,
((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest().getSession());
if (!response) {
throw new BadCredentialsException(
"Invalid Credentials.");
}
Authentication authentication = ...
authentication.setAuthenticated(true);
return authentication;
}
Any help will be greatly appreciated.
You will need to create a custom UserDetailsService that gets the username/password from the same place that your loginmanager is reading it from. See the source for TokenBasedRememberMeServices.processAutoLoginCookie() to see how it's being used.

Resources