I am getting 400 Bad request output when I puts wrong credential.
INFO : org.springframework.security.oauth2.provider.endpoint.TokenEndpoint - Handling error: InvalidGrantException, Bad credentials
I want to change this response.
I am adding few of my configurations here:
<http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="isFullyAuthenticated()" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test" />
</bean>
<bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test/client" />
<property name="typeName" value="Basic" />
<property name="exceptionRenderer" ref="headerOnlyExceptionRender" />
</bean>
<bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
<property name="exceptionTranslator" ref="customExceptionTranslator" />
<property name="exceptionRenderer" ref="headerOnlyExceptionRender" />
</bean>
<bean id="headerOnlyExceptionRender" class="com.spring.myapp.Exception.HeaderOnlyOAuth2ExceptionRenderer"/>
<bean id="customExceptionTranslator" class="com.spring.myapp.Exception.CustomExceptionTranslator"/>
<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
<property name="authenticationEntryPoint" ref="clientAuthenticationEntryPoint" />
</bean>
<authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="notifyUserDetailsService">
<password-encoder hash="bcrypt" />
</authentication-provider>
</authentication-manager>
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" />
<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="accessTokenValiditySeconds" value="12000000" />
<property name="clientDetailsService" ref="clientDetails" />
<property name="tokenEnhancer" ref="tokenEnhancer"/>
</bean>
<bean id="tokenEnhancer" class="com.spring.myapp.security.MyTokenEnhancer" />
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter" resource-id="test" token-services-ref="tokenServices" />
<oauth:client-details-service id="clientDetails">
<!-- client -->
<oauth:client client-id="restapp" authorized-grant-types="authorization_code,client_credentials" authorities="ROLE_APP" scope="read,write,trust" secret="secret" />
<oauth:client client-id="restapp" authorized-grant-types="password,authorization_code,refresh_token,implicit" secret="restapp" authorities="ROLE_APP" />
</oauth:client-details-service>
<sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
<!--you could also wire in the expression handler up at the layer of the
http filters. See https://jira.springsource.org/browse/SEC-1452 -->
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
Related
I am trying to create Oauth server with spring security and I am new to both of them.
The flow is, when I browse the following URL
http://localhost:8080/OAuthServer/oauth/authorize?response_type=code&redirect_uri=http://localhost:8080/client/handler&client_id=test
Problem 1 :I am being redirected to login
http://localhost:8080/OAuthServer/login
but after login authenticates my user is redirected to welcome page http://localhost:8080/OAuthServer/ instead of authorization page
Problem 2(strange): After I logout from welcome page and again do the same process again: broswe on OAuthServer/oauth/authorize?, it shows login page and after login,it is getting redirected to authorization page as expected. But this did not work on first try.
Problem 3 : Now, every time I browse OAuthServer/oauth/authorize? it shows authorization page instead of showing login page. This time I want to authenticate some other user but goes directly to authorization page.
In all the case, there is no error and I am getting authorization code and from code, I am getting access code and refresh code and able to access my resource \employee\list using access code
I am sure some config is wrong here. Please help me out.
Security.xml
<!-- Entry Url -->
<sec:http pattern="/oauth/token**" create-session="stateless"
entry-point-ref="oauthAuthenticationEntryPoint"
authentication-manager-ref="authenticationManager">
<sec:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<sec:anonymous enabled="false" />
<sec:custom-filter ref="clientCredentialsTokenEndpointFilter"
before="BASIC_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
</sec:http>
<sec:http pattern="/oauth/authorize**" create-session="never"
entry-point-ref="LoginEntry">
<sec:anonymous enabled="false" />
<sec:intercept-url pattern="/oauth/authorize"
access="IS_AUTHENTICATED_FULLY" />
</sec:http>
<bean id="LoginEntry"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<constructor-arg value="/login" />
</bean>
<sec:http pattern="/employee/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint" >
<sec:anonymous enabled="false" />
<sec:intercept-url pattern="/employee/**" access="ROLE_USER" />
<sec:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
</sec:http>
<sec:http pattern="/oauth/me**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint">
<sec:anonymous enabled="false" />
<sec:intercept-url pattern="/oauth/me" method="GET"
access="IS_AUTHENTICATED_FULLY" />
<sec:custom-filter ref="resourceServerFilter"
before="PRE_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
</sec:http>
<sec:http authentication-manager-ref="loginAuthentication"
disable-url-rewriting="true">
<sec:intercept-url pattern="/admin**" access="ROLE_USER" />
<sec:form-login login-page="/login"
authentication-failure-url="/login?error" username-parameter="username"
password-parameter="password" />
<sec:logout logout-success-url="/login?logout" />
<!-- enable csrf protection -->
<sec:csrf />
</sec:http>
<sec:authentication-manager id="loginAuthentication">
<sec:authentication-provider>
<sec:user-service>
<sec:user name="mkyong" password="123456" authorities="ROLE_USER" />
<sec:user name="test" password="1234" authorities="ROLE_USER" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
<!-- Server -->
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices"
authorization-request-manager-ref="SECAuthorizationRequestManager"
user-approval-handler-ref="SECTokenServicesUserApprovalHandler">
<oauth:authorization-code
authorization-code-services-ref="JdbcAuthorizationCodeServices" />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
</oauth:authorization-server>
<!-- Resource -->
<oauth:resource-server id="resourceServerFilter"
resource-id="springsec" token-services-ref="tokenServices" />
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="springsec" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler">
</bean>
<bean id="clientCredentialsTokenEndpointFilter" class="com.server.security.SECClientCredentialToken">
<property name="authenticationManager" ref="authenticationManager" />
<property name="clientDetails" ref="clientDetails" />
</bean>
<bean id="userCredentialsTokenEndpointFilter" class="com.server.security.SECUserCredential">
<property name="authenticationManager" ref="loginAuthentication" />
</bean>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider
user-service-ref="clientDetailsUserService" />
</sec:authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="clientDetails" class="com.server.security.SECClientDetailsService">
<property name="id" value="test" />
<property name="secretKey" value="mycompanykey" />
</bean>
<bean id="SECTokenServicesUserApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
<property name="tokenServices" ref="tokenServices" />
</bean>
<bean id="SECAuthorizationRequestManager"
class="org.springframework.security.oauth2.provider.DefaultAuthorizationRequestManager">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<bean id="JdbcAuthorizationCodeServices"
class="org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices">
<constructor-arg ref="jdbcTemplate" />
</bean>
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.JdbcTokenStore">
<constructor-arg ref="jdbcTemplate" />
</bean>
<bean id="jdbcTemplate"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://serverhost:7306/Oauth?useSSL=false" />
<property name="username" value="username" />
<property name="password" value="password" />
</bean>
<!-- End Persistence Layer -->
<!-- ModelViewController -->
<mvc:annotation-driven />
<mvc:default-servlet-handler />
<context:annotation-config />
<context:component-scan
base-package="com.server.security,com.server.resource,com.server.controller" />
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp" />
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean
class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" />
</list>
</property>
</bean>
Problem 1:
I think it is because of create-session="never" on "/oauth/authorize**", please check if the jsession create for first time or not and re-check for 2nd time.
Problem 2:
because you already redirected to home page so session created so it can store redirect in it
problem 3:
you have to use another session by using incognito window, or logout and login again with different user
I’m using Spring 3.2.11.RELEASE with OAuth 2.0.7.RELEASE. I have configured my authorization server to use a JDBC token store (the org.springframework.security.oauth2.provider.token.store.JdbcTokenStore class) . However, repeated requests with the same client ID using the grant_type=client_credentials return the same access token, even after server restarts. The token is valid (it has different expiration dates), but this seems like a security flaw. How do I make repeated valid requests return different access tokens? Below is my Spring configuration …
<http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<!-- The OAuth2 protected resources are separated out into their own block
so we can deal with authorization and error handling separately. This isn't
mandatory, but it makes it easier to control the behaviour. -->
<http pattern="/oauth/(users|clients)/.*" request-matcher="regex"
create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint"
use-expressions="true" xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/oauth/users/([^/].*?)/tokens/.*"
access="#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('write')"
method="DELETE" />
<intercept-url pattern="/oauth/users/.*"
access="#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('read')"
method="GET" />
<intercept-url pattern="/oauth/clients/.*"
access="#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.isClient() and #oauth2.hasScope('read')"
method="GET" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<expression-handler ref="oauthWebExpressionHandler" />
</http>
<!-- The OAuth2 protected resources are separated out into their own block
so we can deal with authorization and error handling separately. This isn't
mandatory, but it makes it easier to control the behaviour. -->
<http pattern="/me/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/me" access="ROLE_USER,SCOPE_READ" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="sparklr2" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="sparklr2/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"
xmlns="http://www.springframework.org/schema/beans">
<constructor-arg>
<list>
<bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</constructor-arg>
</bean>
<authentication-manager id="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider>
<user-service id="userDetailsService">
<user name="marissa" password="koala" authorities="ROLE_USER" />
<user name="paul" password="emu" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
<constructor-arg ref="dataSource" />
</bean>
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="tokenEnhancer" ref="tokenEnhancer" />
<property name="supportRefreshToken" value="true" />
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<bean id="tokenEnhancer"
class="org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter" />
<bean id="requestFactory"
class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<constructor-arg name="clientDetailsService" ref="clientDetails" />
</bean>
<bean id="approvalStore"
class="org.springframework.security.oauth2.provider.approval.TokenApprovalStore">
<property name="tokenStore" ref="tokenStore" />
</bean>
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:client-credentials />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter" entry-point-ref="entry"
resource-id="myprojectAssignment" token-services-ref="tokenServices" />
<bean id="entry" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<constructor-arg value="/myprojectassignment" />
</bean>
<oauth:client-details-service id="clientDetails">
<oauth:client client-id=“client”
authorized-grant-types="client_credentials" authorities="ROLE_CLIENT"
scope="read,write" secret=“password” />
</oauth:client-details-service>
<mvc:default-servlet-handler />
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
<http pattern="/api/**"
create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/**"
access="IS_AUTHENTICATED_FULLY"/>
<custom-filter ref="resourceServerFilter"
before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
Create your own AuthenticationKeyGenerator for your tokenStore as mentioned here.
I'm using Spring Security + Oauth2 for multiple propose. The cenario is: There is a public context, a private context and a REST context (the two lasts are authenticated).
For the private context (/private/), the users that are not authenticated, should be redirected to /login and before authenticating, would be redirected to /private/index. For the REST context (/rest/) the user shoud have a token and then could acess that area.
Remembering this is a POC and the code is very basic at all.
spring-security.xml
<beans:beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security" 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.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/security/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2.xsd">
<sec:http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
use-expressions="true" xmlns="http://www.springframework.org/schema/security">
<sec:intercept-url pattern="/oauth/token" access="isAuthenticated()" />
<sec:anonymous enabled="false" />
<sec:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request
parameters -->
<sec:custom-filter ref="clientCredentialsTokenEndpointFilter"
after="BASIC_AUTH_FILTER" />
<sec:access-denied-handler ref="oauthAccessDeniedHandler" />
</sec:http>
<!-- Spring Security Context -->
<sec:http auto-config="true" use-expressions="true"
xmlns="http://www.springframework.org/schema/security">
<sec:intercept-url pattern="/" access="permitAll" />
<sec:intercept-url pattern="/private/**" access="hasRole('ROLE_USER')" />
<sec:form-login authentication-failure-url="/login?error" />
<sec:logout logout-success-url="/login?logout" />
</sec:http>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
<constructor-arg>
<list>
<bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
<bean
class="org.springframework.security.web.access.expression.WebExpressionVoter" />
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</constructor-arg>
</bean>
<sec:authentication-manager id="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<sec:authentication-provider
user-service-ref="clientDetailsUserService" />
</sec:authentication-manager>
<sec:authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<sec:authentication-provider>
<sec:user-service id="userDetailsService">
<sec:user name="admin" password="admin" authorities="ROLE_ADMIN, ROLE_USER" />
<sec:user name="user" password="user" authorities="ROLE_USER" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<!-- Used for the persistenceof tokens (currently an in memory implementation) -->
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" />
<!-- Used to create token and and every thing about them except for their
persistence that is reposibility of TokenStore (Given here is a default implementation) -->
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler">
</bean>
<!-- authorization-server aka AuthorizationServerTokenServices is an interface
that defines everything necessary for token management -->
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="test" token-services-ref="tokenServices" />
<!-- ClientsDeailsService: Entry Point to clients database (given is in
memory implementation) -->
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="my-trusted-client"
authorized-grant-types="password,authorization_code,refresh_token,implicit"
authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" scope="read,write,trust"
access-token-validity="60" />
<oauth:client client-id="my-trusted-client-with-secret"
authorized-grant-types="password,authorization_code,refresh_token,implicit"
secret="somesecret" authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" />
<oauth:client client-id="my-client-with-secret"
authorized-grant-types="client_credentials" authorities="ROLE_CLIENT"
scope="read" secret="secret" />
<oauth:client client-id="my-less-trusted-client"
authorized-grant-types="authorization_code,implicit" authorities="ROLE_CLIENT" />
<oauth:client client-id="my-less-trusted-autoapprove-client"
authorized-grant-types="implicit" authorities="ROLE_CLIENT" />
<oauth:client client-id="my-client-with-registered-redirect"
authorized-grant-types="authorization_code,client_credentials"
authorities="ROLE_CLIENT" redirect-uri="http://anywhere?key=value"
scope="read,trust" />
<oauth:client client-id="my-untrusted-client-with-registered-redirect"
authorized-grant-types="authorization_code" authorities="ROLE_CLIENT"
redirect-uri="http://anywhere" scope="read" />
<oauth:client client-id="tonr" resource-ids="test"
authorized-grant-types="authorization_code,implicit" authorities="ROLE_CLIENT"
scope="read,write" secret="secret" />
<!--Self defined client -->
<oauth:client client-id="the_client"
authorized-grant-types="authorization_code,client_credentials"
authorities="ROLE_USER" scope="read,write,trust" secret="secret" />
</oauth:client-details-service>
<sec:global-method-security
pre-post-annotations="enabled" proxy-target-class="true"
xmlns="http://www.springframework.org/schema/security">
<!--you could also wire in the expression handler up at the layer of the
http filters. See https://jira.springsource.org/browse/SEC-1452 -->
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
The issue was solved.
For further consulting, just change the word "alias" to "id" as below
<sec:authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
correct:
<sec:authentication-manager id="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
And works!
i,
I’m using Spring 3.2.11.RELEASE with spring-security-oauth2 v 2.0.7.RELEASE. I want to set up a resource server such that if a client properly submits their id and secret with a grant type of client_credentials, they can use the resulting token to POST data to a URL. However, I can’t figure out how to secure that URL (I can POST to that URL even if the token is incorrect). Below is how I’m trying to configure my resource server
<oauth:resource-server id="resourceServerFilter" entry-point-ref="entry"
resource-id="writeUrl" token-services-ref="tokenServices" />
<bean id="entry" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<constructor-arg value="/writeUrl" />
</bean>
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="my-client-with-secret"
authorized-grant-types="client_credentials" authorities="ROLE_CLIENT"
scope="read,write" secret="secret" />
</oauth:client-details-service>
But, as I said, POSTing data to “/writeUrl” whether or not I have a valid token is successful and I wish to lock down that URL. How do I do that? My complete OAuth2 application context configuration is below …
<http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<!-- The OAuth2 protected resources are separated out into their own block
so we can deal with authorization and error handling separately. This isn't
mandatory, but it makes it easier to control the behaviour. -->
<http pattern="/oauth/(users|clients)/.*" request-matcher="regex"
create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint"
use-expressions="true" xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/oauth/users/([^/].*?)/tokens/.*"
access="#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('write')"
method="DELETE" />
<intercept-url pattern="/oauth/users/.*"
access="#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('read')"
method="GET" />
<intercept-url pattern="/oauth/clients/.*"
access="#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.isClient() and #oauth2.hasScope('read')"
method="GET" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
<expression-handler ref="oauthWebExpressionHandler" />
</http>
<!-- The OAuth2 protected resources are separated out into their own block
so we can deal with authorization and error handling separately. This isn't
mandatory, but it makes it easier to control the behaviour. -->
<http pattern="/me/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false" />
<intercept-url pattern="/me" access="ROLE_USER,SCOPE_READ" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="sparklr2" />
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="sparklr2/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"
xmlns="http://www.springframework.org/schema/beans">
<constructor-arg>
<list>
<bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</constructor-arg>
</bean>
<authentication-manager id="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider>
<user-service id="userDetailsService">
<user name="marissa" password="koala" authorities="ROLE_USER" />
<user name="paul" password="emu" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
<bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
</bean>
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
<constructor-arg ref="dataSource" />
</bean>
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="tokenEnhancer" ref="tokenEnhancer" />
<property name="supportRefreshToken" value="true" />
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<bean id="tokenEnhancer"
class="org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter" />
<bean id="requestFactory"
class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<constructor-arg name="clientDetailsService" ref="clientDetails" />
</bean>
<bean id="approvalStore"
class="org.springframework.security.oauth2.provider.approval.TokenApprovalStore">
<property name="tokenStore" ref="tokenStore" />
</bean>
<oauth:authorization-server
client-details-service-ref="clientDetails" token-services-ref="tokenServices">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter" entry-point-ref="entry"
resource-id="writeUrl" token-services-ref="tokenServices" />
<bean id="entry" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<constructor-arg value="/writeUrl" />
</bean>
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="my-client-with-secret"
authorized-grant-types="client_credentials" authorities="ROLE_CLIENT"
scope="read,write" secret="secret" />
</oauth:client-details-service>
<mvc:default-servlet-handler />
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
There should be an intercept-url in the resource endpoint configuration with access restricted to authorized users (I'm guessing your url could match the following pattern)
<security:http pattern="/writeUrl/**"
create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager">
<security:anonymous enabled="false" />
<security:intercept-url pattern="/**"
access="IS_AUTHENTICATED_FULLY"/>
<security:custom-filter ref="resourceServerFilter"
before="PRE_AUTH_FILTER" />
<security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>
I am adding spring security oauth2 to my spring boot application. I have followed a few of the examples on the web and in github from the spring team (had to make some mods for my use case), but I am still not able to return an oauth2 access token from the /oauth/token endpoint. I have been working on this for several days and started off trying to do it in JavaConfig, but then switched to xml config and was able to make some progress. I should note the only config I am doing in xml is the security config and related security beans, all other config is done via JavaConfig.
I am able to successfully authenticate my user (using username & password) using Basic auth, but when it comes to the next step to generate and return the bearer token, this is not happening. Note, I am using a database for storing my user credentials and to store my access tokens (once they get created).
I am making a POST request using grant_type=password with a client id and client secret.
I am under the impression spring oauth2 would handle creating the access token for me and returning it, but maybe this isn't correct or my xml config maybe wrong? Many thanks for any assistance!
Here is my security config xml below:
<http pattern="/oauth/token"
create-session="stateless"
authentication-manager-ref="authenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/**" method="GET" access="ROLE_DENY" />
<intercept-url pattern="/**" method="PUT" access="ROLE_DENY" />
<intercept-url pattern="/**" method="DELETE" access="ROLE_DENY" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request
parameters>
<custom-filter ref="clientCredentialsTokenEndpointFilter"
after="BASIC_AUTH_FILTER" /-->
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<http pattern="/**" create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
xmlns="http://www.springframework.org/schema/security">
<!-- authentication-manager-ref="authenticationManager"
access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security"-->
<anonymous enabled="false" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" />
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<!-- property name="realmName" value="f2rRealm" /-->
</bean>
<bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="f2r/client" />
<property name="typeName" value="Basic" />
</bean>
<bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<bean id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<authentication-manager alias="authenticationManager"
xmlns="http://www.springframework.org/schema/security" >
<!-- authentication-provider user-service-ref="clientDetailsUserService" /-->
<authentication-provider ref="authenticationProvider" />
</authentication-manager>
<bean id="clientDetails" class="com.f2r.security.oauth2.F2RJdbcClientDetailsService" >
<constructor-arg ref="dataSource" />
<property name="clientId" value="f2r" />
<property name="clientSecret" value="f2rsecret" />
<property name="passwordEncoder" ref="passwordEncoder" />
</bean>
<!-- bean id="clientDetailsService"
class="com.f2r.security.oauth2.F2RJdbcClientDetailsService">
<constructor-arg ref="dataSource" />
<property name="clientDetails" ref="clientDetails" />
<property name="passwordEncoder" ref="passwordEncoder" />
</bean-->
<bean id="clientDetailsUserService"
class="com.f2r.security.oauth2.F2RClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails" />
<property name="passwordEncoder" ref="passwordEncoder" />
</bean>
<authentication-manager id="userAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<!-- authentication-provider ref="customUserAuthenticationProvider" /-->
<authentication-provider ref="authenticationProvider" />
</authentication-manager>
<!-- bean id="customUserAuthenticationProvider" class="com.f2r.security.F2RAuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService" />
</bean-->
<bean id="authenticationProvider" class="com.f2r.security.F2RAuthenticationProvider">
<!-- property name="userDetailsService" ref="userDetailsService" /-->
<property name="userDetailsService" ref="clientDetailsUserService" />
</bean>
<bean id="userDetailsService" class="com.f2r.security.F2RUserDetailsService" />
<bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<property name="tokenStore" ref="tokenStore" />
<property name="clientDetailsService" ref="clientDetails" />
<property name="requestFactory" ref="requestFactory" />
</bean>
<bean id="requestFactory"
class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<constructor-arg ref="clientDetails" />
</bean>
<oauth:authorization-server
client-details-service-ref="clientDetails"
token-services-ref="tokenServices"
token-endpoint-url="/oauth/token"
authorization-endpoint-url="/oauth/authorize" >
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<!-- oauth:password authentication-manager-ref="userAuthenticationManager" /-->
<oauth:password />
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
token-services-ref="tokenServices" />
<bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore" >
<constructor-arg ref="dataSource"/>
</bean>
<bean id="tokenServices"
class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="clientDetailsService" ref="clientDetails" />
</bean>
<mvc:annotation-driven />
<mvc:default-servlet-handler />
<sec:global-method-security
pre-post-annotations="enabled" proxy-target-class="true">
<!--you could also wire in the expression handler up at the layer of the
http filters. See https://jira.springsource.org/browse/SEC-1452 -->
<sec:expression-handler ref="oauthExpressionHandler" />
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />