Rationalize some features and merge in customizers from Spring Cloud

This commit is contained in:
Dave Syer
2015-05-22 16:32:47 +01:00
parent 5468949a55
commit af320b49bf
14 changed files with 503 additions and 162 deletions

View File

@@ -1460,6 +1460,162 @@ All of the above can be switched on and off or modified using external propertie
features add a `@Bean` of type `WebSecurityConfigurerAdapter` with
`@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)`.
=== OAuth2
If you have `spring-security-oauth2` on your classpath you can take advantage of some
autoconfiguration to make it easy to set up Authorization or Resource Server features by
configuring some property values in the `Environment`.
==== Authorization Server
To create an Authorization Server and grant access tokens you need to
`@EnableAuthorizationServer` and provide
`spring.oauth2.client.[clientId,clientSecret]`. The client will be
registered for you in an in-memory repository. To switch off the
autoconfiguration and configure the Authorization Server features
yourself just add a `@Bean` of type
`AuthorizationServerConfigurer`. Having done that you will be able to
usethe client credentials to create an access token, e.g.
----
$ curl client:secret@localhost:8080/oauth/token -d grant_type=password -d username=user -d password=pwd
----
The basic auth credentials for the `/token` endpoint are the client id
and secret, and the user credentials are the normal Spring Security
user details (which default in Spring Boot to "user" and a random
password).
==== Resource Server
To use the access token you need a Resource Server (which can be the
same as the Authorization Server). Creating a Resource Server is easy:
just add `@EnableResourceServer` and provide some configuration to
allow the server to decode access tokens. If your app is also an
Authorization Server it already knows how to decode tokens, so there
is nothing else to do. If your app is a standalone service then you
need to give it some more configuration. Here are the options, one of
the following:
* `spring.oauth2.resource.userInfoUri` to use the "/me" resource
(e.g. "https://uaa.run.pivotal.io/userinfo" on PWS), or
* `spring.oauth2.resource.tokenInfoUri` to use the token decoding endpoint
(e.g. "https://uaa.run.pivotal.io/check_token" on PWS).
If you specify both the `userInfoUri` and the `tokenInfoUri` then
you can set a flag to say that one is preferred over the other
(`preferTokenInfo=true` is the default).
Alternatively (instead of `userInfoUri` or `tokenInfoUri`) if the
tokens are JWTs you can configure a
`spring.oauth2.resource.jwt.keyValue` to decode them locally,
where the key is a verification key. The verification key value is
either a symmetric secret or PEM-encoded RSA public key. If you don't
have the key and it's public you can provide a URI where it can be
downloaded (as a JSON object with a "value" field) with
`spring.oauth2.resource.jwt.keyUri`. E.g. on PWS:
----
$ curl https://uaa.run.pivotal.io/token_key
{"alg":"SHA256withRSA","value":"-----BEGIN PUBLIC KEY-----\nMIIBI...\n-----END PUBLIC KEY-----\n"}
----
WARNING: If you use the `spring.oauth2.resource.jwt.keyUri` the
authorization server needs to be running when your application starts
up. It will log a warning if it can't find the key, and tell you what
to do to fix it.
=== Token Type in User Info
Google (and certain other 3rd party identity providers) is more strict
about the token type name that is sent in the headers to the user info
endpoint. The default is "Bearer" which suits most providers and
matches the spec, but if you need to change it you can set
`spring.oauth2.resource.tokenType`.
=== Customizing the User Info RestTemplate
If you have a `userInfoUri`, the Resource Server features use an
`OAuth2RestTemplate` internally to fetch user details for
authentication. This is provided as a qualified `@Bean` with id
"userInfoRestTemplate", but you shouldn't need to know that to just
use it. The default should be fine for most providers, but
occasionally you might need to add additional interceptors, or change
the request authenticator (which is how the token gets attached to
outgoing requests). To add a customization just create a bean of type
`UserInfoRestTemplateCustomizer` - it has a single method that will be
called after the bean is created but before it is initialized. The
rest template that is being customized here is _only_ used internally
to carry out authentication.
[TIP]
====
To set an RSA key value in YAML use the "pipe" continuation
marker to split it over multiple lines ("|") and remember to indent
the key value (it's a standard YAML language feature). Example:
[source,yaml,indent=0]
----
oauth2:
resource:
jwt:
keyValue: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC...
-----END PUBLIC KEY-----
----
====
==== Client
To make your webapp into an OAuth2 client you can simply
`@EnableOAuth2Client` and Spring Boot will create an
`OAuth2RestTemplate` for you to autowire. It uses the
`spring.oauth2.client.*` as credentials (the same as you might be
using in the Authorization Server), but in addition it will need to
know the authorization and token URIs in the Authorization Server. For
example:
.application.yml
[source,yaml]
----
spring:
oauth2:
client:
clientId: bd1c0a783ccdd1c9b9e4
clientSecret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1
accessTokenUri: https://github.com/login/oauth/access_token
userAuthorizationUri: https://github.com/login/oauth/authorize
clientAuthenticationScheme: form
resource:
userInfoUri: https://api.github.com/user
preferTokenInfo: false
----
An app with this configuration will redirect to github for
authorization if you attempt to use the `OAuth2RestTemplate`. If you
are already signed into github you won't even notice that it has
authenticated. These specific credentials will only work if your app
is running on port 8080 (register your own client app in Github or
other provider for more flexibility).
To limit the scope that the client asks for when it obtains an access token
you can set `spring.oauth2.client.scope` (comma separated or an array in YAML). By
default the scope is empty and it is up to to Authorization Server to
decide what the defaults should be, usually depending on the settings in
the client registration that it holds.
NOTE: There is also a setting for
`spring.oauth2.client.clientAuthenticationScheme` which defaults to
"header" (but you might need to set it to "form" if, like Github for
instance, your OAuth2 provider doesn't like header authentication). In
fact, the `spring.oauth2.client.*` properties are bound to an instance
of `AuthorizationCodeResourceDetails` so all its properties can be
specified.
=== Actuator Security
If the Actuator is also in use, you will find:
* The management endpoints are secure even if the application endpoints are unsecure.