(Quick Reference)
7 Configuration - Reference Documentation
Authors: Brian Saville, Bobby Vandiver, Roy Willemse
Version: 3.0.0-RC2
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 in
grails-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 a
TokenEnhancerChain
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 three
UserApprovalHandler
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 a
ClientDetails
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's
securityContextPersistenceFilter
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 the
additionalInformation
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.OAuth2Utilsclass 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.JsonSlurperclass 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)
}
}
The serialize
methods are guaranteed to receive a non-null argument, although they may be provided an empty collection. The deserialize
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)
}