client documentation updates, addresses #135

pull/210/head
Justin Richer 12 years ago
parent 012bb4afd7
commit a0df7ad04b

@ -2,48 +2,34 @@
## Overview ## ## Overview ##
You are reading the documentation for the OIDC Client implemented as a Spring Security AuthenticationFilter. The client facilitates a user's authentication into the secured application to an OpenID Connect Java Spring Server following the [OpenID Connect Standard] described protocol. This project contains an OpenID Connect Client implemented as a Spring Security AuthenticationFilter. The client facilitates a user's authentication into the secured application to an OpenID Connect Java Spring Server following the OpenID Connect Standard protocol.
For an example of the Client configuration, see the [Simple Web App] project.
## Configuring ## ## Configuring ##
Configure the client by adding the following XML to your application context security making changes where necessary for your specific deployment. Configure the client by adding the following XML to your application context security making changes where necessary for your specific deployment.
Open and define an HTTP security configuration with a reference to a bean defined custom ***AuthenticationEntryPoint***: Open and define an HTTP security configuration with a reference to a custom ***AuthenticationEntryPoint***, described below:
<security:http auto-config="false" <security:http auto-config="false" use-expressions="true" disable-url-rewriting="true" entry-point-ref="authenticationEntryPoint" pattern="/**">
use-expressions="true"
disable-url-rewriting="true"
entry-point-ref="authenticationEntryPoint"
pattern="/**">
Specify the access attributes and/or filter list for a particular set of URLs needing protection: Specify the access attributes and/or filter list for a particular set of URLs needing protection:
<security:intercept-url <security:intercept-url pattern="/**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" />
pattern="/**"
access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" />
Indicate that ***OpenIdConnectAuthenticationFilter*** authentication filter should be incorporated into the security filter chain: Indicate that ***OIDCAuthenticationFilter*** authentication filter should be incorporated into the security filter chain:
<security:custom-filter <security:custom-filter before="PRE_AUTH_FILTER" ref="openIdConnectAuthenticationFilter" />
before="PRE_AUTH_FILTER
ref="openIdConnectAuthenticationFilter" />
Set up remember-me authentication referencing the yet to be defined ***UserDetailsService***:
<security:remember-me user-service-ref="myUserDetailsService"
NOTE: See the last section as how to implement your own ***UserDetailsService*** necessary to complete authentication.
Then close the HTTP security configuration: Then close the HTTP security configuration:
</security:http> </security:http>
Define a custom ***AuthenticationEntryPoint*** via a bean declaration: Define a custom ***AuthenticationEntryPoint*** to use a login URL via a bean declaration:
<bean id="authenticationEntryPoint" <bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> <property name="loginFormUrl" value="/openid_connect_login" />
<property name="loginFormUrl"
value="/openid_connect_login"/>
</bean> </bean>
NOTE: The ***loginFormUrl*** value is post-pended to the URI of the application being secured to define the ***redirect_uri***, the value passed to the OIDC Server and, if the ***OIDCAuthenticationUsingChooserFilter*** is configured, also the Account Chooser Application. NOTE: The ***loginFormUrl*** value is post-pended to the URI of the application being secured to define the ***redirect_uri***, the value passed to the OIDC Server and, if the ***OIDCAuthenticationUsingChooserFilter*** is configured, also the Account Chooser Application.
@ -54,61 +40,67 @@ Define an ***AuthenticationManager*** with a reference to a custom authenticatio
<security:authentication-provider ref="openIDConnectAuthenticationProvider" /> <security:authentication-provider ref="openIDConnectAuthenticationProvider" />
</security:authentication-manager> </security:authentication-manager>
Define the custom authentication provider referencing the your yet to be defined implementation of a ***UserDetailsService***: Define the custom authentication provider. Note that it does not take a UserDetailsService as input at this time but instead makes a call to the UserInfoEndpoint to fill in user information.
<bean id="openIdConnectAuthenticationProvider" <bean id="openIdConnectAuthenticationProvider" class="org.mitre.openid.connect.client.OIDCAuthenticationProvider" />
class='org.mitre.openid.connect.client.OIDCAuthenticationProvider">
<property name="userDetailsService" ref="myUserDetailsService"/>
</bean>
### Configuring the OIDCAuthenticationFilter ### ### Configuring the OIDCAuthenticationFilter ###
The ***OpenIdConnectAuthenticationFilter*** filter is defined with the following properties: The ***OIDCAuthenticationFilter*** filter is defined with the following properties:
* ***authenticationManager*** -- a reference to the ***AuthenticationManager***, * ***authenticationManager*** -- a reference to the ***AuthenticationManager***
* ***errorRedirectURI*** -- the URI of the Error redirect, * ***errorRedirectURI*** -- the URI of the Error redirect
* ***authorizationEndpointURI*** -- the URI of the Authorization Endpoint,
* ***tokenEndpointURI*** -- the URI of the Token Endpoint, Additionally, it contains a set of convenience methods to pass through to parameters on the ***OIDCServerConfiguration*** object that defines attributes of the server that it connects to:
* ***clientId*** -- the registered client identifier, and
* ***clientSecret*** -- the registered client secret. * ***issuer*** -- the root issuer string of this server (required)
* ***authorizationEndpointUrl*** -- the URL of the Authorization Endpoint (required)
* ***tokenEndpointUrl*** -- the URL of the Token Endpoint (required)
* ***jwkSigningUrl*** -- the URL of the JWK (public key) Endpoint for token verification
* ***clientId*** -- the registered client identifier (required)
* ***clientSecret*** -- the registered client secret
* ***userInfoUrl*** -- the URL of the User Info Endpoint
* ***scope*** -- space-separated list of scopes; the required value "openid" will always be prepended to the list given here
Configure like so: Configure like so:
<bean id="openIdConnectAuthenticationFilter" <bean id="openIdConnectAuthenticationFilter"
class="org.mitre.openid.connect.client.OpenIdConnectAuthenticationFilter"> class="org.mitre.openid.connect.client.OIDCAuthenticationFilter">
<property name="authenticationManager" <property name="authenticationManager" ref="authenticationManager" />
ref="authenticationManager" /> <property name="errorRedirectURI" value="/login.jsp?authfail=openid" />
<property name="errorRedirectURI" <property name="issuer" value="http://server.example.com:8080/openid-connect-server/" />
value="/login.jsp?authfail=openid" /> <property name="authorizationEndpointUrl" value="http://sever.example.com:8080/openid-connect-server/openidconnect/auth" />
<property name="authorizationEndpointURI" <property name="tokenEndpointUrl" value="http://sever.example.com:8080/openid-connect-server/openidconnect/token" />
value="http://sever.example.com:8080/openid-connect-server/openidconnect/auth" />
<property name="tokenEndpointURI"
value="http://sever.example.com:8080/openid-connect-server/openidconnect/token" />
<property name="clientId"
value="someClientId" />
<property name="clientSecret" value="someClientSecret" />
<property name="issuer" value="http://server.example.com:8080/openid-connect-server/" />
<property name="jwkSigningUrl" value="http://server.example.com:8080/openid-connect-server/jwk" /> <property name="jwkSigningUrl" value="http://server.example.com:8080/openid-connect-server/jwk" />
<property name="clientId" value="someClientId" />
<property name="clientSecret" value="someClientSecret" />
<property name="userInfoUrl" value="http://server.example.com:8080/open-id-connect-server/userinfo" />
<property name="scope" value="profile email address phone" />
</bean> </bean>
NOTE: Again, you will need your own implementation of a ***UserDetailsService*** specific to your deployment. See the last section of this document. ### Configuring the OIDCAuthenticationUsingChooserFilter ###
### Or Alternatively, Configuring the OIDCAuthenticationUsingChooserFilter ### For talking to multiple IdPs using an Account chooser, the ***OIDCAuthenticationUsingChooserFilter*** can be configured and used. [The Client -- Account Chooser protocol] documentation details the protocol used between the Client and an Account Chooser application.
Alternatively, the ***OIDCAuthenticationUsingChooserFilter*** can be configured and used. It was written in response to [Issue #39]. [The Client -- Account Chooser protocol] documentation details the protocol used between the Client and an Account Chooser application.
The ***OIDCAuthenticationUsingChooserFilter*** Authentication Filter has the following properties: The ***OIDCAuthenticationUsingChooserFilter*** Authentication Filter has the following properties:
* ***oidcServerConfigs*** -- a map of ***OIDCserverConfiguration***s to encapsulate the settings necesary for the client to communicate with each respective OIDC server, * ***authenticationManager*** -- a reference to the ***AuthenticationManager***,
* ***errorRedirectURI*** -- the URI of the Error redirect,
* ***accountChooserURI*** -- to denote the URI of the Account Chooser, and * ***accountChooserURI*** -- to denote the URI of the Account Chooser, and
* ***accountChooserClient*** -- to identify the Client to the Account Chooser UI application. * ***accountChooserClient*** -- to identify the Client to the Account Chooser UI application.
* ***oidcServerConfigs*** -- a map of ***OIDCserverConfiguration***s to encapsulate the settings necesary for the client to communicate with each respective OIDC server,
Each ***OIDCServerConfiguration*** entry in ***OIDCserverConfiguration*** map is keyed to the ***issuer*** returned from the Account Chooser Application and enumerates the following properties: Each ***OIDCServerConfiguration*** entry in ***OIDCserverConfiguration*** map is keyed to the ***issuer*** returned from the Account Chooser Application and enumerates the following properties:
* ***authorizationEndpointURI*** -- the URI of the Authorization Endpoint, * ***authenticationManager*** -- a reference to the ***AuthenticationManager***,
* ***tokenEndpointURI*** -- the URI of the Token Endpoint, * ***issuer*** -- the root issuer string of this server (required)
* ***clientId*** -- the registered client identifier, and * ***authorizationEndpointUrl*** -- the URL of the Authorization Endpoint (required)
* ***clientSecret*** -- the registered client secret. * ***tokenEndpointUrl*** -- the URL of the Token Endpoint (required)
* ***jwkSigningUrl*** -- the URL of the JWK (public key) Endpoint for token verification
* ***clientId*** -- the registered client identifier (required)
* ***clientSecret*** -- the registered client secret
* ***userInfoUrl*** -- the URL of the User Info Endpoint
* ***scope*** -- space-separated list of scopes; the required value "openid" will always be prepended to the list given here
Configure like so: Configure like so:
@ -116,20 +108,20 @@ Configure like so:
class="org.mitre.openid.connect.client.OIDCAuthenticationUsingChooserFilter"> class="org.mitre.openid.connect.client.OIDCAuthenticationUsingChooserFilter">
<property name="errorRedirectURI" value="/login.jsp?authfail=openid" /> <property name="errorRedirectURI" value="/login.jsp?authfail=openid" />
<property name="authenticationManager" ref="authenticationManager" /> <property name="authenticationManager" ref="authenticationManager" />
<property name="accountChooserURI" <property name="accountChooserURI" value="http://sever.example.com:8080/account-chooser" />
value="http://sever.example.com:8080/account-chooser" />
<property name="accountChooserClientID" value="FGWEUIASJK" /> <property name="accountChooserClientID" value="FGWEUIASJK" />
<property name="oidcServerConfigs"> <property name="oidcServerConfigs">
<map> <map>
<entry key="http://sever.example.com:8080/Fopenid-connect-server"> <entry key="http://sever.example.com:8080/Fopenid-connect-server">
<bean class="org.mitre.openid.connect.client.OIDCServerConfiguration"> <bean class="org.mitre.openid.connect.client.OIDCServerConfiguration">
<property name="authorizationEndpointURI" <property name="issuer" value="http://server.example.com:8080/openid-connect-server/" />
value="http://sever.example.com:8080/openid-connect-server/oauth/authorize" /> <property name="authorizationEndpointUrl" value="http://sever.example.com:8080/openid-connect-server/openidconnect/auth" />
<property name="tokenEndpointURI" <property name="tokenEndpointUrl" value="http://sever.example.com:8080/openid-connect-server/openidconnect/token" />
value="http://sever.example.com:8080/openid-connect-server/oauth/token" /> <property name="jwkSigningUrl" value="http://server.example.com:8080/openid-connect-server/jwk" />
<property name="clientId" <property name="clientId" value="someClientId" />
value="someClientId" /> <property name="clientSecret" value="someClientSecret" />
<property name="clientSecret" value="someClientSecret" /> <property name="userInfoUrl" value="http://server.example.com:8080/open-id-connect-server/userinfo" />
<property name="scope" value="profile email address phone" />
</bean> </bean>
</entry> </entry>
<entry key=". . . <entry key=". . .
@ -137,100 +129,5 @@ Configure like so:
</property> </property>
</bean> </bean>
Again, you will need your own implementation of a ***UserDetailsService***. See the next section.
## Implementing your own UserDetailsService ##
You need to implement your own ***UserDetailsService*** to complete the authentication.
An example ***UserDetailsService*** for the Rave Portal follows:
package org.mitre.mpn.service.impl;
import org.apache.rave.portal.model.NewUser;
import org.apache.rave.portal.model.User;
import org.apache.rave.portal.service.NewAccountService;
import org.apache.rave.portal.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.mitre.openid.connect.client.OpenIdConnectAuthenticationToken;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service(value = "myUserDetailsService")
public class MyUserDetailsService implements UserDetailsService,
AuthenticationUserDetailsService<OpenIdConnectAuthenticationToken> {
private static final Logger log = LoggerFactory.getLogger(MpnUserDetailsService.class);
private final UserService userService;
private final NewAccountService newAccountService;
//TODO: This is temporarily hard-coded while we wait for the concept of Page Templates to be implemented in Rave
private static final String DEFAULT_LAYOUT_CODE = "columns_3";
@Autowired
public MyUserDetailsService(UserService userService, NewAccountService newAccountService) {
this.userService = userService;
this.newAccountService = newAccountService;
}
/* (non-Javadoc)
* @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
*/
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.debug("loadUserByUsername called with: {}", username);
User user = userService.getUserByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User with username '" + username + "' was not found!");
}
return user;
}
/* (non-Javadoc)
* @see org.springframework.security.core.userdetails.AuthenticationUserDetailsService#loadUserDetails(org.springframework.security.core.Authentication)
*/
public UserDetails loadUserDetails(OpenIdConnectAuthenticationToken token) throws UsernameNotFoundException {
log.debug("loadUserDetails called with: {}", token);
User user = userService.getUserByUsername(token.getUserId());
if (user == null) {
NewUser newUser = new NewUser();
newUser.setUsername(token.getUserId());
newUser.setEmail(token.getUserId() + "@example.com");
newUser.setPageLayout(DEFAULT_LAYOUT_CODE);
newUser.setPassword(UUID.randomUUID().toString());
try {
newAccountService.createNewAccount(newUser);
} catch (Exception e) {
throw new RuntimeException(e);
}
user = userService.getUserByUsername(token.getName());
}
return user;
}
}
[OpenID Connect Standard]: http://openid.net/specs/openid-connect-standard-1_0.html "OpenID Connect Standard 1.0"
[OpenID Connect Standard]: http://openid.net/specs/openid-connect-standard-1_0.html#code_flow "Authorization Code Flow, OpenID Connect Standard"
[Issuer Identifier]: http://openid.net/specs/openid-connect-messages-1_0.html#issuer_identifier "Issuer Identifier"
[Issue #39]: http://github.com/jricher/OpenID-Connect-Java-Spring-Server/issues/39 "Issue #39 -- Multiple Point Client"
[The Client -- Account Chooser protocol]: https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/blob/master/account-chooser/docs/protocol.md [The Client -- Account Chooser protocol]: https://github.com/mitreid-connect/OpenID-Connect-Java-Spring-Server/blob/master/account-chooser/docs/protocol.md
[Simple Web App]: https://github.com/mitreid-connect/simple-web-app
Loading…
Cancel
Save