Cannot make Bcrypt hash to work when password is being checked back - spring

I am using Bcrypt to hash passwords and using Random as per Spring documentation. I am using Spring Security 3.2.5.RELEASE.
I have the following OAuth2 security configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:oauth2="http://www.springframework.org/schema/security/oauth2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/security/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2.xsd">
<beans:bean id="userService" class="com.nando.api.service.DefaultUserService" />
<beans:bean id="webServiceClientService"
class="com.nando.api.service.DefaultWebServiceClientService" />
<beans:bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<beans:constructor-arg ref="webServiceClientService" />
</beans:bean>
<beans:bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" />
<beans:bean id="webSecurityExpressionHandler"
class="org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler" />
<beans:bean id="methodSecurityExpressionHandler"
class="org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler" />
<beans:bean id="passwordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<beans:bean id="tokenStore"
class="com.nando.api.service.DefaultAccessTokenService" />
<beans:bean id="oauthRequestFactory" class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<!-- TODO arguments here -->
<beans:constructor-arg name="clientDetailsService" ref="webServiceClientService" />
<!-- <beans:property name="securityContextAccessor" ref="oauthRequestFactory" /> -->
</beans:bean>
<beans:bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<beans:property name="tokenStore" ref="tokenStore" />
<!-- TODO here -->
<beans:property name="requestFactory" ref="oauthRequestFactory" />
</beans:bean>
<beans:bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<beans:bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint" />
<authentication-manager>
<authentication-provider user-service-ref="userService">
<password-encoder ref="passwordEncoder" />
</authentication-provider>
</authentication-manager>
<authentication-manager id="oauthClientAuthenticationManager">
<authentication-provider user-service-ref="clientDetailsUserService">
<password-encoder ref="passwordEncoder" />
</authentication-provider>
</authentication-manager>
<oauth2:authorization-server
token-services-ref="tokenStore" client-details-service-ref="webServiceClientService"
user-approval-page="oauth/authorize" error-page="oauth/error">
<oauth2:authorization-code />
</oauth2:authorization-server>
<beans:bean id="nonceServices"
class="com.nando.api.service.DefaultOAuthNonceService" />
<beans:bean id="resourceServerFilter"
class="com.nando.api.filters.OAuthSigningTokenAuthenticationFilter">
<beans:property name="authenticationEntryPoint" ref="oauthAuthenticationEntryPoint" />
<beans:property name="nonceServices" ref="nonceServices" />
<beans:property name="tokenStore" ref="tokenStore" />
<beans:property name="resourceId" value="nando" />
</beans:bean>
<global-method-security pre-post-annotations="enabled"
order="0" proxy-target-class="true">
<expression-handler ref="methodSecurityExpressionHandler" />
</global-method-security>
<http security="none" pattern="/resource/**" />
<http security="none" pattern="/favicon.ico" />
<http use-expressions="true" create-session="stateless"
authentication-manager-ref="oauthClientAuthenticationManager"
entry-point-ref="oauthAuthenticationEntryPoint" pattern="/oauth/token">
<intercept-url pattern="/oauth/token" access="hasAuthority('OAUTH_CLIENT')" />
<http-basic />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<expression-handler ref="webSecurityExpressionHandler" />
</http>
<http use-expressions="true" create-session="stateless"
entry-point-ref="oauthAuthenticationEntryPoint" pattern="/services/**">
<intercept-url pattern="/services/**"
access="hasAuthority('USE_WEB_SERVICES')" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<expression-handler ref="webSecurityExpressionHandler" />
</http>
<http use-expressions="true">
<intercept-url pattern="/session/list"
access="hasAuthority('VIEW_USER_SESSIONS')" />
<intercept-url pattern="/oauth/**"
access="hasAuthority('USE_WEB_SERVICES')" />
<intercept-url pattern="/login/**" access="permitAll()" />
<intercept-url pattern="/login" access="permitAll()" />
<intercept-url pattern="/logout" access="permitAll()" />
<intercept-url pattern="/**" access="isFullyAuthenticated()" />
<form-login default-target-url="/ticket/list" login-page="/login"
login-processing-url="/login/submit" authentication-failure-url="/login?loginFailed"
username-parameter="username" password-parameter="password" />
<logout logout-url="/logout" logout-success-url="/login?loggedOut"
delete-cookies="JSESSIONID" invalidate-session="true" />
<session-management invalid-session-url="/login"
session-fixation-protection="changeSessionId">
<concurrency-control error-if-maximum-exceeded="true"
max-sessions="1" session-registry-ref="sessionRegistry" />
</session-management>
<csrf />
<expression-handler ref="webSecurityExpressionHandler" />
</http>
</beans:beans>
The problem is:
When it runs it goes to org.springframework.security.authentication.dao.DaoAuthenticationProvider and the method:
additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication) fails because the salt is empty.
It should have a Random Salt. This is how I am creating my password and storing on the database. I have verified the retrieved password from the database and it is correct.
UserPrincipal principal = new UserPrincipal();
principal.setUserName(userName);
UUID userID = UUIDs.timeBased();
principal.setUserID(userID);
String salt = BCrypt.gensalt(HASHING_ROUNDS, RANDOM);
byte[] hash = BCrypt.hashpw(password, salt).getBytes();
principal.setHashedPassword(Converters.byteArray2ByteBuffer(hash));
Where:
private static final SecureRandom RANDOM;
static {
try {
RANDOM = SecureRandom.getInstanceStrong();
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e);
}
}
private static final int HASHING_ROUNDS = 10;
The password is hashed and generated properly. It is saved properly on the database and retrieved properly. But when it gets checked, the presented password is not hashed so that the comparison fails.
First, this.saltSource is null because I have no salt beans defined. I thought this was random and the salt was the old way of doing it.
Now, when looking at the debugger:
if (this.saltSource != null) {
salt = this.saltSource.getSalt(userDetails);
}
if (authentication.getCredentials() == null) {
logger.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails);
}
String presentedPassword = authentication.getCredentials().toString();
if (!passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) {
logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"), userDetails);
}
The presentedPassword is not hashed and the salt is empty. So the (!passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) test checks and it fails.
If I am using a Random salt, how can I make this to work? What am I missing?

Related

Spring Security's intercept-url's access="hasRole()" attribute gives error [duplicate]

I have the following snippet
<http use-expressions="true" auto-config="false"
entry-point-ref="loginUrlAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager" disable-url-rewriting="false">
<!--<custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter"
/> -->
<custom-filter position="FORM_LOGIN_FILTER"
ref="usernamePasswordAuthenticationFilter" />
<custom-filter position="LOGOUT_FILTER" ref="tapLockFilter" />
<intercept-url pattern="/session/**" access="permitAll" />
<intercept-url pattern="/deviceregistration/**" access="permitAll" />
<intercept-url pattern="/session/lock" access="hasRole('ROLE_MEMBER')" />
<intercept-url pattern="/app/resources/admin*" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/app/SuperAppdashboard*" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/app/*" access="hasRole('ROLE_MEMBER')" />
<!--<session-management invalid-session-url="/tizelytics/session/invalidSession"
session-authentication-error-url="/tizelytics/session/accessDenied" session-authentication-strategy-ref="sas">
</session-management> -->
<session-management invalid-session-url="/session/invalidSession"
session-authentication-error-url="/session/accessDenied"
session-fixation-protection="none">
<concurrency-control max-sessions="1"
expired-url="/session/accessExpired" />
</session-management>
</http>
When i run this on server it throws an exception saying
Unsupported configuration attributes: [permitAll, permitAll, hasRole('ROLE_ADMIN'), hasRole('ROLE_ADMIN'), hasRole('ROLE_MEMBER'), hasRole('ROLE_MEMBER')]
here is my access-decision-manager bean within the same xml
<beans:bean id="accessDecisionManager"
class="org.springframework.security.access.vote.AffirmativeBased">
<beans:constructor-arg>
<beans:list>
<beans:bean
class="org.springframework.security.access.vote.AuthenticatedVoter" />
<beans:bean class="org.springframework.security.access.vote.RoleVoter" />
</beans:list>
</beans:constructor-arg>
</beans:bean>
If i remove the access-decision-manager-ref no exception is thrown the app launches correctly can anyone please advice?
Since you are defining your own accessDecisionManager, I don't see WebExpressionVoter as one of the beans in its list. WebExpressionVoter resolves strings like permitAll(), hasRole(), hasAuthority(), etc. So, your accessDecisionManager bean should be:
<beans:bean id="accessDecisionManager"
class="org.springframework.security.access.vote.AffirmativeBased">
<beans:constructor-arg>
<beans:list>
<beans:bean
class="org.springframework.security.access.vote.AuthenticatedVoter" />
<beans:bean class="org.springframework.security.access.vote.RoleVoter" />
<beans:bean class="org.springframework.security.web.access.expression.WebExpressionVoter" />
</beans:list>
</beans:constructor-arg>
</beans:bean>

