Rationalize some features and merge in customizers from Spring Cloud
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user