I've setup an OAuth2 server with spring security. I want to write client application to use this oauth server with spring security without protecting any resource. Means I just want to run oauth2 from client side with spring security 3.1. I have written the following configuration but it asks for credentials before redirecting to oauth2 server authorize page. But I want to redirect user to oauth2 server authorization page before asking any credentials from client side. I am using following configuration
<http auto-config='true' xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/product/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<custom-filter ref="oauth2ClientFilter" after="EXCEPTION_TRANSLATION_FILTER" />
</http>
<authentication-manager xmlns="http://www.springframework.org/schema/security">
<authentication-provider>
<user-service>
<user name="jimi" password="jimi" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
<!--apply the oauth client context -->
<oauth:client id="oauth2ClientFilter" />
<oauth:resource id="fooClient" type="authorization_code"
client-id="foo" client-secret="secret" access-token-uri="${accessTokenUri}"
user-authorization-uri="${userAuthorizationUri}" scope="read" />
<bean id="dService" class="com.abc.service.DServiceImpl">
<property name="dURL" value="${dURL}"></property>
<property name="dRestTemplate">
<oauth:rest-template resource="fooClient" />
</property>
</bean>
So i just want /product url should access oauth2 server. Rest of the URL mapping should work without this.
And User should be anonymous for client ( No need to show login from on client side).
But When I run my application "http://localhost/client-sample/product/1" then it shows "http://localhost/client-sample/spring_security_login". But I want user should redirect to oaut2 server page.
Spring security prevents anonymous users from acquiring an access token. But if you still want this functionality in your application then you will have to extend org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails class and override isClientOnly() method.
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
public class ExtendedBaseOAuth2ProtectedResourceDetails extends
AuthorizationCodeResourceDetails {
public boolean isClientOnly() {
return true;
}
}
By default this method returns false. So you have to override this method to return true.
Then in your root-context.xml file you have to define oaut2 resource like this.
<bean id="fooClient" class="com.abc.service.ExtendedBaseOAuth2ProtectedResourceDetails">
<property name="clientId" value="foo"></property>
<property name="clientSecret" value="secret"></property>
<property name="accessTokenUri" value="${accessTokenUri}"></property>
<property name="userAuthorizationUri" value="${userAuthorizationUri}"></property>
<property name="scope" value="#{{'read','write'}}"> </property>
</bean>
<bean id="dService" class="com.abc.service.DServiceImpl">
<property name="dURL" value="${dURL}"></property>
<property name="dRestTemplate">
<oauth:rest-template resource="fooClient" />
</property>
</bean>
This will not ask authorization on client side before redirecting the user to the oauth2 provider authorization page.
Related
The problem is that my custom Spring Security filter is never invoked when a request comes in. During debugging, I found that in doFilter() in FilterChainProxy, my filter (JwtAuthenticationFilter) can be fetched:
But it's skipped. Then I found it's due to:
So the superclass of my filer, which is AbstractAuthenticationProcessingFilter thinks the request doesn't need authentication and it just calls doFilter() to pass it down. I think my configs specified that auth is needed. This specific request is /ui/home/index.jsp, where \ui is the context.
My security configs:
<http use-expressions="true" pattern="/**" entry-point-ref="JwtAuthenticationEntryPoint" create-session="stateless">
<custom-filter before="CONCURRENT_SESSION_FILTER" ref="jwtAuthenticationFilter" />
<intercept-url pattern="/home/**" access="isAuthenticated()"/>
// some other intercept-url definitions
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="authenticationProvider"/>
</authentication-manager>
And bean configs:
<bean id="jwtAuthenticationFilter" class="com.pk.jjwt.JwtAuthenticationTokenFilter" >
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationSuccessHandler" ref="jwtAuthenticationSuccessHandler" />
</bean>
<bean id="JwtAuthenticationEntryPoint" class="com.pk.jjwt.JwtAuthenticationEntryPoint" />
<bean id="authenticationProvider" class="com.pk.jjwt.JwtAuthenticationProvider" />
<bean id="jwtAuthenticationSuccessHandler" class="com.pk.jjwt.JwtAuthenticationSuccessHandler" />
I wonder what might cause the filters getting skipped? I think I specified that every url pattern needs to be authenticated. I'm not sure why it thinks that request doesn't need authentication from my custom filter.
Edit:
So I debugged the requiresAuthentication() method, and found:
Basically it's evaluating uri.endsWith("/ui/**") and uri is /ui/home/index.jsp. It returned false, so the filter is skipped.
I am moving from Spring Security 3.2 to 4.1, and I (still) use xml configuration.
It seems that using the <logout /> element does not allow setting the http method to GET.
Is this true?
If, yes, does it mean I have to create a Controller mapping to "/logout" and log out programmatically from there?
Due to legacy reasons, I have to use GET for my LogOutFilter and XML config. The below works. Note I don't recommend working around the csrf protection but I've had to.
This might help others.
<b:bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<b:constructor-arg name="logoutSuccessUrl" value="/loggedOut" />
<b:constructor-arg name="handlers">
<b:list>
<b:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</b:list>
</b:constructor-arg>
<b:property name="logoutRequestMatcher">
<b:bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
<b:constructor-arg name="pattern" value="/logout*"/>
<b:constructor-arg name="httpMethod" value="GET"/>
</b:bean>
</b:property>
</b:bean>
Remember to put the custom filter in the element
<custom-filter before="CSRF_FILTER" ref="logoutFilter" />
The key thing here is that you register your own logoutRequestMatcher
I'm new to Spring security and cas.
In my project I have a cas(CenteralAuthenticationServer) server and a service server.
I want to implement Switch user filter for some users in my application.
Where I should put these lines?
<bean id="switchUserProcessingFilter" class="org.springframework.security.web.authentication.switchuser.SwitchUserFilter">
<property name="userDetailsService" ref="userDetailsService" />
<property name="switchUserUrl" value="/j_spring_security_switch_user" />
<property name="exitUserUrl" value="/j_spring_security_exit_user" />
<property name="targetUrl" value="/index.jsp" />
</bean>
In my cas project or in my web application?
Should I tell tomcat to use this filter in web.xml?
Is there any implementation example?
Should I create java class to implement this fitler?
Add it in your web application (dispatcher-servlet.xml). Check this example if you need.
switch user link
I am using both Spring security and Spring i18n. This is my security config:
<security:http access-denied-page="/denied.htm">
<security:form-login login-page="/login.htm"
authentication-failure-url="/login.htm?login_error=true" />
<security:intercept-url pattern="/denied.htm" filters="none"/>
<security:intercept-url pattern="/login.htm*" filters="none"/>
<security:intercept-url pattern="/*" access="IS_AUTHENTICATED_FULLY" />
<security:logout/>
</security:http>
Besides that, I have set authenticationManager for database with MD5 encoding for password. Security work just fine. My i18n config is:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages" />
</bean>
It works fine with reading locales from web browser's HTTP request, but I want it to change locale if I click on the link on the page (adds ?lang=hr parameter to current page). So when I add this, locale doesn't change at all:
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="en"/>
</bean>
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
<property name="interceptors">
<ref bean="localeChangeInterceptor" />
</property>
</bean>
So I have few questions.
Why the locale interception suddenly doesn't work and how to fix it?
How to read the current chosen locale for user's session from java class? I have java class where I need to fetch spring's message from message_en.properties or message_hr.properties file. Jasper report.
I need to add some interceptor (or something like that) to restrain user with default password only to work with /changePassword.htm page. What is the simplest solution?
Many thanks
Why the locale interception suddenly doesn't work and how to fix
it?
I guess: To "fix" you local interceptor, you should check, that the local interceptor can be invoked even if the user is not logged in.
_2. How to read the current chosen locale for user's session from java
class?
Use the RequestContext.getLocale() method.
#see http://static.springsource.org/spring/docs/2.0.x/reference/mvc.html#mvc-localeresolver
added
The best place (in design/architecure) to obtain the local form the request is the web controller. If you are using Spring 3.0 you can obtain the HttpServletRequest directly if you put an parameter of this type to your Controller Request Handler Method. But you have an better choise: just add a Local parameter to your controller handler method
#see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping-arguments
_3. I need to add some interceptor (or something like that) to restrain user
with default password only to work
with /changePassword.htm page. What is
the simplest solution?
One way (may not the simplest, and a one that needs documentation) is to give a user with the default passwort not the full set of priveleges (ony the privileges that he need to set the new password), after chaning tha password, give the user the full set of privileges, which allow him to do all the other stuff.
Try registering localeChangeInterceptor this way. It worked for me.
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang"></property>
</bean>
</mvc:interceptors>
<bean id="ntlmFilter" class="org.springframework.security.ui.ntlm.NtlmProcessingFilter">
<security:custom-filter position="NTLM_FILTER" />
<property name="stripDomain" value="true" />
<property name="defaultDomain" value="company" />
<property name="domainController" value="192.168.1.1" />
<property name="authenticationManager" ref="_authenticationManager" />
</bean>
may i know how to set failover second controller?
Unfortunately, NTLM isn't supported by Spring 3.
If using a secondary domain controller is a critical requirement for your application, I think you'll need to look into the jcifs source. Even jcifs doesn't want to support NTLM anymore either. But the old libraries are out there. I've hacked around so that my app will invisibly authenticate users whether they're from domainA or domainB. So it's possible, although possibly a bit daunting.
If I understood your question properly, you are looking for a fallback authentication provider, You can setup a list of authentication managers, so that if first one fails, it will automatically check with second one.
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="ntlmServiceAuthenticationProvider"/>
<security:authentication-provider ref="ldapAuthProvider"/>
</security:authentication-manager>