Spring Security OAuth2: InsufficientAuthenticationException - spring-security

First of all, I disabled basic auth:
security.basic.enabled=false
Then I access the authorization page:
http://localhost:8080/oauth/authorize?client_id=client&response_type=code&redirect_uri=http://www.baidu.com
I got following exception:
org.springframework.security.authentication.InsufficientAuthenticationException: User must be authenticated with Spring Security before authorization can be completed.
at org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint.authorize(AuthorizationEndpoint.java:138) ~[spring-security-oauth2-2.0.10.RELEASE.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) ~[spring-web-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:832) ~[spring-webmvc-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:743) ~[spring-webmvc-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:961) ~[spring-webmvc-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895) ~[spring-webmvc-4.2.7.RELEASE.jar:4.2.7.RELEASE]
at ...
I don't understand why I have to do authentication first before OAuth?

The flow for the authorization code grant goes like this:
Client redirects the user to auth server's authorization page. Hence the http://localhost:8080/oauth/authorize?client_id=client&response_type=code&redirect_uri=http://www.baidu.com
If the user were already logged in, the user would be immediately shown an authorization page where he can approve the authorization request. If the user is not yet logged in, he should be redirected to a login page first to authenticate himself to let Spring Security know who is giving the authorization.
What you probably need to do is secure the authorization endpoint by requiring a role granted like this in xml:
<security:http disable-url-rewriting="true"
use-expressions="true"
entry-point-ref="loginEntryPoint">
...
<security:intercept-url pattern="/oauth/authorize" access="hasRole('ROLE_USER')"/>
...
</security:http>
If the user is not yet logged in, this will trigger Spring Security to redirect the user to login as configured in your loginEntryPoint. Typically, you would redirect the user to a login page. After successfully authenticating, the user will return to the authorization endpoint.

Related

WSO2 and Spring SAML single logout issue

