Can't get Spring Security OAuth2 login to trigger -
i writing restful
web service (jersey
running on tomcat
) needs authenticate users' email address, , possibly access google calendar. plan users redirected login google via oauth2
.
my web service protected spring security
. works fine basic authentication (i.e. hard-wired list of users , passwords.) if try access of protected resources prompted login.
now trying wire in spring security oauth2
. understanding redirect google if try access protected resource.
however, no matter try can't seem oauth fire. there no console errors logged, , resources protected (i error "full authentication required access resource").
something wrong; config, understanding, or both. suggestions appreciated.
web.xml
(partial):
<servlet-mapping> <servlet-name>jersey rest service</servlet-name> <url-pattern>/v1/*</url-pattern> </servlet-mapping> <listener> <listener-class> org.springframework.web.context.contextloaderlistener </listener-class> </listener> <filter> <filter-name>springsecurityfilterchain</filter-name> <filter-class>org.springframework.web.filter.delegatingfilterproxy</filter-class> </filter> <context-param> <param-name>contextconfiglocation</param-name> <param-value>/web-inf/spring/spring-security.xml</param-value> </context-param> <filter-mapping> <filter-name>springsecurityfilterchain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
spring-security.xml
(with google keys hidden):
<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" xmlns:context="http://www.springframework.org/schema/context" xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.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"> <debug /> <oauth:client id="oauth2clientfilter" /> <oauth:resource id="googleoauth2resource" type="authorization_code" client-id="hidden" client-secret="hidden" access-token-uri="https://accounts.google.com/o/oauth2/v3/token" user-authorization-uri="https://accounts.google.com/o/oauth2/auth" scope="email" /> <http xmlns="http://www.springframework.org/schema/security" entry-point-ref="oauthauthenticationentrypoint" create-session="stateless"> <intercept-url pattern="/v1/**" access="is_authenticated_fully" /> <intercept-url pattern="/**" access="is_authenticated_anonymously" /> <custom-filter ref="oauth2clientfilter" after="exception_translation_filter" /> <access-denied-handler ref="oauthaccessdeniedhandler" /> </http> <oauth:rest-template id="googleoauthresttemplate" resource="googleoauth2resource" /> <beans:bean id="oauthauthenticationentrypoint" class="org.springframework.security.oauth2.provider.error.oauth2authenticationentrypoint"> </beans:bean> <beans:bean id="oauthaccessdeniedhandler" class="org.springframework.security.oauth2.provider.error.oauth2accessdeniedhandler"> </beans:bean> <authentication-manager> </authentication-manager> </beans:beans>
update: did find working demo (the name misleading-- using oauth2, not openid.) accessing protected resource triggers redirect google expected. didn't have luck translating annotated classes xml though, , i'm not running under spring boot or spring mvc difficult me switch using annotations.
** update 2: ** debugger can see oauth2clientcontextfilter.dofilter getting called, decides not redirect because filter chain isn't throwing userredirectrequiredexception. (the exception being thrown filter chain accessdeniedexception.)
the reason receiving response: "full authentication required access resource"
because oauth2authenticationentrypoint
expecting access token.
the oauth2authenticationentrypoint
used if resource server accepting requests access tokens. in case though, appears intention relying party relies on google give access token can access user's data on google on behalf.
so must follow same flow demo app found on github:
- the user accesses secured endpoint
/test
- the user not yet authenticated gets redirected
/login
configured inloginurlauthenticationentrypoint
- the request
/login
goes through filterchain again , intercepted inopenidconnectauthenticationfilter
configuredoauth2resttemplate
attempts retrieve user info. throwsuserredirectrequiredexception
because oauth2clientcontext not have access token yet retrieve user's info. oauth2clientcontextfilter
catches thrownuserredirectrequiredexception
, redirects user google's authorization page.
here's debug logs show flow:
2016-09-11 02:32:34.361 debug 41435 --- [nio-8080-exec-1] o.s.security.web.filterchainproxy : /test @ position 1 of 13 in additional filter chain; firing filter: 'webasyncmanagerintegrationfilter' 2016-09-11 02:32:34.366 debug 41435 --- [nio-8080-exec-1] o.s.security.web.filterchainproxy : /test @ position 2 of 13 in additional filter chain; firing filter: 'securitycontextpersistencefilter' 2016-09-11 02:32:34.367 debug 41435 --- [nio-8080-exec-1] w.c.httpsessionsecuritycontextrepository : no httpsession exists 2016-09-11 02:32:34.367 debug 41435 --- [nio-8080-exec-1] w.c.httpsessionsecuritycontextrepository : no securitycontext available httpsession: null. new 1 created. 2016-09-11 02:32:34.375 debug 41435 --- [nio-8080-exec-1] o.s.security.web.filterchainproxy : /test @ position 3 of 13 in additional filter chain; firing filter: 'headerwriterfilter' 2016-09-11 02:32:34.378 debug 41435 --- [nio-8080-exec-1] o.s.s.w.header.writers.hstsheaderwriter : not injecting hsts header since did not match requestmatcher org.springframework.security.web.header.writers.hstsheaderwriter$securerequestmatcher@38511637 2016-09-11 02:32:34.379 debug 41435 --- [nio-8080-exec-1] o.s.security.web.filterchainproxy : /test @ position 4 of 13 in additional filter chain; firing filter: 'csrffilter' 2016-09-11 02:32:34.381 debug 41435 --- [nio-8080-exec-1] o.s.security.web.filterchainproxy : /test @ position 5 of 13 in additional filter chain; firing filter: 'logoutfilter' 2016-09-11 02:32:34.382 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.matcher.antpathrequestmatcher : request 'get /test' doesn't match 'post /logout 2016-09-11 02:32:34.382 debug 41435 --- [nio-8080-exec-1] o.s.security.web.filterchainproxy : /test @ position 6 of 13 in additional filter chain; firing filter: 'oauth2clientcontextfilter' 2016-09-11 02:32:34.382 debug 41435 --- [nio-8080-exec-1] o.s.security.web.filterchainproxy : /test @ position 7 of 13 in additional filter chain; firing filter: 'openidconnectauthenticationfilter' 2016-09-11 02:32:34.383 debug 41435 --- [nio-8080-exec-1] o.s.security.web.filterchainproxy : /test @ position 8 of 13 in additional filter chain; firing filter: 'requestcacheawarefilter' 2016-09-11 02:32:34.383 debug 41435 --- [nio-8080-exec-1] o.s.security.web.filterchainproxy : /test @ position 9 of 13 in additional filter chain; firing filter: 'securitycontextholderawarerequestfilter' 2016-09-11 02:32:34.385 debug 41435 --- [nio-8080-exec-1] o.s.security.web.filterchainproxy : /test @ position 10 of 13 in additional filter chain; firing filter: 'anonymousauthenticationfilter' 2016-09-11 02:32:34.396 debug 41435 --- [nio-8080-exec-1] o.s.s.w.a.anonymousauthenticationfilter : populated securitycontextholder anonymous token: 'org.springframework.security.authentication.anonymousauthenticationtoken@9055c2bc: principal: anonymoususer; credentials: [protected]; authenticated: true; details: org.springframework.security.web.authentication.webauthenticationdetails@b364: remoteipaddress: 0:0:0:0:0:0:0:1; sessionid: null; granted authorities: role_anonymous' 2016-09-11 02:32:34.396 debug 41435 --- [nio-8080-exec-1] o.s.security.web.filterchainproxy : /test @ position 11 of 13 in additional filter chain; firing filter: 'sessionmanagementfilter' 2016-09-11 02:32:34.405 debug 41435 --- [nio-8080-exec-1] o.s.s.w.session.sessionmanagementfilter : requested session id d2c2005bfb0ad21f3380bc0be8326094 invalid. 2016-09-11 02:32:34.405 debug 41435 --- [nio-8080-exec-1] o.s.security.web.filterchainproxy : /test @ position 12 of 13 in additional filter chain; firing filter: 'exceptiontranslationfilter' 2016-09-11 02:32:34.406 debug 41435 --- [nio-8080-exec-1] o.s.security.web.filterchainproxy : /test @ position 13 of 13 in additional filter chain; firing filter: 'filtersecurityinterceptor' 2016-09-11 02:32:34.407 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.matcher.antpathrequestmatcher : checking match of request : '/test'; against '/' 2016-09-11 02:32:34.415 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.matcher.antpathrequestmatcher : checking match of request : '/test'; against '/test' 2016-09-11 02:32:34.421 debug 41435 --- [nio-8080-exec-1] o.s.s.w.a.i.filtersecurityinterceptor : secure object: filterinvocation: url: /test; attributes: [authenticated] 2016-09-11 02:32:34.422 debug 41435 --- [nio-8080-exec-1] o.s.s.w.a.i.filtersecurityinterceptor : authenticated: org.springframework.security.authentication.anonymousauthenticationtoken@9055c2bc: principal: anonymoususer; credentials: [protected]; authenticated: true; details: org.springframework.security.web.authentication.webauthenticationdetails@b364: remoteipaddress: 0:0:0:0:0:0:0:1; sessionid: null; granted authorities: role_anonymous 2016-09-11 02:32:34.650 debug 41435 --- [nio-8080-exec-1] o.s.s.access.vote.affirmativebased : voter: org.springframework.security.web.access.expression.webexpressionvoter@3f726a43, returned: -1 2016-09-11 02:32:34.676 debug 41435 --- [nio-8080-exec-1] o.s.s.w.a.exceptiontranslationfilter : access denied (user anonymous); redirecting authentication entry point org.springframework.security.access.accessdeniedexception: access denied @ org.springframework.security.access.vote.affirmativebased.decide(affirmativebased.java:83) @ org.springframework.security.access.intercept.abstractsecurityinterceptor.beforeinvocation(abstractsecurityinterceptor.java:206) @ org.springframework.security.web.access.intercept.filtersecurityinterceptor.invoke(filtersecurityinterceptor.java:115) @ org.springframework.security.web.access.intercept.filtersecurityinterceptor.dofilter(filtersecurityinterceptor.java:84) @ org.springframework.security.web.filterchainproxy$virtualfilterchain.dofilter(filterchainproxy.java:342) @ org.springframework.security.web.access.exceptiontranslationfilter.dofilter(exceptiontranslationfilter.java:113) @ org.springframework.security.web.filterchainproxy$virtualfilterchain.dofilter(filterchainproxy.java:342) @ org.springframework.security.web.session.sessionmanagementfilter.dofilter(sessionmanagementfilter.java:103) @ org.springframework.security.web.filterchainproxy$virtualfilterchain.dofilter(filterchainproxy.java:342) @ org.springframework.security.web.authentication.anonymousauthenticationfilter.dofilter(anonymousauthenticationfilter.java:113) @ org.springframework.security.web.filterchainproxy$virtualfilterchain.dofilter(filterchainproxy.java:342) @ org.springframework.security.web.servletapi.securitycontextholderawarerequestfilter.dofilter(securitycontextholderawarerequestfilter.java:154) @ org.springframework.security.web.filterchainproxy$virtualfilterchain.dofilter(filterchainproxy.java:342) @ org.springframework.security.web.savedrequest.requestcacheawarefilter.dofilter(requestcacheawarefilter.java:45) @ org.springframework.security.web.filterchainproxy$virtualfilterchain.dofilter(filterchainproxy.java:342) @ org.springframework.security.web.authentication.abstractauthenticationprocessingfilter.dofilter(abstractauthenticationprocessingfilter.java:199) @ org.springframework.security.web.filterchainproxy$virtualfilterchain.dofilter(filterchainproxy.java:342) @ org.springframework.security.oauth2.client.filter.oauth2clientcontextfilter.dofilter(oauth2clientcontextfilter.java:57) @ org.springframework.security.web.filterchainproxy$virtualfilterchain.dofilter(filterchainproxy.java:342) @ org.springframework.security.web.authentication.logout.logoutfilter.dofilter(logoutfilter.java:110) @ org.springframework.security.web.filterchainproxy$virtualfilterchain.dofilter(filterchainproxy.java:342) @ org.springframework.security.web.csrf.csrffilter.dofilterinternal(csrffilter.java:85) @ org.springframework.web.filter.onceperrequestfilter.dofilter(onceperrequestfilter.java:107) @ org.springframework.security.web.filterchainproxy$virtualfilterchain.dofilter(filterchainproxy.java:342) @ org.springframework.security.web.header.headerwriterfilter.dofilterinternal(headerwriterfilter.java:57) @ org.springframework.web.filter.onceperrequestfilter.dofilter(onceperrequestfilter.java:107) @ org.springframework.security.web.filterchainproxy$virtualfilterchain.dofilter(filterchainproxy.java:342) @ org.springframework.security.web.context.securitycontextpersistencefilter.dofilter(securitycontextpersistencefilter.java:87) @ org.springframework.security.web.filterchainproxy$virtualfilterchain.dofilter(filterchainproxy.java:342) @ org.springframework.security.web.context.request.async.webasyncmanagerintegrationfilter.dofilterinternal(webasyncmanagerintegrationfilter.java:50) @ org.springframework.web.filter.onceperrequestfilter.dofilter(onceperrequestfilter.java:107) @ org.springframework.security.web.filterchainproxy$virtualfilterchain.dofilter(filterchainproxy.java:342) @ org.springframework.security.web.filterchainproxy.dofilterinternal(filterchainproxy.java:192) @ org.springframework.security.web.filterchainproxy.dofilter(filterchainproxy.java:160) @ org.apache.catalina.core.applicationfilterchain.internaldofilter(applicationfilterchain.java:241) @ org.apache.catalina.core.applicationfilterchain.dofilter(applicationfilterchain.java:208) @ org.springframework.security.oauth2.client.filter.oauth2clientcontextfilter.dofilter(oauth2clientcontextfilter.java:57) @ org.apache.catalina.core.applicationfilterchain.internaldofilter(applicationfilterchain.java:241) @ org.apache.catalina.core.applicationfilterchain.dofilter(applicationfilterchain.java:208) @ org.apache.catalina.core.standardwrappervalve.invoke(standardwrappervalve.java:220) @ org.apache.catalina.core.standardcontextvalve.invoke(standardcontextvalve.java:122) @ org.apache.catalina.authenticator.authenticatorbase.invoke(authenticatorbase.java:503) @ org.apache.catalina.core.standardhostvalve.invoke(standardhostvalve.java:170) @ org.apache.catalina.valves.errorreportvalve.invoke(errorreportvalve.java:103) @ org.apache.catalina.core.standardenginevalve.invoke(standardenginevalve.java:116) @ org.apache.catalina.connector.coyoteadapter.service(coyoteadapter.java:421) @ org.apache.coyote.http11.abstracthttp11processor.process(abstracthttp11processor.java:1070) @ org.apache.coyote.abstractprotocol$abstractconnectionhandler.process(abstractprotocol.java:611) @ org.apache.tomcat.util.net.nioendpoint$socketprocessor.dorun(nioendpoint.java:1736) @ org.apache.tomcat.util.net.nioendpoint$socketprocessor.run(nioendpoint.java:1695) @ java.util.concurrent.threadpoolexecutor.runworker(threadpoolexecutor.java:1142) @ java.util.concurrent.threadpoolexecutor$worker.run(threadpoolexecutor.java:617) @ org.apache.tomcat.util.threads.taskthread$wrappingrunnable.run(taskthread.java:61) @ java.lang.thread.run(thread.java:745) 2016-09-11 02:32:34.678 debug 41435 --- [nio-8080-exec-1] o.s.s.w.util.matcher.andrequestmatcher : trying match using ant [pattern='/**', get] 2016-09-11 02:32:34.678 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.matcher.antpathrequestmatcher : request '/test' matched universal pattern '/**' 2016-09-11 02:32:34.679 debug 41435 --- [nio-8080-exec-1] o.s.s.w.util.matcher.andrequestmatcher : trying match using negatedrequestmatcher [requestmatcher=ant [pattern='/**/favicon.ico']] 2016-09-11 02:32:34.679 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.matcher.antpathrequestmatcher : checking match of request : '/test'; against '/**/favicon.ico' 2016-09-11 02:32:34.679 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.matcher.negatedrequestmatcher : matches = true 2016-09-11 02:32:34.679 debug 41435 --- [nio-8080-exec-1] o.s.s.w.util.matcher.andrequestmatcher : trying match using negatedrequestmatcher [requestmatcher=mediatyperequestmatcher [contentnegotiationstrategy=org.springframework.web.accept.contentnegotiationmanager@7f127599, matchingmediatypes=[application/json], useequals=false, ignoredmediatypes=[*/*]]] 2016-09-11 02:32:34.689 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.m.mediatyperequestmatcher : httprequestmediatypes=[text/html, application/xhtml+xml, image/webp, application/xml;q=0.9, */*;q=0.8] 2016-09-11 02:32:34.689 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.m.mediatyperequestmatcher : processing text/html 2016-09-11 02:32:34.689 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.m.mediatyperequestmatcher : application/json .iscompatiblewith text/html = false 2016-09-11 02:32:34.689 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.m.mediatyperequestmatcher : processing application/xhtml+xml 2016-09-11 02:32:34.691 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.m.mediatyperequestmatcher : application/json .iscompatiblewith application/xhtml+xml = false 2016-09-11 02:32:34.692 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.m.mediatyperequestmatcher : processing image/webp 2016-09-11 02:32:34.692 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.m.mediatyperequestmatcher : application/json .iscompatiblewith image/webp = false 2016-09-11 02:32:34.697 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.m.mediatyperequestmatcher : processing application/xml;q=0.9 2016-09-11 02:32:34.699 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.m.mediatyperequestmatcher : application/json .iscompatiblewith application/xml;q=0.9 = false 2016-09-11 02:32:34.703 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.m.mediatyperequestmatcher : processing */*;q=0.8 2016-09-11 02:32:34.705 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.m.mediatyperequestmatcher : ignoring 2016-09-11 02:32:34.707 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.m.mediatyperequestmatcher : did not match media types 2016-09-11 02:32:34.707 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.matcher.negatedrequestmatcher : matches = true 2016-09-11 02:32:34.707 debug 41435 --- [nio-8080-exec-1] o.s.s.w.util.matcher.andrequestmatcher : trying match using negatedrequestmatcher [requestmatcher=requestheaderrequestmatcher [expectedheadername=x-requested-with, expectedheadervalue=xmlhttprequest]] 2016-09-11 02:32:34.708 debug 41435 --- [nio-8080-exec-1] o.s.s.w.u.matcher.negatedrequestmatcher : matches = true 2016-09-11 02:32:34.709 debug 41435 --- [nio-8080-exec-1] o.s.s.w.util.matcher.andrequestmatcher : requestmatchers returned true 2016-09-11 02:32:34.759 debug 41435 --- [nio-8080-exec-1] o.s.s.w.s.httpsessionrequestcache : defaultsavedrequest added session: defaultsavedrequest[http://localhost:8080/test] 2016-09-11 02:32:34.759 debug 41435 --- [nio-8080-exec-1] o.s.s.w.a.exceptiontranslationfilter : calling authentication entry point. 2016-09-11 02:32:34.760 debug 41435 --- [nio-8080-exec-1] o.s.s.web.defaultredirectstrategy : redirecting 'http://localhost:8080/login' 2016-09-11 02:32:34.761 debug 41435 --- [nio-8080-exec-1] w.c.httpsessionsecuritycontextrepository : securitycontext empty or contents anonymous - context not stored in httpsession. 2016-09-11 02:32:34.761 debug 41435 --- [nio-8080-exec-1] s.s.w.c.securitycontextpersistencefilter : securitycontextholder cleared, request processing completed 2016-09-11 02:32:35.059 debug 41435 --- [nio-8080-exec-2] o.s.security.web.filterchainproxy : /login @ position 1 of 13 in additional filter chain; firing filter: 'webasyncmanagerintegrationfilter' 2016-09-11 02:32:35.059 debug 41435 --- [nio-8080-exec-2] o.s.security.web.filterchainproxy : /login @ position 2 of 13 in additional filter chain; firing filter: 'securitycontextpersistencefilter' 2016-09-11 02:32:35.059 debug 41435 --- [nio-8080-exec-2] w.c.httpsessionsecuritycontextrepository : httpsession returned null object spring_security_context 2016-09-11 02:32:35.059 debug 41435 --- [nio-8080-exec-2] w.c.httpsessionsecuritycontextrepository : no securitycontext available httpsession: org.apache.catalina.session.standardsessionfacade@7ff7af51. new 1 created. 2016-09-11 02:32:35.060 debug 41435 --- [nio-8080-exec-2] o.s.security.web.filterchainproxy : /login @ position 3 of 13 in additional filter chain; firing filter: 'headerwriterfilter' 2016-09-11 02:32:35.060 debug 41435 --- [nio-8080-exec-2] o.s.s.w.header.writers.hstsheaderwriter : not injecting hsts header since did not match requestmatcher org.springframework.security.web.header.writers.hstsheaderwriter$securerequestmatcher@38511637 2016-09-11 02:32:35.060 debug 41435 --- [nio-8080-exec-2] o.s.security.web.filterchainproxy : /login @ position 4 of 13 in additional filter chain; firing filter: 'csrffilter' 2016-09-11 02:32:35.060 debug 41435 --- [nio-8080-exec-2] o.s.security.web.filterchainproxy : /login @ position 5 of 13 in additional filter chain; firing filter: 'logoutfilter' 2016-09-11 02:32:35.061 debug 41435 --- [nio-8080-exec-2] o.s.s.w.u.matcher.antpathrequestmatcher : request 'get /login' doesn't match 'post /logout 2016-09-11 02:32:35.061 debug 41435 --- [nio-8080-exec-2] o.s.security.web.filterchainproxy : /login @ position 6 of 13 in additional filter chain; firing filter: 'oauth2clientcontextfilter' 2016-09-11 02:32:35.062 debug 41435 --- [nio-8080-exec-2] o.s.security.web.filterchainproxy : /login @ position 7 of 13 in additional filter chain; firing filter: 'openidconnectauthenticationfilter' 2016-09-11 02:32:35.187 debug 41435 --- [nio-8080-exec-2] o.s.s.web.defaultredirectstrategy : redirecting 'https://accounts.google.com/o/oauth2/auth?client_id=%3cclient_id%3e&redirect_uri=http%3a%2f%2flocalhost%3a8080%2flogin&response_type=code&scope=openid&state=19p08w' 2016-09-11 02:32:35.187 debug 41435 --- [nio-8080-exec-2] w.c.httpsessionsecuritycontextrepository : securitycontext empty or contents anonymous - context not stored in httpsession. 2016-09-11 02:32:35.188 debug 41435 --- [nio-8080-exec-2] s.s.w.c.securitycontextpersistencefilter : securitycontextholder cleared, request processing completed
also, in sample code, take note of @enableoauth2client
imports oauth2clientconfiguration
.
Comments
Post a Comment