Cleaned up client configuration page

master
Justin Richer 2014-05-27 16:12:54 -04:00
parent b5fe7b485a
commit 702783e156
1 changed files with 210 additions and 220 deletions

@ -22,27 +22,27 @@ By default all valid users get a special Spring Security GrantedAuthority that i
To map these authorities into more useful ones like **ROLE_USER** and **ROLE_ADMIN**, you need to wire in an authorities mapper, such as the one included in the client library:
```
<property name="authoritiesMapper">
<bean class="org.mitre.openid.connect.client.NamedAdminAuthoritiesMapper">
<property name="admins">
<set>
<!-- This is an example of how to set up a user as an administrator: they'll be given ROLE_ADMIN in addition to ROLE_USER -->
<bean class="org.mitre.openid.connect.client.SubjectIssuerGrantedAuthority">
<constructor-arg name="subject" value="${admin.sub}" />
<constructor-arg name="issuer" value="${admin.iss}" />
</bean>
</set>
</property>
</bean>
```xml
<property name="authoritiesMapper">
<bean class="org.mitre.openid.connect.client.NamedAdminAuthoritiesMapper">
<property name="admins">
<set>
<!-- This is an example of how to set up a user as an administrator: they'll be given ROLE_ADMIN in addition to ROLE_USER -->
<bean class="org.mitre.openid.connect.client.SubjectIssuerGrantedAuthority">
<constructor-arg name="subject" value="${admin.sub}" />
<constructor-arg name="issuer" value="${admin.iss}" />
</bean>
</set>
</property>
</bean>
</property>
```
# Filter
There is one filter class `org.mitre.openid.connect.client.OIDCAuthenticationFilter` that handles all core client (or "Relying Party") functions. It is set to listen on `/openid-connect-login` at the root of the application. The filter bean is configured like this:
```
```xml
<bean id="openIdConnectAuthenticationFilter" class="org.mitre.openid.connect.client.OIDCAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="issuerService">
@ -71,22 +71,11 @@ It is configurable for use in different modes through the use of different prope
* `authRequestOptionsService`: Provides a set of optional parameter values to be sent to the authorization endpoint
* `authRequestUrlBuilder`: Crafts the URL used to redirect the user to the OpenID Connect server
### Validator
To validate ID token signatures, the client will need access to a validator for each issuer's key set. This service bean will automatically fetch the keys and set up a validator:
```
<bean id="validatorCache" class="org.mitre.jwt.signer.service.impl.JWKSetCacheService" />
```
Depending on how the component scan is set up in the project, the validator may need to get set up as a property on the filter:
```
<property name="validationServices" ref="validatorCache" />
```
## Issuer Service
This service tells the client which `issuer`, or root server URL, to talk to for a login request.
### Static Issuer Service
Always returns the same issuer, very useful for tightly-coupled deployments.
@ -101,7 +90,7 @@ Always returns the same issuer, very useful for tightly-coupled deployments.
Allows an issuer to be passed in following the format of the OpenID Connect [third party client login initiation protocol](http://openid.net/specs/openid-connect-standard-1_0.html#client_Initiate_login). If the issuer is not passed in the `iss` parameter, it will redirect the user to an [Account Chooser](https://github.com/mitreid-connect/account-chooser) URL and listen for the callback.
```
```xml
<bean class="org.mitre.openid.connect.client.service.impl.ThirdPartyIssuerService">
<property name="accountChooserUrl" value="http://login.example.net/account-chooser/" />
</bean>
@ -110,31 +99,31 @@ This service supports setting of a `whitelist` or a `blacklist` property. If the
The whitelist is a set of strings:
```
<property name="whitelist">
<set>
<value>http://good-idp.com/</value>
<value>http://other-idp.com/</value>
</set>
</property>
```xml
<property name="whitelist">
<set>
<value>http://good-idp.com/</value>
<value>http://other-idp.com/</value>
</set>
</property>
```
The blacklist is a set of a strings:
```
<property name="blacklist">
<set>
<value>http://bad-idp.com/</value>
<value>http://evil-idp.com/</value>
</set>
</property>
```xml
<property name="blacklist">
<set>
<value>http://bad-idp.com/</value>
<value>http://evil-idp.com/</value>
</set>
</property>
```
### Webfinger Discovery Issuer Service
Takes in input from a user form and does discovery based on the Webfinger protocol. The filter will redirect the user to a login page (to be supplied by the client application) if an identifier is not returned as a result of this discovery.
```
```xml
<bean class="org.mitre.openid.connect.client.service.impl.WebfingerIssuerService">
<property name="loginPageUrl" value="login" />
</bean>
@ -144,58 +133,58 @@ This service supports setting of a `whitelist` or a `blacklist` property. If the
The whitelist is a set of strings:
```
<property name="whitelist">
<set>
<value>http://good-idp.com/</value>
<value>http://other-idp.com/</value>
</set>
</property>
```xml
<property name="whitelist">
<set>
<value>http://good-idp.com/</value>
<value>http://other-idp.com/</value>
</set>
</property>
```
The blacklist is a set of a strings:
```
<property name="blacklist">
<set>
<value>http://bad-idp.com/</value>
<value>http://evil-idp.com/</value>
</set>
</property>
```xml
<property name="blacklist">
<set>
<value>http://bad-idp.com/</value>
<value>http://evil-idp.com/</value>
</set>
</property>
```
## Server Configuration
The client must know things about the server such as its authorization endpoint URL and token endpoint URL. Since these will vary from issuer to issuer, the server configuration objects are indexed by issuer URL.
In addition to the root `issuer` URL that uniquely identifies a server, a client must know things about the server such as its authorization endpoint URL and token endpoint URL. Since these will vary from issuer to issuer, the server configuration objects are indexed by issuer URL.
### Static Server Configuration
Provides server information such as authorization endpoint url, issuer, and other parameters for each configured issuer configured as in-memory objects inside a map.
```
<bean class="org.mitre.openid.connect.client.service.impl.StaticServerConfigurationService">
<property name="servers">
<map>
<entry key="${idp.url}">
<bean class="org.mitre.openid.connect.config.ServerConfiguration">
<property name="issuer" value="${idp.url}" />
<property name="authorizationEndpointUri" value="${idp.url}authorize" />
<property name="tokenEndpointUri" value="${idp.url}token" />
<property name="userInfoUri" value="${idp.url}userinfo" />
<property name="jwksUri" value="${idp.url}jwk" />
</bean>
</entry>
</map>
</property>
</bean>
```xml
<bean class="org.mitre.openid.connect.client.service.impl.StaticServerConfigurationService">
<property name="servers">
<map>
<entry key="${idp.url}">
<bean class="org.mitre.openid.connect.config.ServerConfiguration">
<property name="issuer" value="${idp.url}" />
<property name="authorizationEndpointUri" value="${idp.url}authorize" />
<property name="tokenEndpointUri" value="${idp.url}token" />
<property name="userInfoUri" value="${idp.url}userinfo" />
<property name="jwksUri" value="${idp.url}jwk" />
</bean>
</entry>
</map>
</property>
</bean>
```
### Dynamically Discovered Server Configuration
Dynamically discovers server information for an issuer based on the [OpenID Connect Discovery protocol](http://openid.net/specs/openid-connect-discovery-1_0.html).
```
```xml
<bean class="org.mitre.openid.connect.client.service.impl.DynamicServerConfigurationService" />
```
@ -205,22 +194,22 @@ Server information is stored in an in-memory cache after discovery.
Combines a static configuration service with a dynamically discovered one in one bean. Checks the static configuration first, then performs dynamic discovery. The `servers` property passes through to the static configuration service.
```
<bean class="org.mitre.openid.connect.client.service.impl.HybridServerConfigurationService">
<property name="servers">
<map>
<entry key="${idp.url}">
<bean class="org.mitre.openid.connect.config.ServerConfiguration">
<property name="issuer" value="${idp.url}" />
<property name="authorizationEndpointUri" value="${idp.url}authorize" />
<property name="tokenEndpointUri" value="${idp.url}token" />
<property name="userInfoUri" value="${idp.url}userinfo" />
<property name="jwksUri" value="${idp.url}jwk" />
</bean>
</entry>
</map>
</property>
</bean>
```xml
<bean class="org.mitre.openid.connect.client.service.impl.HybridServerConfigurationService">
<property name="servers">
<map>
<entry key="${idp.url}">
<bean class="org.mitre.openid.connect.config.ServerConfiguration">
<property name="issuer" value="${idp.url}" />
<property name="authorizationEndpointUri" value="${idp.url}authorize" />
<property name="tokenEndpointUri" value="${idp.url}token" />
<property name="userInfoUri" value="${idp.url}userinfo" />
<property name="jwksUri" value="${idp.url}jwk" />
</bean>
</entry>
</map>
</property>
</bean>
```
## Client Configuration
@ -231,33 +220,33 @@ The client must know certain things like its `client_id` and `client_secret` in
Provides information for a pre-registered client to connect to a server.
```
<bean class="org.mitre.openid.connect.client.service.impl.StaticClientConfigurationService">
<property name="clients">
<map>
<entry key="${idp.url}">
<bean class="org.mitre.oauth2.model.RegisteredClient">
<property name="clientId" value="client" />
<property name="clientSecret" value="secret" />
<property name="scope">
<set value-type="java.lang.String">
<value>openid</value>
<value>email</value>
<value>address</value>
<value>profile</value>
<value>phone</value>
</set>
</property>
<property name="tokenEndpointAuthMethod" value="SECRET_BASIC" />
<property name="redirectUris">
<set>
<value>http://localhost:8080/simple-web-app/openid_connect_login</value>
</set>
</property>
</bean>
</entry>
</map>
</property>
```xml
<bean class="org.mitre.openid.connect.client.service.impl.StaticClientConfigurationService">
<property name="clients">
<map>
<entry key="${idp.url}">
<bean class="org.mitre.oauth2.model.RegisteredClient">
<property name="clientId" value="client" />
<property name="clientSecret" value="secret" />
<property name="scope">
<set value-type="java.lang.String">
<value>openid</value>
<value>email</value>
<value>address</value>
<value>profile</value>
<value>phone</value>
</set>
</property>
<property name="tokenEndpointAuthMethod" value="SECRET_BASIC" />
<property name="redirectUris">
<set>
<value>http://localhost:8080/simple-web-app/openid_connect_login</value>
</set>
</property>
</bean>
</entry>
</map>
</property>
</bean>
```
@ -265,38 +254,38 @@ Provides information for a pre-registered client to connect to a server.
Dynamically registers the client for each issuer based on the template of client information.
```
<bean class="org.mitre.openid.connect.client.service.impl.DynamicRegistrationClientConfigurationService">
<property name="template">
<bean class="org.mitre.oauth2.model.RegisteredClient">
<property name="clientName" value="Simple Web App" />
<property name="scope">
<set value-type="java.lang.String">
<value>openid</value>
<value>email</value>
<value>address</value>
<value>profile</value>
<value>phone</value>
</set>
</property>
<property name="tokenEndpointAuthMethod" value="SECRET_BASIC" />
<property name="redirectUris">
<set>
<value>http://localhost:8080/simple-web-app/openid_connect_login</value>
</set>
</property>
</bean>
</property>
</bean>
```xml
<bean class="org.mitre.openid.connect.client.service.impl.DynamicRegistrationClientConfigurationService">
<property name="template">
<bean class="org.mitre.oauth2.model.RegisteredClient">
<property name="clientName" value="Simple Web App" />
<property name="scope">
<set value-type="java.lang.String">
<value>openid</value>
<value>email</value>
<value>address</value>
<value>profile</value>
<value>phone</value>
</set>
</property>
<property name="tokenEndpointAuthMethod" value="SECRET_BASIC" />
<property name="redirectUris">
<set>
<value>http://localhost:8080/simple-web-app/openid_connect_login</value>
</set>
</property>
</bean>
</property>
</bean>
```
All properties set in the template object are passed in to the dynamic registration endpoint's input and the dynamically registered client information is held in an in-memory cache.
All properties set in the template object are passed in to the dynamic registration endpoint's input and the dynamically registered client information is held (by default) in an in-memory cache.
#### Registered Client Service
This service has a `registeredClientService` property which optionally allows for a service to be configured to save a client's registration information. If the registration information is not saved somewhere, then a client application will re-register itself with the server every time it starts. By default, the service is configured with an `InMemoryRegisteredClientService` which, as the name suggests, does not use persistent storage and will therefore forget about existing registrations every time the client is restarted. The library also contains a `JsonFileRegisteredClientService` which saves the registered client's registration_client_uri and registration_access_token out to disk in a plaintext (non-encrypted) JSON file. This file contains sensitive information and it must be readable and writeable by whatever process is running the client application, but it should not be readable by other untrusted applications.
The dynamic client registration service has a `registeredClientService` property which optionally allows for a service to be configured to save a client's registration information. If the registration information is not saved somewhere, then a client application will re-register itself with the server every time it starts. By default, the service is configured with an `InMemoryRegisteredClientService` which, as the name suggests, does not use persistent storage and will therefore forget about existing registrations every time the client is restarted. The library also contains a `JsonFileRegisteredClientService` which saves the registered client's registration_client_uri and registration_access_token out to disk in a plaintext (non-encrypted) JSON file. This file contains sensitive information and it must be readable and writeable by whatever process is running the client application, but it should not be readable by other untrusted applications.
```
```xml
<property name="registeredClientService">
<bean class="org.mitre.openid.connect.client.service.impl.JsonFileRegisteredClientService">
<constructor-arg name="filename" value="/tmp/swa-clients.json" />
@ -310,58 +299,58 @@ It would be greatly preferable for a client to have its own implementation of th
Combines a static client configuration service with a dynamically registered one. Checks the static configuration first, and if that fails, invokes the dynamic registration process. The `clients` property passes through to the static service and the `template` and `registeredClientService` properties pass through to the dynamic service underneath.
```
<bean class="org.mitre.openid.connect.client.service.impl.HybridClientConfigurationService">
<property name="clients">
<map>
<entry key="${idp.url}">
<bean class="org.mitre.oauth2.model.RegisteredClient">
<property name="clientId" value="client" />
<property name="clientSecret" value="secret" />
<property name="scope">
<set value-type="java.lang.String">
<value>openid</value>
<value>email</value>
<value>address</value>
<value>profile</value>
<value>phone</value>
</set>
</property>
<property name="tokenEndpointAuthMethod" value="SECRET_BASIC" />
<property name="redirectUris">
<set>
<value>http://localhost:8080/simple-web-app/openid_connect_login</value>
</set>
</property>
</bean>
</entry>
</map>
</property>
<property name="template">
<bean class="org.mitre.oauth2.model.RegisteredClient">
<property name="clientName" value="Simple Web App" />
<property name="scope">
<set value-type="java.lang.String">
<value>openid</value>
<value>email</value>
<value>address</value>
<value>profile</value>
<value>phone</value>
</set>
</property>
<property name="tokenEndpointAuthMethod" value="SECRET_BASIC" />
<property name="redirectUris">
<set>
<value>http://localhost:8080/simple-web-app/openid_connect_login</value>
</set>
</property>
</bean>
</property>
<property name="registeredClientService">
<bean class="org.mitre.openid.connect.client.service.impl.JsonFileRegisteredClientService">
<constructor-arg name="filename" value="/tmp/swa-clients.json" />
</bean>
</property>
```xml
<bean class="org.mitre.openid.connect.client.service.impl.HybridClientConfigurationService">
<property name="clients">
<map>
<entry key="${idp.url}">
<bean class="org.mitre.oauth2.model.RegisteredClient">
<property name="clientId" value="client" />
<property name="clientSecret" value="secret" />
<property name="scope">
<set value-type="java.lang.String">
<value>openid</value>
<value>email</value>
<value>address</value>
<value>profile</value>
<value>phone</value>
</set>
</property>
<property name="tokenEndpointAuthMethod" value="SECRET_BASIC" />
<property name="redirectUris">
<set>
<value>http://localhost:8080/simple-web-app/openid_connect_login</value>
</set>
</property>
</bean>
</entry>
</map>
</property>
<property name="template">
<bean class="org.mitre.oauth2.model.RegisteredClient">
<property name="clientName" value="Simple Web App" />
<property name="scope">
<set value-type="java.lang.String">
<value>openid</value>
<value>email</value>
<value>address</value>
<value>profile</value>
<value>phone</value>
</set>
</property>
<property name="tokenEndpointAuthMethod" value="SECRET_BASIC" />
<property name="redirectUris">
<set>
<value>http://localhost:8080/simple-web-app/openid_connect_login</value>
</set>
</property>
</bean>
</property>
<property name="registeredClientService">
<bean class="org.mitre.openid.connect.client.service.impl.JsonFileRegisteredClientService">
<constructor-arg name="filename" value="/tmp/swa-clients.json" />
</bean>
</property>
</bean>
```
@ -373,7 +362,7 @@ This optional service returns a `Map<String, String>` of parameters and values t
This service will return the same Map of options regardless of the context of the client, server, or request. It is configured by passing in a map of options and their values:
```
```xml
<bean class="org.mitre.openid.connect.client.service.impl.StaticAuthRequestOptionsService">
<property name="options">
<map>
@ -387,12 +376,13 @@ This service will return the same Map of options regardless of the context of th
If no options service is configured, a static authorization request options service with an empty map is provided automatically.
## Authorization Request URL Builder
In order to direct the user to the authorization endpoint of the IdP, the client filter must create a URL to send to the user's browser. This is handled by the Authorization Request URL Builder service.
### Plain Authorization Request
Builds the URL using normal HTTP parameters.
```
```xml
<bean class="org.mitre.openid.connect.client.service.impl.PlainAuthRequestUrlBuilder" />
```
@ -400,48 +390,48 @@ Builds the URL using normal HTTP parameters.
Builds the URL using a signed Request Object.
```
```xml
<bean class="org.mitre.openid.connect.client.service.impl.SignedAuthRequestUrlBuilder">
<property name="signingAndValidationService" ref="defaultsignerService" />
</bean>
```
This also requires configuration (and generation) of a [json web key set](wiki/Keys) and several support components such as a signing and validation service and a keystore:
This also requires configuration (and generation) of a [json web key set](wiki/Key-generation) and several support components such as a signing and validation service and a keystore:
```
<bean id="defaultsignerService" class="org.mitre.jwt.signer.service.impl.DefaultJwtSigningAndValidationService">
<constructor-arg name="keyStore">
<bean id="defaultKeyStore" class="org.mitre.jose.keystore.JWKSetKeyStore">
<property name="location" value="classpath:keystore.jwks" />
</bean>
</constructor-arg>
<property name="defaultSignerKeyId" value="rsa1" />
<property name="defaultSigningAlgorithmName" value="RS256" />
</bean>
```xml
<bean id="defaultsignerService" class="org.mitre.jwt.signer.service.impl.DefaultJwtSigningAndValidationService">
<constructor-arg name="keyStore">
<bean id="defaultKeyStore" class="org.mitre.jose.keystore.JWKSetKeyStore">
<property name="location" value="classpath:keystore.jwks" />
</bean>
</constructor-arg>
<property name="defaultSignerKeyId" value="rsa1" />
<property name="defaultSigningAlgorithmName" value="RS256" />
</bean>
```
Furthermore, the client must be configured to publish its public key at a URL that the server can fetch in order to validate the request object's signature. The following bean will publish whatever keys are configured in the signing and validation service that's used in the auth request builder:
```
<bean id="clientKeyPublisher" class="org.mitre.openid.connect.client.keypublisher.ClientKeyPublisher">
<property name="jwkPublishUrl" value="jwk" />
<property name="signingAndValidationService" ref="defaultsignerService" />
</bean>
```xml
<bean id="clientKeyPublisher" class="org.mitre.openid.connect.client.keypublisher.ClientKeyPublisher">
<property name="jwkPublishUrl" value="jwk" />
<property name="signingAndValidationService" ref="defaultsignerService" />
</bean>
```
### Encrypted Authorization Request
Builds the URL using an encrypted Request Object.
```
```xml
<bean class="org.mitre.openid.connect.client.service.impl.EncryptedAuthRequestUrlBuilder">
<property name="encrypterService" ref="validatorCache" />
<property name="alg">
<property name="alg">
<util:constant static-field="com.nimbusds.jose.JWEAlgorithm.RSA1_5"/>
</property>
<property name="enc">
</property>
<property name="enc">
<util:constant static-field="com.nimbusds.jose.EncryptionMethod.A128GCM"/>
</property>
</property>
</bean>
```