The issue I'm having has been discussed several times on this site, however most posts are quite old. Here is something similar to what I'm experiencing. I'm using WSO2 IS 5.2 as my IdP and I have 2 java based web applications hosted on difference servers that participate in SSO. Each webapp (SP) has implemented the Spring-SAML extension. Single Sign-On works perfectly but Single Logout only partially works. Here is the test case:
Access secure resource on webapp1
Login page from Idp (WSO2) is presented and user logs in
Secure resource from webapp1 is presented
Access secure resource on webapp2
SAML request is sent to Idp, Idp responds and user is authenticated
Secure resource from webapp2 is presented, end SSO
Initiate single log out from webapp2
Webapp2 send saml request (through browser) to Idp and saml response is returned
User is logged off locally on webapp2 and Idp session is terminated
The IdP directly sends logout request to webapp1 (back-channel type)
Logout request fails to webapp1 (log indicate SamlStatusException: No user is logged in)
So the end result is that I still have a local session on webapp1. If I change the order and initiate SLO from webapp1, then webapp1 will be logged out and webapp2's local session will continue to exist. The WSO2 server is able to determine the 2nd session participant during SLO, however the HTTP request sent from the Idp to the 2nd session participant does not have a Spring security context. This would be a stateless HTTP request so there wouldn't be a logged in user. This is why I believe it is failing.
I found this discussion. Its about 2 years old. Is there anything new on this issue? Maybe a configuration step missed by me on WSO2 or in the Spring-saml config.
Here is a relevant piece of my SP metadata:
<md:SingleLogoutService Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SingleLogout" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"/>
<md:SingleLogoutService Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SingleLogout" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"/>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</md:NameIDFormat>
<md:AssertionConsumerService Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SSO" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" isDefault="true" index="0"/>
<md:AssertionConsumerService Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SSO" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" index="1"/>
Some relevant Spring-Saml config on the SP:
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="entityId" value="urn:webapp1:mycity"/>
<property name="entityBaseURL" value="https://wwwdev04.domain.org:443/webapp" />
<property name="extendedMetadata">
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<!-- <property name="signMetadata" value="false"/> -->
<property name="idpDiscoveryEnabled" value="false"/>
</bean>
</property>
</bean>
</constructor-arg>
</bean>
WSO2 was not implementing the SAML 2.0 specification correctly. The specification requires that Single Logout with HTTP-* bindings is done using front-end channel (= through user's browser) - which makes the HTTP session available and allows Spring SAML to terminate it correctly. I believe that this issue was never fixed in WSO2.
Spring SAML uses HttpSession for storage of user's state by default. This is also the reason why Spring SAML doesn't support Single Logout with SOAP binding out of the box. It would be possible to implement an application-wide storage of Spring Security sessions which could be invalidated independently from the HttpSession (and therefore work-around the WSO2's limitation), but this is not configured by default (and I have never tried it).

Spring security url interceptor

I have spring security implemented in my application, and you can logged with twitter facebook o normal, if you sign in with your email and password there aren't any problem, but if you logged with twitter,the url interceptor don't let see that page.
I have this code when you logged with twitter in my controller in java.
Authentication authentication = new UsernamePasswordAuthenticationToken(userRegister.getEmail(), "ROLE_USER");
SecurityContextHolder.getContext().setAuthentication(authentication);
And this is my url:interceptor in my spring-security.xml
<security:intercept-url pattern="/member/**" access="hasRole('ROLE_USER')" />
Anybody can help me?
Thanky yoU!

How The Spring Security is redirecting to Login page if User is unauthorized

What is the Internal mechanism of authorization by spring-security?
How it is redirecting the URL to /Login if a user does not enters valid credentials?
Who is responsible for this Action?
What is the internal flow of project ?
All the important magic is in the security filter chain.
At some point some component checks whether the request is authenticated. Usually it is the last filter - FilterSecurityInterceptor (checking access conditions based on request path), but it can be MethodSecurityInterceptor (#Secured annotation check) or even your own custom code. The important thing is that this check will end in AuthenticationException or AccessDeniedException being thrown.
The next important component is ExceptionTranslationFilter. This filter checks if the thrown exception is AuthenticationException or AccessDeniedException and calls configured AuthenticationEntryPoint. Depending on the configured authentication mechanism, this might send redirect to login page or 401 response with WWW-Authenticate header (e.g. BASIC auth).
So the overall process for FORM based login looks like this (it might look like a mess, but it is actually pretty well designed and not that complex once you understand the principles):
unauthenticated user makes request to /foo.html
request is checked by FilterSecurityInterceptor against your security expression isAuthenticated() and throws AccessDeniedException
thrown exception is catched by ExceptionTranslationFilter, which in turn calls LoginUrlAuthenticationEntryPoint
entry point sends 301 redirect response to /login.html
user makes another request to /login.html
request is checked by FilterSecurityInterceptor and for this path, anonymous access is allowed
login form is presented to user
user fills the login form and submits it as POST /login.html
this request is intercepted by authentication processing filter UsernamePasswordAuthenticationFilter
username and password is extracted and AuthenticationManager is called to perform actual authentication (actual authentication is delegated to other components - usually DaoAuthenticationProvider and UserDetailsService)
authentication is successful and the Authentication token is marked as authenticated and put on SecurityContextHolder (so it is available to other components)
AuthenticationSuccessHandler is being called, which might just redirect user back to /foo.html
on the way up, the successful authentication is being picked up by SecurityContextPersistenceFilter (checks SecurityContextHolder), which stores authentication on the HTTP session
user makes yet another request to /foo.html
SecurityContextPersistenceFilter restores authentication from session onto SecurityContextHolder
FilterSecurityInterceptor checks your access rule again and allows further processing for the freshly authenticated request (i.e. dispatcher servlet is called)
user enjoys his /foo.html

WSO2 API Manager - API authentication failure - Required OAuth credentials not provided

I am using wso2 API manager over one of the rest APIs we have . Every time I hit the service on wso2, I am getting the below mentioned error though the application is running fine. I have tried setting OPTIONS as "None" but in vain.
Can someone suggest how to fix it?
2014-03-25 19:36:05,647 [-] [PassThroughMessageProcessor-9] ERROR APIAuthenticationHandler API authentication failure
org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException: Required OAuth credentials not provided
at org.wso2.carbon.apimgt.gateway.handlers.security.oauth.OAuthAuthenticator.authenticate(OAuthAuthenticator.java:114)
at org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler.handleRequest(APIAuthenticationHandler.java:92)
at org.apache.synapse.rest.API.process(API.java:285)
at org.apache.synapse.rest.RESTRequestHandler.dispatchToAPI(RESTRequestHandler.java:76)
at org.apache.synapse.rest.RESTRequestHandler.process(RESTRequestHandler.java:63)
at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:220)
at org.apache.synapse.core.axis2.SynapseMessageReceiver.receive(SynapseMessageReceiver.java:83)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
at org.apache.synapse.transport.passthru.ServerWorker.processNonEntityEnclosingRESTHandler(ServerWorker.java:336)
at org.apache.synapse.transport.passthru.ServerWorker.processEntityEnclosingRequest(ServerWorker.java:377)
at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:183)
at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
According to the error it seems you are not sending the Authorization header. Can you specify which client you are using to send the request?

Spring Security "exceptionMappings"

Using Spring Security preauthentication, my web app re-directs to /login_disabled.html upon hitting a InsufficientAuthenticationException.
sample of applicationContext-security-preauth.xml
<beans:property name="exceptionMappings">
<beans:props>
<beans:prop key="org.springframework.security.
InsufficientAuthenticationException">
/login_disabled.html
Based on this post, it seems that I should be able to re-direct the user to log in again.
Would I just need to re-direct the user to the webpage responsible for authentication?
It's not really clear for me what's the problem here. The redirection to the login page is automatically done without any further configuration if you have form-login set up. If the user tries to access a secured page without being authenticated, the ExceptionTranslationFilter invokes the AuthenticationEntryPoint to initiate authentication.
Using ExceptionMappingAuthenticationFailureHandler to map InsufficientAuthenticationException to a redirect-url won't work anyway because:
It's not indicating an authentication failre. It indicates the condition that the user is only anonymously authenticated while trying to access a secured resource. (As opposed to an auth failure such as entering bad credentials, or user has disabled status.)
It never even gets thrown. (Only instantiated and passed as a parameter in the above linked code.)

Resources