added configurable support for clients to send extra parameters like display and prompt, addresses #426
parent
3360117b7b
commit
6a9650d2a7
|
@ -22,6 +22,7 @@ import java.net.URI;
|
|||
import java.security.SecureRandom;
|
||||
import java.text.ParseException;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -33,10 +34,12 @@ import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
|
|||
import org.mitre.jwt.signer.service.impl.JWKSetSigningAndValidationServiceCacheService;
|
||||
import org.mitre.oauth2.model.RegisteredClient;
|
||||
import org.mitre.openid.connect.client.model.IssuerServiceResponse;
|
||||
import org.mitre.openid.connect.client.service.AuthRequestOptionsService;
|
||||
import org.mitre.openid.connect.client.service.AuthRequestUrlBuilder;
|
||||
import org.mitre.openid.connect.client.service.ClientConfigurationService;
|
||||
import org.mitre.openid.connect.client.service.IssuerService;
|
||||
import org.mitre.openid.connect.client.service.ServerConfigurationService;
|
||||
import org.mitre.openid.connect.client.service.impl.StaticAuthRequestOptionsService;
|
||||
import org.mitre.openid.connect.config.ServerConfiguration;
|
||||
import org.mitre.openid.connect.model.OIDCAuthenticationToken;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -88,8 +91,9 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
|
|||
private ServerConfigurationService servers;
|
||||
private ClientConfigurationService clients;
|
||||
private IssuerService issuerService;
|
||||
private AuthRequestOptionsService authOptions = new StaticAuthRequestOptionsService(); // initialize with an empty set of options
|
||||
private AuthRequestUrlBuilder authRequestBuilder;
|
||||
|
||||
|
||||
protected int httpSocketTimeout = HTTP_SOCKET_TIMEOUT;
|
||||
|
||||
/**
|
||||
|
@ -201,7 +205,9 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
|
|||
// this value comes back in the auth code response
|
||||
String state = createState(session);
|
||||
|
||||
String authRequest = authRequestBuilder.buildAuthRequestUrl(serverConfig, clientConfig, redirectUri, nonce, state);
|
||||
Map<String, String> options = authOptions.getOptions(serverConfig, clientConfig, request);
|
||||
|
||||
String authRequest = authRequestBuilder.buildAuthRequestUrl(serverConfig, clientConfig, redirectUri, nonce, state, options);
|
||||
|
||||
logger.debug("Auth Request: " + authRequest);
|
||||
|
||||
|
@ -603,4 +609,18 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
|
|||
this.authRequestBuilder = authRequestBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the authOptions
|
||||
*/
|
||||
public AuthRequestOptionsService getAuthRequestOptionsService() {
|
||||
return authOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param authOptions the authOptions to set
|
||||
*/
|
||||
public void setAuthRequestOptionsService(AuthRequestOptionsService authOptions) {
|
||||
this.authOptions = authOptions;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
*
|
||||
*/
|
||||
package org.mitre.openid.connect.client.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.mitre.oauth2.model.RegisteredClient;
|
||||
import org.mitre.openid.connect.config.ServerConfiguration;
|
||||
|
||||
/**
|
||||
*
|
||||
* This service provides any extra options that need to be passed to the authentication request.
|
||||
* These options may depend on the server configuration, client configuration, or HTTP request.
|
||||
*
|
||||
* @author jricher
|
||||
*
|
||||
*/
|
||||
public interface AuthRequestOptionsService {
|
||||
|
||||
public Map<String, String> getOptions(ServerConfiguration server, RegisteredClient client, HttpServletRequest request);
|
||||
|
||||
}
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package org.mitre.openid.connect.client.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.mitre.oauth2.model.RegisteredClient;
|
||||
import org.mitre.openid.connect.config.ServerConfiguration;
|
||||
|
||||
|
@ -36,6 +38,6 @@ public interface AuthRequestUrlBuilder {
|
|||
* @param state
|
||||
* @return
|
||||
*/
|
||||
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state);
|
||||
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state, Map<String, String> options);
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
package org.mitre.openid.connect.client.service.impl;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.mitre.oauth2.model.RegisteredClient;
|
||||
|
@ -42,7 +44,7 @@ public class PlainAuthRequestUrlBuilder implements AuthRequestUrlBuilder {
|
|||
* @see org.mitre.openid.connect.client.service.AuthRequestUrlBuilder#buildAuthRequest(javax.servlet.http.HttpServletRequest, org.mitre.openid.connect.config.ServerConfiguration, org.springframework.security.oauth2.provider.ClientDetails)
|
||||
*/
|
||||
@Override
|
||||
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state) {
|
||||
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state, Map<String, String> options) {
|
||||
try {
|
||||
|
||||
URIBuilder uriBuilder = new URIBuilder(serverConfig.getAuthorizationEndpointUri());
|
||||
|
@ -57,8 +59,9 @@ public class PlainAuthRequestUrlBuilder implements AuthRequestUrlBuilder {
|
|||
uriBuilder.addParameter("state", state);
|
||||
|
||||
// Optional parameters:
|
||||
|
||||
// TODO: display, prompt
|
||||
for (Entry<String, String> option : options.entrySet()) {
|
||||
uriBuilder.addParameter(option.getKey(), option.getValue());
|
||||
}
|
||||
|
||||
return uriBuilder.build().toString();
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
package org.mitre.openid.connect.client.service.impl;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
|
||||
|
@ -45,24 +47,31 @@ public class SignedAuthRequestUrlBuilder implements AuthRequestUrlBuilder {
|
|||
* @see org.mitre.openid.connect.client.service.AuthRequestUrlBuilder#buildAuthRequestUrl(org.mitre.openid.connect.config.ServerConfiguration, org.springframework.security.oauth2.provider.ClientDetails, java.lang.String, java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state) {
|
||||
public String buildAuthRequestUrl(ServerConfiguration serverConfig, RegisteredClient clientConfig, String redirectUri, String nonce, String state, Map<String, String> options) {
|
||||
|
||||
// create our signed JWT for the request object
|
||||
JWTClaimsSet claims = new JWTClaimsSet();
|
||||
|
||||
//set parameters to JwtClaims
|
||||
claims.setCustomClaim("response_type", "code");
|
||||
claims.setCustomClaim("client_id", clientConfig.getClientId());
|
||||
claims.setCustomClaim("scope", Joiner.on(" ").join(clientConfig.getScope()));
|
||||
claims.setClaim("response_type", "code");
|
||||
claims.setClaim("client_id", clientConfig.getClientId());
|
||||
claims.setClaim("scope", Joiner.on(" ").join(clientConfig.getScope()));
|
||||
|
||||
// build our redirect URI
|
||||
claims.setCustomClaim("redirect_uri", redirectUri);
|
||||
claims.setClaim("redirect_uri", redirectUri);
|
||||
|
||||
// this comes back in the id token
|
||||
claims.setCustomClaim("nonce", nonce);
|
||||
claims.setClaim("nonce", nonce);
|
||||
|
||||
// this comes back in the auth request return
|
||||
claims.setCustomClaim("state", state);
|
||||
claims.setClaim("state", state);
|
||||
|
||||
// Optional parameters
|
||||
for (Entry<String, String> option : options.entrySet()) {
|
||||
claims.setClaim(option.getKey(), option.getValue());
|
||||
}
|
||||
|
||||
|
||||
|
||||
SignedJWT jwt = new SignedJWT(new JWSHeader(signingAndValidationService.getDefaultSigningAlgorithm()), claims);
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
*
|
||||
*/
|
||||
package org.mitre.openid.connect.client.service.impl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.mitre.oauth2.model.RegisteredClient;
|
||||
import org.mitre.openid.connect.client.service.AuthRequestOptionsService;
|
||||
import org.mitre.openid.connect.config.ServerConfiguration;
|
||||
|
||||
/**
|
||||
*
|
||||
* Always returns the same set of options.
|
||||
*
|
||||
* @author jricher
|
||||
*
|
||||
*/
|
||||
public class StaticAuthRequestOptionsService implements AuthRequestOptionsService {
|
||||
|
||||
private Map<String, String> options = new HashMap<String, String>();
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.mitre.openid.connect.client.service.AuthRequestOptionsService#getOptions(org.mitre.openid.connect.config.ServerConfiguration, org.mitre.oauth2.model.RegisteredClient, javax.servlet.http.HttpServletRequest)
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> getOptions(ServerConfiguration server, RegisteredClient client, HttpServletRequest request) {
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the options
|
||||
*/
|
||||
public Map<String, String> getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param options the options to set
|
||||
*/
|
||||
public void setOptions(Map<String, String> options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -16,6 +16,9 @@
|
|||
******************************************************************************/
|
||||
package org.mitre.openid.connect.client.service.impl;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mitre.oauth2.model.RegisteredClient;
|
||||
|
@ -23,6 +26,7 @@ import org.mitre.openid.connect.config.ServerConfiguration;
|
|||
import org.mockito.Mockito;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
|
@ -60,9 +64,12 @@ public class TestPlainAuthRequestUrlBuilder {
|
|||
"&scope=openid+profile" + // plus sign used for space per application/x-www-form-encoded standard
|
||||
"&redirect_uri=https%3A%2F%2Fclient.example.org%2F" +
|
||||
"&nonce=34fasf3ds" +
|
||||
"&state=af0ifjsldkj";
|
||||
"&state=af0ifjsldkj" +
|
||||
"&foo=bar";
|
||||
|
||||
Map<String, String> options = ImmutableMap.of("foo", "bar");
|
||||
|
||||
String actualUrl = urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "https://client.example.org/", "34fasf3ds", "af0ifjsldkj");
|
||||
String actualUrl = urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "https://client.example.org/", "34fasf3ds", "af0ifjsldkj", options);
|
||||
|
||||
assertThat(actualUrl, equalTo(expectedUrl));
|
||||
}
|
||||
|
@ -72,7 +79,9 @@ public class TestPlainAuthRequestUrlBuilder {
|
|||
|
||||
Mockito.when(serverConfig.getAuthorizationEndpointUri()).thenReturn("e=mc^2");
|
||||
|
||||
urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "example.com", "", "");
|
||||
Map<String, String> options = ImmutableMap.of("foo", "bar");
|
||||
|
||||
urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "example.com", "", "", options);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.springframework.security.authentication.AuthenticationServiceExceptio
|
|||
import org.springframework.web.util.UriComponents;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.nimbusds.jose.Algorithm;
|
||||
|
@ -63,6 +64,8 @@ public class TestSignedAuthRequestUrlBuilder {
|
|||
private String nonce = "34fasf3ds";
|
||||
private String state = "af0ifjsldkj";
|
||||
private String responseType = "code";
|
||||
private Map<String, String> options = ImmutableMap.of("foo", "bar");
|
||||
|
||||
|
||||
// RSA key properties:
|
||||
// {@link package com.nimbusds.jose.jwk#RSAKey}
|
||||
|
@ -113,7 +116,7 @@ public class TestSignedAuthRequestUrlBuilder {
|
|||
@Test
|
||||
public void buildAuthRequestUrl() {
|
||||
|
||||
String requestUri = urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, redirectUri, nonce, state);
|
||||
String requestUri = urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, redirectUri, nonce, state, options);
|
||||
|
||||
// parsing the result
|
||||
UriComponentsBuilder builder = null;
|
||||
|
@ -144,6 +147,9 @@ public class TestSignedAuthRequestUrlBuilder {
|
|||
assertEquals(redirectUri, claims.getClaim("redirect_uri"));
|
||||
assertEquals(nonce, claims.getClaim("nonce"));
|
||||
assertEquals(state, claims.getClaim("state"));
|
||||
for (String claim : options.keySet()) {
|
||||
assertEquals(options.get(claim), claims.getClaim(claim));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = AuthenticationServiceException.class)
|
||||
|
@ -151,6 +157,6 @@ public class TestSignedAuthRequestUrlBuilder {
|
|||
|
||||
Mockito.when(serverConfig.getAuthorizationEndpointUri()).thenReturn("e=mc^2");
|
||||
|
||||
urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "example.com", "", "");
|
||||
urlBuilder.buildAuthRequestUrl(serverConfig, clientConfig, "example.com", "", "", options);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue