7 Configuration
Version: 4.0.0.BUILD-SNAPSHOT
Table of Contents
7 Configuration
The plugin is pessimistic by default, locking down as much as possible to guard against accidental security breaches. However, these constraints can be modified if so desired ingrails-app/conf/application.groovy
. The properties below exist in the grails.plugin.springsecurity.oauthProvider
namespace.
7.1 Plugin
The following properties define whether the plugin is active and where the required filters are registered in the Spring Security filter chain:Property | Default Value | Meaning |
---|---|---|
active | true | Whether the plugin is enabled. |
filterStartPosition | SecurityFilterPosition.X509_FILTER.order | The position in the filter chain of the OAuth2AuthenticationProcessingFilter , which handles authentication for resource access by extracting an access token from the incoming request. |
clientFilterStartPosition | SecurityFilterPosition.DIGEST_AUTH_FILTER.order | The position in the filter chain of the ClientCredentialsTokenEndpointFilter , which handles client authentication. |
statelessFilterStartPosition | SecurityFilterPosition.SECURITY_CONTEXT_FILTER.order | The position in the filter chain of the StatelessSecurityContextPersistenceFilter , which is used to ensure access to OAuth 2.0 resources and the token endpoint are stateless. |
exceptionTranslationFilterStartPosition | SecurityFilterPosition.EXCEPTION_TRANSLATION_FILTER.order | The position in the filter chain of the ExceptionTranslationFilter configured with a NullRequestCache , which is used to ensure access to OAuth 2.0 resources and the token endpoint are stateless. |
basicAuthenticationFilterStartPosition | SecurityFilterPosition.BASIC_AUTH_FILTER.order | The position in the filter chain of the BasicAuthenticationFilter configured with a NullRememberMeServices , which is used to ensure access to OAuth 2.0 resources and the token endpoint are stateless. |
registerStatelessFilter | true | When this is true , the plugin will register the statelessSecurityContextPersistenceFilter in the filter chain after the securityContextPersistenceFilter provided by the Spring Security Core plugin. See below for additional configuration of the filter chain(s) required to properly secure access to OAuth 2.0 resources. |
registerExceptionTranslationFilter | true | When this is true , the plugin will register the oauth2ExceptionTranslationFilter in the filter chain after the exceptionTranslationFilter provided by the Spring Security Core plugin. See below for additional configuration of the filter chain(s) required to properly secure access to OAuth 2.0 resources. |
registerBasicAuthenticationFilter | true | When this is true , the plugin will register the oauth2BasicAuthenticationFilter in the filter chain after the basicAuthenticationFilter provided by the Spring Security Core plugin. See below for additional configuration of the filter chain(s) required to properly secure access to OAuth 2.0 resources. |
realmName | Grails OAuth2 Realm | Realm name included in the WWW-Authenticate header in a challenge response. |
7.2 Endpoint URLs
The endpoint URLs used by the underlying Spring Security OAuth 2.0 implementation can be changed using the following properties:Property | Default Value | Meaning |
---|---|---|
authorizationEndpointUrl | '/oauth/authorize' | Authorization endpoint URL. |
tokenEndpointUrl | '/oauth/token' | Token endpoint URL. |
userApprovalEndpointUrl | '/oauth/confirm_access' | URL of the view to display for confirming access to protected resources. |
userApprovalParameter | 'user_oauth_approval' | The name of the parameter submitted in the confirmation request. The value of this parameter is used to determine whether a user has confirmed (true ) or denied (false ) access. |
errorEndpointUrl | '/oauth/error' | URL of the view to display if an error occurs while interacting with the authorization endpoint and the error cannot be returned as part of the query or fragment of the client's redirect URI. This is usually the case when there is a problem with the requesting client's redirect URI. |
When changing the URL for the authorizationEndpointUrl
or tokenEndpointUrl
, you must update Spring Security Core's configuration. Using the staticRules
configuration and the default configuration as an example, your grails-app/conf/Config.groovy
will look like this:
grails.plugin.springsecurity.controllerAnnotations.staticRules = [ [pattern: '/oauth/authorize', access: "isFullyAuthenticated() and (request.getMethod().equals('GET') or request.getMethod().equals('POST'))"], [pattern: '/oauth/token', access: "isFullyAuthenticated() and request.getMethod().equals('POST')"], ...
To change the authorizationEndpointUrl
to /authorize
, you will need to make the following changes in grails-app/conf/application.groovy
:
grails.plugin.springsecurity.oauthProvider.authorizationEndpointUrl = '/authorize'grails.plugin.springsecurity.controllerAnnotations.staticRules = [ [pattern: '/authorize', access: "isFullyAuthenticated() and (request.getMethod().equals('GET') or request.getMethod().equals('POST'))"], [pattern: '/oauth/token', access: "isFullyAuthenticated() and request.getMethod().equals('POST')"], ...
7.3 Token Services
The following properties apply to how tokens are issued and how long they are valid. If a client has defined a specific token validity length, the client's length will take priority over the values configured for the token services.Property | Default Value | Meaning |
---|---|---|
tokenServices.registerTokenEnhancers | true | Whether registered TokenEnhancer instances should be used. |
tokenServices.accessTokenValiditySeconds | 60 * 60 * 12 | The length of time that an access token will be valid after it has been issued. |
tokenServices.refreshTokenValiditySeconds | 60 * 60 * 24 * 30 | The length of time that a refresh token will be valid after it has been issued. |
tokenServices.reuseRefreshToken | false | Whether a new refresh token should be generated if one is currently available. |
tokenServices.supportRefreshToken | true | Whether a refresh token can be issued upon request. |
7.4 Token Enhancers Configuration
By default, the plugin will register aTokenEnhancerChain
with an empty list of TokenEnhancer
delegates. When the tokenServices.registerTokenEnhancers
option is true
, the plugin will detect and use all registered Spring beans implementing the TokenEnhancer
interface.If more control over the ordering of the enhancers in the chain is desired, set the tokenServices.registerTokenEnhancers
option to false
. The TokenEnhancerChain
bean is registered under the name tokenEnhancerChain
, so the plugin consumer can get a handle to it for more fine grained configuration.
This bean is aliased under the name tokenEnhancer
. This is the bean that is registered with the tokenServices
bean. This is done to allow customization of the registered enhancer with minimal effort. Just override the tokenEnhancer
bean.
7.5 Supported Grant Types
The following properties determine which of the standard grant types the application can support. Individual clients must declare which of the enabled grant types they support.Property | Default Value | Meaning |
---|---|---|
grantTypes.authorizationCode | true | Whether the Authorization Code Grant is supported. |
grantTypes.implicit | true | Whether the Implicit Grant is supported. |
grantTypes.clientCredentials | true | Whether the Client Credentials Grant is supported. |
grantTypes.password | true | Whether the Resource Owner Password Credentials is supported. |
grantTypes.refreshToken | true | Whether Refresh Token Grant is supported. |
7.6 Additional Authorization Constraints
The plugin enforces the following restrictions on authorization request params:Property | Default Value | Meaning |
---|---|---|
authorization.requireRegisteredRedirectUri | true | Whether a client is required to have registered a redirect URI before performing an authorization request. This addresses RFC 6749 Section 10.6: Authorization Code Redirection URI Manipulation and RFC 6749 Section 10.15: Open Redirectors . |
authorization.requireScope | true | Whether the scope for each access token requested is required. |
7.7 User Approval Configuration
The plugin provides support for the threeUserApprovalHandler
implementations provided by the underlying Spring OAuth library. This only applies to the authorization endpoint and allows you to configure the method of auto-approval used by the application. The following properties determine which method of auto-approval to use and how it is configured:Property | Default Value | Meaning |
---|---|---|
auto | EXPLICIT | Determines which method of auto-approval to use. The value is determined by grails.plugin.springsecurity.oauthProvider.approval.UserApprovalSupport and must be EXPLICIT , TOKEN_STORE or APPROVAL_STORE . |
handleRevocationAsExpiry | false | When configured to use an approval store for auto-approval, this determines if approval revocation should expire the corresponding approval instance (true ) or delete the approval (false ) outright. |
approvalValiditySeconds | 60 * 60 * 24 * 30 | When configured to use an approval store for auto-approval, the length of time that an approval will be valid after it has been granted. |
scopePrefix | 'scope.' | When configured to use an approval store for auto-approval, the prefix added to approved scopes as part of the auto-approval process. |
The auto
property determines which of the three UserApprovalHandler
provided by Spring OAuth will be used.
The default option is to require explicit approval for every authorization and is equivalent to setting auto
to EXPLICIT
:
grails.plugin.springsecurity.oauthprovider.approval.auto = UserApproval.EXPLICIT
Auto-approval based on previously issued access tokens is supported via the TokenStoreUserApprovalHandler
provided by Spring OAuth and can be configured by setting auto
to TOKEN_STORE
:
grails.plugin.springsecurity.oauthprovider.approval.auto = UserApproval.TOKEN_STORE
Auto-approval based on prior approvals is supported via the ApprovalStoreUserApprovalHandler
provided by Spring OAuth and can be configured by setting auto
to APPROVAL_STORE
:
grails.plugin.springsecurity.oauthprovider.approval.auto = UserApproval.APPROVAL_STORE
The plugin will configure the TokenStoreUserApprovalHandler
and ApprovalStoreUserApprovalHandler
to use the GORM backed TokenStore
and ApprovalStore
respectively.
Please consult Spring OAuth directly for more information on the usage of the TokenStore
and ApprovalStore
methods of auto-approval.
7.8 Default Client Configuration
An application can use the following properties to define the default values that will be used when creating aClientDetails
instance if a client has not specified a value. The default configuration will not allow a client to retrieve an access token unless they have explicitly registered support for the requested grant type.Property | Default Value | Meaning |
---|---|---|
defaultClientConfig.resourceIds | [] | Resources the client is authorized to access. This is currently unused as access to resources is controlled by Spring Security Core's rules. |
defaultClientConfig.authorizedGrantTypes | [] | Grant types the client supports. |
defaultClientConfig.scope | [] | Scope to use for each access token request. |
defaultClientConfig.autoApproveScopes | [] | Scopes to auto-approve for authorization requests. Including a value of true in the list will auto-approve all scopes for clients using the default configuration. |
defaultClientConfig.registeredRedirectUri | null | URI to redirect the user-agent to during an authorization code or implicit grant. |
defaultClientConfig.authorities | [] | Roles and authorities granted to the client. |
defaultClientConfig.accessTokenValiditySeconds | null | The length of time that an access token will be valid after it has been issued. This is used instead of the length configured for token services if available. |
defaultClientConfig.refreshTokenValiditySeconds | null | The length of time that a refresh token will be valid after it has been issued. This is used instead of the length configured for token services if available. |
defaultClientConfig.additionalInformation | [:] | Additional information about the client. This is not required by OAuth 2.0 but is exposed in the underlying Spring library. |
7.9 Filter Chain Configuration
Spring Security Core plugin'ssecurityContextPersistenceFilter
stores state in the HTTP session. Access to the token endpoint and OAuth 2.0 resources must be stateless.By default, the OAuth2 plugin will register the statelessSecurityContextPersistenceFilter
in the filter chain after the securityContextPersistenceFilter
provided by the Spring Security Core plugin. This is provided as a convenience for the plugin consumer, so they can remove one filter or the other to easily achieve stateful or stateless request handling. See the example below. This automatic filter registration can be disabled by setting the registerStatelessFilter
configuration option to false
.
The plugin registers an OAuth2AuthenticationProcessingFilter
under the bean name oauth2ProviderFilter
. This filter provides token authentication using the underlying token store for resource access.
The plugin registers a ClientCredentialsTokenEndpointFilter
under the bean name clientCredentialsTokenEndpointFilter
. This filter is responsible for authenticating the client specified in any OAuth 2.0 requests. The plugin also registers a BasicAuthenticationFilter
under the bean name oauth2BasicAuthenticationFilter
. This filter is responsible for authenticating the client via HTTP Basic authentication, which is the recommended method in the OAuth 2.0 specification.
Finally, the plugin registers an ExceptionTranslationFilter
under the bean name oauth2ExceptionTranslationFilter
. This filter is created with a NullRequestCache
instance rather than the HttpSessionRequestCache
instance that the Spring Security Core plugin provided ExceptionTranslationFilter
is created with. Similar to the statelessSecurityContextPersistenceFilter
, this filter is registered automatically by the plugin but can be disabled by setting the registerExceptionTranslationFilter
configuration option to false
.
The following filter chain configuration is recommended:
grails.plugin.springsecurity.filterChain.chainMap = [ [pattern: '/oauth/token', filters: 'JOINED_FILTERS,-oauth2ProviderFilter,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-rememberMeAuthenticationFilter,-exceptionTranslationFilter'], [pattern: '/securedOAuth2Resources/**', filters: 'JOINED_FILTERS,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-rememberMeAuthenticationFilter,-oauth2BasicAuthenticationFilter,-exceptionTranslationFilter'], [pattern: '/**', filters: 'JOINED_FILTERS,-statelessSecurityContextPersistenceFilter,-oauth2ProviderFilter,-clientCredentialsTokenEndpointFilter,-oauth2BasicAuthenticationFilter,-oauth2ExceptionTranslationFilter'] ]
The oauth2ProviderFilter
and stateful securityContextPersistenceFilter
and exceptionTranslationFilter
are removed from the token endpoint's filter chain. With the securityContextPersistenceFilter
removed, the statelessSecurityContextPersistenceFilter
will be used to ensure access token requests are stateless. Similarly, removing the exceptionTranslationFilter
will allow the oauth2ExceptionTranslationFilter
to take its place in the filter chain.
The securityContextPersistenceFilter
and exceptionTranslationFilter
are also removed from the filter chain for OAuth 2.0 resources. However, the oauth2ProviderFilter
must not be removed, as this filter is responsible for authenticating the OAuth 2.0 access token included in the request.
It is recommend that filter chain(s) for non-OAuth 2.0 resources have all OAuth 2.0 specific filters removed. These include: statelessSecurityContextPersistenceFilter
, oauth2ProviderFilter
, clientCredentialsTokenEndpointFilter
, basicAuthenticationFilter
and oauth2ExceptionTranslationFilter
. It is also recommended that any unnecessary filters such as the rememberMeAuthenticationFilter
and authenticationProcessingFilter
are removed from the filter chains for the token endpoint and OAuth 2.0 resources.
7.10 Domain Class Custom Serialization Configuration
The default behavior of the plugin is to serialize theadditionalInformation
and scope
properties of the Client
and AccessToken
classes as a Map<String, Object>
and Set<String>
respectively. This is how the s2-init-oauth2-provider script will generate the domain classes. However, this might not be ideal for all plugin consumers who want more control over the serialization of these fields.To accommodate these users, it is possible to override the default serialization method on a case-by-case basis. The plugin provides two interfaces to accomplish.
For the additionalInformation
fields:
package grails.plugin.springsecurity.oauthprovider.serialization;import java.util.Map;
public interface OAuth2AdditionalInformationSerializer {
Object serialize(Map<String, Object> additionalInformation);
Map<String, Object> deserialize(Object additionalInformation); }
For the scope
field:
package grails.plugin.springsecurity.oauthprovider.serialization;import java.util.Set;
public interface OAuth2ScopeSerializer {
Object serialize(Set<String> scopes);
Set<String> deserialize(Object scopes); }
By default, the plugin registers implementations that do little more than return the argument provided to each method. The following table shows which plugin provided Spring beans implement these interfaces and how they're used:
Bean Name | Interface Implemented | Description |
---|---|---|
clientAdditionalInformationSerializer | OAuth2AdditionalInformationSerializer | Handles deserialization of the additionalInformation property of the Client class into a Map<String, Object> . Only the deserialize method is used by the plugin at this time. |
accessTokenAdditionalInformationSerializer | OAuth2AdditionalInformationSerializer | Handles serialization and deserialization of the additionalInformation property of the AccessToken class into a Map<String, Object> . |
accessTokenScopeSerializer | OAuth2ScopeSerializer | Handles serialization and deserialization of the scope property of the AccessToken class into a Set<String> . |
Overriding these beans in resources.groovy
will allow the plugin consumer to customize how these fields are serialized. However, this will require the affected domain class to be modified to accommodate the change. For example, let's change the AccessToken
to serialized its additionalInformation
as JSON String
and its scope
as white space delimited String
.
First, modify the AccessToken
class to reflect the change in the storage of these fields:
package test.oauth2class AccessToken {
String authenticationKey byte[] authentication
String username String clientId
String value String tokenType
Date expiration String additionalInformation
String scope
static hasOne = [refreshToken: String]
static constraints = { username nullable: true clientId nullable: false, blank: false value nullable: false, blank: false, unique: true tokenType nullable: false, blank: false expiration nullable: false scope nullable: false refreshToken nullable: true authenticationKey nullable: false, blank: false, unique: true authentication nullable: false, minSize: 1, maxSize: 1024 * 4 additionalInformation nullable: true }
static mapping = { version false scope lazy: false } }
Next, implement the earlier described interfaces:
package testimport grails.plugin.springsecurity.oauthprovider.serialization.OAuth2ScopeSerializer import org.springframework.security.oauth2.common.util.OAuth2Utils
class WhiteSpaceDelimitedStringScopeSerializer implements OAuth2ScopeSerializer {
@Override Object serialize(Set<String> scopes) { return OAuth2Utils.formatParameterList(scopes) }
@Override Set<String> deserialize(Object scopes) { return OAuth2Utils.parseParameterList(scopes) } }
And:
package testimport grails.plugin.springsecurity.oauthprovider.serialization.OAuth2AdditionalInformationSerializer import groovy.json.JsonOutput import groovy.json.JsonSlurper
class JsonAdditionalInformationSerializer implements OAuth2AdditionalInformationSerializer {
@Override Object serialize(Map<String, Object> additionalInformation) { JsonOutput.toJson(additionalInformation) }
@Override Map<String, Object> deserialize(Object additionalInformation) { new JsonSlurper().parseText(additionalInformation as String) } }
Theserialize
methods are guaranteed to receive a non-null argument, although they may be provided an empty collection. Thedeserialize
methods are expected to return a non-null value.
Finally, in resources.groovy
, override the appropriate beans:
import test.JsonAdditionalInformationSerializer import test.WhiteSpaceDelimitedStringScopeSerializerbeans = { // Other beans here
accessTokenAdditionalInformationSerializer(JsonAdditionalInformationSerializer) accessTokenScopeSerializer(WhiteSpaceDelimitedStringScopeSerializer) }