spring rest access in outside of application without login

I have one application using spring 4 and all the methods are rest(using RestController). I used spring-security(role based) for login and authentication url.
Below is my spring-security.xml
<?xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:http auto-config="true" use-expressions="true">
<security:form-login login-page="/public/login"
default-target-url="/auth/userhome" authentication-failure-url="/public/fail2login" always-use-default-target="true"/>
<security:intercept-url pattern="/index.jsp" access="permitAll" />
<security:intercept-url pattern="/public/**" access="permitAll" />
<security:intercept-url pattern="/resources/**" access="permitAll" />
<security:logout logout-success-url="/public/logout" />
<security:intercept-url pattern="/auth/**" access="fullyAuthenticated" />
<security:intercept-url pattern="/**" access="denyAll" />
<security:session-management
session-fixation-protection="migrateSession" invalid-session-url="/login">
<security:concurrency-control
max-sessions="1" expired-url="/login" />
</security:session-management>
</security:http>
<security:authentication-manager>
<security:authentication-provider
user-service-ref="hbUserDetailService">
<security:password-encoder hash="plaintext" />
</security:authentication-provider>
</security:authentication-manager>
</beans>
Service:
package com.arat.budget.service;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.arat.budget.dao.UserDao;
import com.arat.budget.model.UserRoles;
import com.arat.budget.model.Users;
#Service
public class HbUserDetailsService implements UserDetailsService {
#Autowired
private UserDao userDao;
#SuppressWarnings("unchecked")
#Transactional
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
Users user = userDao.findByUserName(username);
List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRoleses());
return buildUserForAuthentication(user, authorities);
}
// Converts com.mkyong.users.model.User user to
// org.springframework.security.core.userdetails.User
private User buildUserForAuthentication(Users user, List<GrantedAuthority> authorities) {
return new User(user.getUsername(), user.getPassword(), user.isEnabled(), true, true, true, authorities);
}
private List<GrantedAuthority> buildUserAuthority(Set<UserRoles> userRoles) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
// Build user's authorities
for (UserRoles userRole : userRoles) {
setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
}
List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);
return Result;
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
#RestController
public class PostAuthController {
#RequestMapping(value = "/auth/userhome", method = RequestMethod.GET)
public String executeSecurity(ModelMap model, Principal principal) {
String name = principal.getName();
model.addAttribute("author", name);
model.addAttribute("message",
"Welcome To Login Form Based Spring Security Example!!!");
return "auth/welcome";
}
}
I am able to login without any issue. But I have one controller with /auth/employee/{id} and request mapping.
Since /auth/** is fullyAuthenticated so how other application can access the rest endpoint
#RestController
#RequestMapping(value="/auth")
public class EmployeeController{
#RequestMapping("/employee/{id}",method=RequestMethod.GET)
public List<Employee> getEmployee(#PathVariable int id){
return userDao.getEmployee(id);
}
}
Could you please help me how can I access /auth/employee/1001 in another application without login?
Note: I am using tiles to render the page in this application
You can use Basic Authentication for this. Extend BasicAuthenticationEntryPoint class and create a custom implementation of it.
public class CustomBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
#Override
public void commence(final HttpServletRequest request,
final HttpServletResponse response,
final AuthenticationException authException) throws IOException, ServletException {
//Authentication failed, send error response.
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.addHeader("WWW-Authenticate", "Basic realm=" + getRealmName() + "");
PrintWriter writer = response.getWriter();
writer.println("HTTP Status 401 : " + authException.getMessage());
}
#Override
public void afterPropertiesSet() throws Exception {
setRealmName("MY_TEST_REALM");
super.afterPropertiesSet();
}
}
For more info refer this.
Hope this helps.
I got my solution.
I created a separate api url which will expose only resources and added basic auth filter.
My spring-security.xml looks like below.
<?xml version="1.0"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<!-- Oauth start -->
<http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager">
<intercept-url pattern="/oauth/token"
access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<custom-filter ref="clientCredentialsTokenEndpointFilter"
after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/api/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager">
<anonymous enabled="false" />
<intercept-url pattern="/api/**" access="ROLE_APP" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<beans:bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="test" />
</beans:bean>
<beans:bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="test/client" />
<beans:property name="typeName" value="Basic" />
</beans:bean>
<beans:bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<beans:bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<beans:property name="authenticationManager" ref="clientAuthenticationManager" />
</beans:bean>
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
<beans:bean class="org.springframework.security.access.vote.RoleVoter" />
<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</beans:list>
</beans:constructor-arg>
</beans:bean>
<authentication-manager id="clientAuthenticationManager">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<authentication-manager alias="authenticationManager">
<authentication-provider
user-service-ref="hbUserDetailService">
<password-encoder hash="plaintext" />
</authentication-provider>
<!-- <authentication-provider>
<jdbc-user-service data-source-ref="spring_db_DataSource"/>
</authentication-provider> -->
</authentication-manager>
<beans:bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<beans:constructor-arg ref="clientDetails" />
</beans:bean>
<beans:bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" />
<beans:bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<beans:property name="tokenStore" ref="tokenStore" />
<beans:property name="supportRefreshToken" value="true" />
<beans:property name="accessTokenValiditySeconds" value="120" />
<beans:property name="clientDetailsService" ref="clientDetails" />
</beans:bean>
<beans:bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
<beans:property name="tokenServices" ref="tokenServices" />
</beans:bean>
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="test" token-services-ref="tokenServices" />
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="restapp"
authorized-grant-types="authorization_code,client_credentials"
authorities="ROLE_APP" scope="read,write,trust" secret="secret" />
<oauth:client client-id="restapp"
authorized-grant-types="password,authorization_code,refresh_token,implicit"
secret="restapp" authorities="ROLE_APP" />
</oauth:client-details-service>
<!-- <global-method-security
pre-post-annotations="enabled" proxy-target-class="true">
<expression-handler ref="oauthExpressionHandler" />
</global-method-security> -->
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
<!-- Oauth end -->
<!-- Form based security starts-->
<http auto-config="true" use-expressions="true"
authentication-manager-ref="authenticationManagerForRest">
<form-login login-page="/public/login"
default-target-url="/auth/userhome" authentication-failure-url="/public/fail2login"
always-use-default-target="true" />
<intercept-url pattern="/index.jsp"
access="permitAll" />
<intercept-url pattern="/public/**"
access="permitAll" />
<intercept-url pattern="/resources/**"
access="permitAll" />
<logout logout-success-url="/public/logout" />
<access-denied-handler error-page="/403.html"/>
<intercept-url pattern="/auth/**"
access="fullyAuthenticated" />
<intercept-url pattern="/**" access="denyAll" />
<session-management
session-fixation-protection="migrateSession" invalid-session-url="/login">
<concurrency-control
max-sessions="1" expired-url="/login" />
</session-management>
</http>
<authentication-manager alias="authenticationManagerForRest">
<authentication-provider
user-service-ref="hbUserDetailService">
<password-encoder hash="plaintext" />
</authentication-provider>
</authentication-manager>
<!-- Form based security ends -->
</beans:beans>
deploy the project and to get the access token
localhost:8080/<context>/oauth/token?grant_type=password&client_id=restapp&client_secret=restapp&username=<uer>&password=<password>
it will give the access token using which we can involke the rest end point

Spring Oauth2 - update to 2.0.x and configuration no longer works

Ok, so, after updating to Spring Oauth2 2.0.6 - from 1.0.0.M6, my configuration stopped working. I had to make a few tweaks here and the (like, some classes that no longer exists and some that changed package).
The current configuration is the following one:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd">
<global-method-security pre-post-annotations="enabled" />
<http pattern="/favicon.ico" security="none" />
<http pattern="/login/**" security="none" />
<http pattern="/css/**" security="none" />
<http pattern="/js/**" security="none" />
<http pattern="/img/**" security="none" />
<http pattern="/mockdata/**" security="none" />
<http pattern="/p/api/**" security="none" />
<http pattern="/p/public/**" entry-point-ref="oauthAuthenticationEntryPoint" authentication-manager-ref="clientAuthenticationManager">
<intercept-url pattern="/p/public/**" access="ROLE_OAUTH_CLIENT" />
<custom-filter ref="resourceServerFilter" before="EXCEPTION_TRANSLATION_FILTER" />
</http>
<http pattern="/public/**" entry-point-ref="oauthAuthenticationEntryPoint" authentication-manager-ref="clientAuthenticationManager">
<intercept-url pattern="/public/**" access="ROLE_OAUTH_CLIENT" />
<custom-filter ref="resourceServerFilter" before="EXCEPTION_TRANSLATION_FILTER" />
</http>
<http pattern="/p/oauth/token" create-session="never" authentication-manager-ref="clientAuthenticationManager">
<intercept-url pattern="/p/oauth/token" access="ROLE_OAUTH_CLIENT" />
<anonymous enabled="false" />
<http-basic />
<custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http access-decision-manager-ref="accessDecisionManager">
<intercept-url pattern="/p/tasks/comment" access="ROLE_ACTIVE,ROLE_OAUTH_CLIENT" />
<intercept-url pattern="/**" access="ROLE_ACTIVE"/>
<!-- ATTENTION TO THIS LINE - If commented out the login works -->
<custom-filter ref="resourceServerFilter" before="EXCEPTION_TRANSLATION_FILTER" />
<access-denied-handler error-page="/login/" />
<form-login login-page="/login/" default-target-url="/" authentication-failure-url="/login/?error=1" />
<http-basic/>
<logout logout-url="/logout" logout-success-url="/" />
<remember-me user-service-ref="userDetailsServiceImpl" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="userDetailsServiceImpl">
<password-encoder hash="md5"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="on-tasks2" />
</beans:bean>
<beans:bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<beans:bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<beans:property name="authenticationManager" ref="clientAuthenticationManager" />
</beans:bean>
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<beans:constructor-arg>
<beans:list>
<beans:bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
<beans:bean class="org.springframework.security.access.vote.RoleVoter">
<beans:property name="rolePrefix" value="" />
</beans:bean>
<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</beans:list>
</beans:constructor-arg>
</beans:bean>
<authentication-manager id="clientAuthenticationManager">
<authentication-provider user-service-ref="clientDetailsUserDetailsService" />
</authentication-manager>
<beans:bean id="clientDetailsUserDetailsService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<beans:constructor-arg ref="clientDetails" />
</beans:bean>
<beans:bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<beans:property name="tokenStore" ref="tokenStore" />
<beans:property name="supportRefreshToken" value="false" />
<beans:property name="clientDetailsService" ref="clientDetails" />
</beans:bean>
<beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
<beans:constructor-arg ref="dataSource" />
</beans:bean>
<oauth:authorization-server
client-details-service-ref="clientDetails"
token-services-ref="tokenServices"
authorization-endpoint-url="/p/oauth/authorize"
token-endpoint-url="/p/oauth/token"
user-approval-page="access_confirmation">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter" resource-id="on-tasks" token-services-ref="tokenServices" />
<beans:bean id="clientDetails" class="org.springframework.security.oauth2.provider.client.JdbcClientDetailsService">
<beans:constructor-arg ref="dataSource" />
</beans:bean>
</beans:beans>
With this configuration as-is, whenever I try to login, it redirects to the login page with a 302 code on /j_spring_security_check. If I comment that line (custom-filter ref="resourceServerFilter" before="EXCEPTION_TRANSLATION_FILTER") out, the login works.
Also, now, if I try to access localhost:8080/p/oauth/token?client_id=the-client-ids&client_secret=someMockedSecret&grant_type=client_credentials&scope=comment I get a 404, whereas before it used to create the access token.
The lines that were changed with the update are the following:
- <beans:bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.MediaTypeAwareAuthenticationEntryPoint">
+ <beans:bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
- <beans:bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.MediaTypeAwareAccessDeniedHandler" />
+ <beans:bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
- <beans:bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.filter.ClientCredentialsTokenEndpointFilter">
+ <beans:bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
- <beans:bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.RandomValueTokenServices">
+ <beans:bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
- <beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.JdbcTokenStore">
+ <beans:bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
- <beans:bean id="clientDetails" class="org.springframework.security.oauth2.provider.JdbcClientDetailsService">
+ <beans:bean id="clientDetails" class="org.springframework.security.oauth2.provider.client.JdbcClientDetailsService">
Any suggestions? I've tried a few different configurations that I found here in StackOverflow but none of them worked for me.
Thanks in any advance.
-glauber

j_spring_security_check is not available

I upgraded Spring Security from 2 to 3
Previously Security.xml has AuthenticationProcessingFilter and AuthenticationProcessingFilterEntryPoint
So my new Security.xml is
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
<beans:bean id="userAuthenticationService"
class="com.raykor.core.service.UserAuthenticationService" />
<beans:bean id="shaEncoder"
class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" />
<global-method-security />
<http auto-config="false" entry-point-ref="authenticationProcessingFilterEntryPoint">
<intercept-url pattern="/resettingPassword.do**" access="ROLE_ADMIN" />
<intercept-url pattern="/resetPassword.do**" access="ROLE_ADMIN" />
<logout logout-success-url="/index.jsp" invalidate-session="true" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="userAuthenticationService">
<password-encoder ref="shaEncoder">
<salt-source user-property="salt" />
</password-encoder>
</authentication-provider>
</authentication-manager>
<beans:bean id="authenticationFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="filterProcessesUrl" value="/j_spring_security_check" />
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="authenticationFailureHandler"
ref="failureHandler" />
<beans:property name="authenticationSuccessHandler"
ref="successHandler" />
</beans:bean>
<beans:bean id="successHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="alwaysUseDefaultTargetUrl" value="false" />
<beans:property name="defaultTargetUrl" value="/home.do" />
</beans:bean>
<beans:bean id="failureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/login.do?error=true" />
</beans:bean>
<beans:bean id="authenticationProcessingFilterEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/login.do" />
<beans:property name="forceHttps" value="false" />
</beans:bean>
`
Also added filter springSecurityFilterChain in web.xml
On login.do it opens Login Page,On Submit it submits to j_spring_security_check with username and password as j_username & j_password
So why is it saying as j_spring_security_checknot avaliable
You instantiate a UsernamePasswordAuthenticationFilter, but it won't be part of the security filter chain just by creating it. Try removing the auto-config="false" from the http config element, and include a <form-login> element within that. I think all the configuration that you have done through the bean definitions can be done using the more concise namespace configuration which should be preferred with Spring Security 3.
I missed to add custom-filter ref i updated
as
<http auto-config="false" entry-point-ref="authenticationProcessingFilterEntryPoint">
<custom-filter position="FORM_LOGIN_FILTER" ref="authenticationFilter"/>
<intercept-url pattern="/resettingPassword.do**" access="ROLE_ADMIN" />
<intercept-url pattern="/resetPassword.do**" access="ROLE_ADMIN" />
<logout logout-success-url="/index.jsp" invalidate-session="true" />
</http>

Why could a Spring3 Security login work only exactly once until the server is restarted?

Everything works like a charm the first time I login after deployment of my Spring security app. But after the first logout, I can't login again until the service is restarted! Also it seems as if the login was successful, as I can see the users data being loaded in the hibernate sql-log.
Here the relevant code fragments:
applicationContext-security.xml:
<global-method-security pre-post-annotations="enabled" />
<http auto-config="true" use-expressions="true" security="none" pattern="/bookmark/add" />
<http auto-config="true"
use-expressions="true"
access-denied-page="/user/login"
disable-url-rewriting="true">
<intercept-url pattern="/dashboard/**" access="isAuthenticated()" />
<intercept-url pattern="/user/**" access="permitAll" />
<intercept-url pattern="/**" access="permitAll" />
<form-login
default-target-url="/dashboard"
login-page="/user/login"
login-processing-url="/user/doLogin"
authentication-failure-url="/user/login/error"
username-parameter="email"
password-parameter="password" />
<logout logout-success-url="/user/logout"
logout-url="/user/doLogout"
invalidate-session="true"
delete-cookies="true" />
<remember-me services-ref="rememberMeServices" key="myfancysalt" />
<session-management invalid-session-url="/user/login">
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="loginUserDetailsService">
<password-encoder ref="passwordEncoder" hash="sha-256">
<salt-source system-wide="myfancysalt" />
</password-encoder>
</authentication-provider>
</authentication-manager>
<beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" />
<beans:bean id="rememberMeFilter" class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<beans:property name="rememberMeServices" ref="rememberMeServices"/>
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
<beans:bean id="rememberMeServices" class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<beans:property name="userDetailsService" ref="loginUserDetailsService"/>
<beans:property name="key" value="myfancysalt"/>
</beans:bean>
<beans:bean id="rememberMeAuthenticationProvider" class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
<beans:property name="key" value="myfancysalt"/>
</beans:bean>
LoginController:
#RequestMapping(value = "login", method = RequestMethod.GET)
public String login(Principal principal) {
if (principal != null) { // If user is already logged in, redirect him
return "redirect:/dashboard";
}
return "user/login";
}
#RequestMapping(value = {"login/error", "/user/doLogin"})
public ModelAndView processLogin(Principal principal) {
if (principal != null) { // If user is already logged in, redirect him
return new ModelAndView("redirect:/dashboard", null);
}
HashMap map = new HashMap();
map.put("error", true);
return new ModelAndView("user/login", map);
}
#RequestMapping(value = "logout")
public ModelAndView logout() {
return new ModelAndView("user/logout");
}
The necessary filter in web.xml is present.
Any help is very much appreciated!
### EDIT ###:
The problem lied in the concurrent session limitation. After I removed the following part from the applicationcontext-security.xml, everything works fine. Can someone tell me what's wrong with it? (I just copy/pasted it from some howto).
<session-management invalid-session-url="/user/login">
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>
You can try to do:
principal == null
before you logout.

Resources