I am writing a RESTful
web service (Jersey running on Tomcat) that needs to authenticate users. The plan is to redirect them to login to Google via OAuth2
. Once they grant us permission to see their email address, we'll know if they are a known user in our system.
I am using Spring Security
. I had it working with basic authentication (hard-wired list of users and passwords.) Then I added OAuth2
elements to the XML configuration, but when I access the service from a browser I'm still getting prompted to login by the browser, instead of getting redirected to Google's website. There are no particular errors logged by the console.
Suggestions would be appreciated. Here is my Spring Security configuration file: spring-security.xml (though without the real client's ID and secret.)
<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="myclientid.apps.googleusercontent.com" client-secret="myclientsecret"
access-token-uri="https://accounts.google.com/o/oauth2/v3/token" user-authorization-uri="https://accounts.google.com/o/oauth2/auth" scope="email" />
<http auto-config='true' xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/V1/**" access="ROLE_USER" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<custom-filter ref="oauth2ClientFilter" after="EXCEPTION_TRANSLATION_FILTER" />
</http>
<oauth:rest-template id="googleOauthRestTemplate" resource="googleOauth2Resource" />
<authentication-manager>
</authentication-manager>
</beans:beans>
Here are the guts of my web.xml
file. (Nothing here was changed from when I had the hard-wired list of users and passwords.)
<!-- Require HTTPS for everything except /img (favicon) and /css. -->
<security-constraint>
<web-resource-collection>
<web-resource-name>HTTPSOnly</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>HTTPSOrHTTP</web-resource-name>
<url-pattern>*.ico</url-pattern>
<url-pattern>/img/*</url-pattern>
<url-pattern>/css/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- Register resources and providers under com.vogella.jersey.first package. -->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.foobar.dataservices</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/V1/*</url-pattern>
</servlet-mapping>
<resource-ref>
<description>TAE DB Connection Pool</description>
<res-ref-name>jdbc/taeDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<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>
</web-app>
Suggestions for getting OAuth2
working would be most appreciated.
Removing auto-config="true" from the http element in spring-security.xml got rid of the wrong login form.
This revealed a new error:
Configuration problem: No AuthenticationEntryPoint could be established. Please make sure you have a login mechanism configured through the namespace (such as form-login) or specify a custom AuthenticationEntryPoint with the 'entry-point-ref' attribute
So I added the missing entry-point-ref
, and an access-denied-handler
while I was at it:
<http xmlns="http://www.springframework.org/schema/security" entry-point-ref="oauthAuthenticationEntryPoint">
<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>
<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>
The service now launches without logging any errors and does not show the wrong login form.
(But note that it denies permission to all my resources. I thought Spring Security
would redirect to Google on behalf of my RESTful
service, but maybe my webpage needs to get the authorization token before calling the service? I think that's a new topic though.)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.