I'm developing an application based on Spring and I'm using Spring Security 3.1.3.
Every time i try to authenticate, authentication doesn't succeed. Here is my security-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<security:http auto-config="true">
<security:form-login login-page="/app/main"
default-target-url="/app/account" />
<security:logout logout-url="/app/logout"
logout-success-url="/app/main" />
</security:http>
<bean id="passwordEncoder"
class="org.springframework.security.crypto.bcrypt. BCryptPasswordEncoder" />
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
user-service-ref="userService" >
<security:password-encoder ref="passwordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
<bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication .dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userService" />
<property name="hideUserNotFoundExceptions" value="false" />
</bean>
<bean id="authenticationManager"
class="org.springframework.security.authentication .ProviderManager">
<constructor-arg>
<ref local="daoAuthenticationProvider" />
</constructor-arg>
</bean>
</beans>
In my bean's password set method, i use BCryptPasswordEncoder like following:
public void setPassword(String password) {
PasswordEncoder passwordEncoder= new BCryptPasswordEncoder();
this.password=passwordEncoder.encode(password);
}
I store username and encoded password in db. I can authenticate just the first time after i sign up. Reason for that is that hibernate entity manager does automatic update of password value in database after selection. I don't know why!!! When i use plain text password, none of this is happening, everything works fine.
It's difficult to know for sure, since you haven't elaborated on what "my bean" is or where this setPassword function is used, but if it's part of a Hibernate entity, then it may be called with an already encoded password (e.g. when loading an entity from the database, not just when creating a new). You certainly wouldn't want to use bcrypt at that point. This might also explain why you can login the first time and sounds likely from your description of hibernate automatically updating the field.
For testing purposes, try adding an assertion that checks that the string doesn't begin with "$2a" (as a bcrypt string will), and throw an exception if it does.
If that's the case, make sure you call the encoder outside the entity when you create it, and pass in the encoded password to the setter.
Related
I am developing the server side for a mobile application as per below:
- I'm using Spring MVC framework and I have already implemented BASIC AUTHENTICATION for restful requests (using JSON) as per code below.
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:http create-session="stateless" entry-point- ref="restAuthenticationEntryPoint" use-expressions="true">
<security:intercept-url pattern="/restful" access="hasRole('ROLE_USER')"/>
<security:intercept-url pattern="/restful/*" access="hasRole('ROLE_USER')"/>
<security:intercept-url pattern="/login" access="permitAll"/>
<security:custom-filter ref="myFilter" after="BASIC_AUTH_FILTER"/>
<!-- <security:logout /> -->
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
user-service-ref="daoUserService">
<security:password-encoder ref="passwordEncoder" />
</security:authentication-provider>
</security:authentication-manager>
<bean id="restAuthenticationEntryPoint" class="com.bp_gae.utils.RestAuthenticationEntryPoint">
</bean>
<bean id="myFilter"
class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationEntryPoint" ref="restAuthenticationEntryPoint" />
</bean>
<bean
id="passwordEncoder"
class="com.bp_gae.utils.AppPasswordEncoder" />
<bean
id="daoUserService"
class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<property
name="dataSource"
ref="dataSource" />
<property
name="enableGroups"
value="false" />
<property
name="enableAuthorities"
value="true" />
<property name="usersByUsernameQuery">
<value>
select username,password, 1
from users
where username = ?
</value>
</property>
<property name="authoritiesByUsernameQuery">
<value>
select username,authority
from users c,
user_roles cp
where c.user_id = cp.user_id
and c.username = ?
</value>
</property>
</bean>
</beans>
So the mobile client sends username, password in every request and a check in DB is done to determine whether he can have access to protected resources.There are no sessions created. The new requirement is to intagrate Facebook authentication.
1) The mobile user signs in and authenticates on client side and sends the authentication token to server.
2) The server should get user facebook details using that token (check whether this token is valid against facebook) using facebook app-id and app-secret from FB app I've created. I am using Spring Social for that purpose.
3) All protected resources are accessible after either basic or Facebook successful auth.
4) I already have a Users table in DB (username,email,password) and I'm thinking of creating another one with SocialUsers (email, token) and do some matching between them to link same users.
I am not sure on how to get both authentication methods working in my security.xml file.
-Do I have to set up another filter for Social Auth?
-In that case how can I use both filters?
Any suggestions / sample code welcome!
I'm using jersey as a RESTFul webserver. (jersey-server 1.8) with spring (3.2.0.RELEASE) and hibernate.
My endpoints are protected using spring-security (3.1.3.RELEASE) with 2 legged oAuth 1.0a (spring-security-oauth 1.0.0.M4 )
Everything works as expected and the securing works.
Inside my ConsumerDetailsServiceImpl (implements ConsumerDetailsService, UserDetailsService, AuthenticationProvider) i throw different exceptions (all are of form OAuthException now, but i want to add my own custom exceptions)
However no matter what i tried i cannot get to customize the different authentication and access denied exceptions the way i want, i always get the default 401 page
My API is agreed to always return a json responseobject so i need to catch these exceptions and show 401 pages with json inside it
My securty.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:security="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oauth="http://www.springframework.org/schema/security/oauth"
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
http://www.springframework.org/schema/security/oauth
http://www.springframework.org/schema/security/spring-security-oauth.xsd">
<!-- Authentication beans -->
<bean name="consumerDetailsService" class="com.securitytest.core.services.impl.ConsumerDetailsServiceImpl" />
<bean name="oauthProcessingFilterEntryPoint" class="org.springframework.security.oauth.provider.OAuthProcessingFilterEntryPoint" />
<bean id="oAuthAuthenticationHandler" class="com.securitytest.core.security.CustomOAuthAuthenticationHandler" />
<security:http auto-config="true" use-expressions="true" entry-point-ref="oauthProcessingFilterEntryPoint" >
<security:intercept-url pattern="/rest/secured/**" access="isAuthenticated()" />
<security:intercept-url pattern="/rest/unsecured/**" access="permitAll" />
<security:intercept-url pattern="/rest/**" access="isAuthenticated()" />
<security:form-login login-page='/login' default-target-url="/home" authentication-failure-handler-ref="authenticationFailureHandler"/>
<security:access-denied-handler ref="accessDeniedHandler" />
</security:http>
<bean id="accessDeniedHandler" class="com.securitytest.core.security.CustomoauthAccessDeniedHandler" />
<!-- this was just a test, it didn't work obviously -->
<bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
<property name="exceptionMappings">
<props>
<prop key="org.springframework.security.authentication.BadCredentialsException">/login/badCredentials</prop>
<prop key="org.springframework.security.authentication.CredentialsExpiredException">/login/credentialsExpired</prop>
<prop key="org.springframework.security.authentication.LockedException">/login/accountLocked</prop>
<prop key="org.springframework.security.authentication.DisabledException">/login/accountDisabled</prop>
</props>
</property>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="consumerDetailsService" />
</security:authentication-manager>
<bean id="nonceServices" class="org.springframework.security.oauth.provider.nonce.InMemoryNonceServices" />
<oauth:provider
auth-handler-ref="oAuthAuthenticationHandler"
consumer-details-service-ref="consumerDetailsService"
nonce-services-ref="nonceServices"
token-services-ref="tokenServices"
require10a="true"
/>
<oauth:token-services id="tokenServices" />
Stuff i tried
Change the exceptionTranslationFilter -> is not allowed by the docs
Add a custom access-denied-handler and a authentication-failure-handler-ref
<security:http auto-config="true" use-expressions="true" entry-point-ref="oauthProcessingFilterEntryPoint" >
<security:intercept-url pattern="/rest/secured/**" access="isAuthenticated()" />
<security:intercept-url pattern="/rest/unsecured/**" access="permitAll" />
<security:intercept-url pattern="/rest/**" access="isAuthenticated()" />
<security:form-login login-page='/login' default-target-url="/home" authentication-failure-handler-ref="authenticationFailureHandler"/>
<security:access-denied-handler ref="accessDeniedHandler" />
</security:http>
-> this gets blatantly ignored by spring-security/oauth
Add a custom filter after the EXCEPTION_TRANSLATION_FILTER
<security:custom-filter after="EXCEPTION_TRANSLATION_FILTER" ref="myFilter" />
MyFilter just implements "javax.servlet.Filter".
-> It goes into the doFilter but i have no idea what do with it (i can't see which exception is thrown, if any).
Any help is appreciated!!
I am quite late answering this question and you might have resolved or moved to some other alternative. However I recently dived into the Oauth and faced similar problem and managed to resolve it. Sharing it as reference for others.
I have used Oauth's MediaTypeAwareAccessDeniedHandler and MediaTypeAwareAuthenticationEntryPoint for error handling. As per documentation, it defaults to 401 error page. However, from source code, error response content type is dependent upon request Accept-Type. But requesting clients to always sent Accept-Type as application/json is like asking fox to safeguard hen.
Good news is that response type support setter injection. So simple solution was to override defaults and inject response property to always sent JSON response irrespective of Accept-Type
<bean id="accessDeniedHandler" class="org.springframework.security.oauth2.provider.error.MediaTypeAwareAccessDeniedHandle"/>
<property name="responses">
<map>
<entry key="*/*" value="{error:"%s"}"></entry>
</map>
</property>
</bean>
I recently ran into an issue where I'm being reauthenticated every time I launch or bring my web app to the foreground when launching it from the homescreen on iOS (I added it to the homescreen from Safari originally). This does not happen when I'm in Safari directly.
My research has shown that this can be overcome in php by creating/restarting the session and then adding a session cookie as follows:
// Start or resume session
session_start();
// Extend cookie life time by an amount of your liking
$cookieLifetime = 365 * 24 * 60 * 60; // A year in seconds
setcookie(session_name(),session_id(),time()+$cookieLifetime);
Rather than do this programatically, I was wondering if there is a way to do this through the XML configuration. Otherwise, how could I accomplish something similar with Spring Security?
Here is my security-ctx.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
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.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint">
</bean>
<sec:http auto-config="false" entry-point-ref="http403EntryPoint">
<sec:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
</sec:http>
<bean id="siteminderFilter" class=
"org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<property name="principalRequestHeader" value="x-paas-uid"/>
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<bean id="preauthAuthProvider"
class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
<bean id="userDetailsServiceWrapper"
class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<property name="userDetailsService" ref="ldapUserDetailsService"/>
</bean>
</property>
</bean>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="preauthAuthProvider"/>
</sec:authentication-manager>
<!-- Example using LDAP, but will ultimately use database service -->
<sec:ldap-server id="ldapServer" port="636" root="o=home"
url="ldaps://ldap.home.com"/>
<sec:ldap-user-service id="ldapUserDetailsService" server-ref="ldapServer"
group-search-base="ou=groups,o=home"
role-prefix="ROLE_" group-role-attribute="cn"
user-search-base="ou=people,o=home" user-search-filter="uid={0}"/>
</beans>
As far as I know Spring Security does not manage session timeout value. So there is no way to do it in security xml out of the box. If you want to define this value system wide (for all sessions) then look into your servlet container / application server documentation. In a case of Tomcat you can add following snippet to the web.xml descriptor:
<web-app ....>
.....
<session-config>
<!-- value is in minutes -->
<!-- 60x24x365 -->
<session-timeout>525600</session-timeout>
</session-config>
....
</web-app>
I wonder how/where can I manage Authentication at SecurityContext in pre-authentation Scenario.
I am using spring security 2.x to implement pre-authentation Scenario in my project. now, it patially work.
After user login by pre-authentation process, they can be authrozied with relevant roles, and are able to acecess resources which defined in security:filter.
e.g.
<security:filter-invocation-definition-source lowercase-comparisons="true" path-type="ant">
<security:intercept-url pattern="/resource/**" access="ROLE_ADMIN" />
In a some controller, I want to check principal in security content.
public abstract class AbstractUserAuthenticationController extends AbstractController
{
protected boolean isAuthenticated(String userName)
{
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); // where issue come up
But SecurityContextHolder.getContext().getAuthentication() always return null.
In addition, I also can not use secuiry tag in jsp to check if user has relative roles
<security:authorize ifNotGranted="ROLE_ADMIN">
no role found
</security:authorize>
Below shows the "filterChainProxy" I am using.
<bean id="filterChainProxy" class="org.springframework.security.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/*subscri*=httpSessionContextIntegrationFilter,logoutFilter,j2eePreAuthenticatedProcessingFilter,securityContextHolderAwareRequestFilter,subscribeExceptionTranslationFilter,filterInvocationInterceptor
/**=httpSessionContextIntegrationFilter,logoutFilter,j2eePreAuthenticatedProcessingFilter,logoutFilter,rememberMeProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor
</value>
</property>
</bean>
<bean id="preAuthenticatedAuthenticationProvider" class="org.springframework.security.providers.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService" />
</bean>
<bean id="preAuthenticatedUserDetailsService" class="demo.project.security.auth.RsaAuthenticationUserDetailsService" >
<property name="userService" ref="userService" />
</bean>
<bean id="j2eePreAuthFilter" class="demo.project.security.filter.AutoLoginFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="userService" ref="userService" />
</bean>
I think I need to set Authentication to SecurityContext in somewhere, But I do not know where/where.
What I am missing? Can anyone provide me some clues?
Thanks!
Ian
You should use SecurityContextHolder.setContext method to store your SecurityContext prior to getting it back.
The simplest way for doing this is just SecurityContextHolder.setContext(new SecurityContextImpl()).
I'm having trouble discovering exactly what I need to implement in order to use a custom authentication method with my web application using Spring Security. I have a Grails application with the Spring Security plugin that currently uses the standard user/password authentication with a browser form. This is working correctly.
I need to implement a mechanism alongside of this that implements a type of MAC authentication. If the HTTP request contains several parameters (e.g. a user identifier, timestamp, signature, etc.) I need to take those parameters, perform some hashing and signature/timestamp comparisons, and then authenticate the user.
I'm not 100% sure where to start with this. What Spring Security classes do I need to extend/implement? I have read the Reference Documentation and have an okay understanding of the concepts, but am not really sure if I need a Filter or Provider or Manager, or where/how exactly to create Authentication objects. I've messed around trying to extend AbstractProcessingFilter and/or implement AuthenticationProvider, but I just get caught up understanding how I make them all play nicely.
Implement a custom AuthenticationProvider which gets all your authentication information from the Authentication: getCredentials(), getDetails(), and getPrincipal().
Tie it into your Spring Security authentication mechanism using the following configuration snippet:
<bean id="myAuthenticationProvider" class="com.example.MyAuthenticationProvider">
<security:custom-authentication-provider />
</bean>
This step is optional, if you can find a suitable one from standard implementations. If not, implement a class extending the Authentication interface on which you can put your authentication parameters:
(e.g. a user identifier, timestamp, signature, etc.)
Extend a custom SpringSecurityFilter which ties the above two classes together. For example, the Filter might get the AuthenticationManager and call authenticate() using your implementation of Authentication as input.
You can extend AbstractAuthenticationProcessingFilter as a start.
You can reference UsernamePasswordAuthenticationFilter which extends AbstractAuthenticationProcessingFilter. UsernamePasswordAuthenticationFilter implements the standard Username/Password Authentication.
Configure your Spring Security to add or replace the standard AUTHENTICATION_PROCESSING_FILTER. For Spring Security Filter orders, see http://static.springsource.org/spring-security/site/docs/3.0.x/reference/ns-config.html#filter-stack
Here is a configuration snippet for how to replace it with your implementation:
<beans:bean id="myFilter" class="com.example.MyAuthenticationFilter">
<custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/>
</beans:bean>
I have recently put up a sample application that does custom authentication with Spring Security 3.
The source code is here.
More details are in this blog post.
Here is an example of securityContext.xml configuration file using custom autenticationFilter (extending AUTHENTICATION_PROCESSING_FILTER) and authenticationProvider. The user authentication data is provided by jdbc connection. Configuration is for Spring Security 2.0.x
<?xml version="1.0" encoding="UTF-8"?>
<sec:global-method-security />
<sec:http auto-config="false" realm="CUSTOM" create-session="always" servlet-api-provision="true"
entry-point-ref="authenticationProcessingFilterEntryPoint" access-denied-page="/notauthorized.xhtml"
session-fixation-protection="migrateSession">
<sec:port-mappings>
<sec:port-mapping http="80" https="443" />
</sec:port-mappings>
<sec:anonymous granted-authority="ROLE_ANONYMOUS" username="Anonymous" />
<sec:intercept-url pattern="/**" access="ROLE_ANONYMOUS, ROLE_USER" />
<sec:logout logout-url="/logoff" logout-success-url="/home.xhtml" invalidate-session="false" />
</sec:http>
<bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.xhtml" />
<property name="forceHttps" value="false" />
</bean>
<bean id="authenticationProcessingFilter" class="mypackage.CustomAuthenticationProcessingFilter">
<sec:custom-filter position="AUTHENTICATION_PROCESSING_FILTER" />
<property name="defaultTargetUrl" value="/" />
<property name="filterProcessesUrl" value="/logon" />
<property name="authenticationFailureUrl" value="/loginError.xhtml" />
<property name="alwaysUseDefaultTargetUrl" value="false" />
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<jee:jndi-lookup id="securityDataSource" jndi-name="jdbc/DB_DS" />
<bean id="myUserDetailsService" class="mypackage.CustomJdbcDaoImpl">
<property name="dataSource" ref="securityDataSource" />
<property name="rolePrefix" value="ROLE_" />
</bean>
<bean id="apcAuthenticationProvider" class="mypackage.CustomDaoAuthenticationProvider">
<property name="userDetailsService" ref="myUserDetailsService" />
<sec:custom-authentication-provider />
</bean>
<bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager">
<property name="providers">
<list>
<ref local="apcAuthenticationProvider" />
</list>
</property>
</bean>
</beans>