slight sequence diagrams tweaks, mods to account-chooser and openid-connect-client
parent
b06640c921
commit
6f43040587
Binary file not shown.
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Binary file not shown.
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
@ -5,11 +5,11 @@ A Successful Client and Account Chooser Interaction
|
||||||
|
|
||||||
Client->End-User Browser: HTTP-Redirect\n to Account\n Chooser URL\nwith redirect_uri,\n and client_id\n parameters
|
Client->End-User Browser: HTTP-Redirect\n to Account\n Chooser URL\nwith redirect_uri,\n and client_id\n parameters
|
||||||
activate End-User Browser
|
activate End-User Browser
|
||||||
End-User Browser-->Account Chooser:HTTP Get/Put\n Request containing\n redirect_uri\n and client_id
|
End-User Browser->Account Chooser:HTTP Get/Put\n Request containing\n redirect_uri\n and client_id
|
||||||
note right of "Account Chooser": Client Id\n is verified as\n supported, and the\n End-User selects\n an Account
|
note right of "Account Chooser": Client Id\n is verified as\n supported, and the\n End-User selects\n an Account
|
||||||
deactivate End-User Browser
|
deactivate End-User Browser
|
||||||
activate Account Chooser
|
activate Account Chooser
|
||||||
Account Chooser-->End-User Browser:HTTP-Redirect to \nAccount Chooser URL\n with issuer parameters
|
Account Chooser->End-User Browser:HTTP-Redirect to \nAccount Chooser URL\n with issuer parameters
|
||||||
activate End-User Browser
|
activate End-User Browser
|
||||||
deactivate Account Chooser
|
deactivate Account Chooser
|
||||||
End-User Browser->Client: HTTP Get\n Request containing the\n issuer parameter
|
End-User Browser->Client: HTTP Get\n Request containing the\n issuer parameter
|
||||||
|
@ -21,11 +21,11 @@ The Client ID is not Supported by the Account Chooser Application
|
||||||
|
|
||||||
Client->End-User Browser: HTTP-Redirect to\n Account Chooser URL\n w/ redirect_uri,\n and client_id parameters
|
Client->End-User Browser: HTTP-Redirect to\n Account Chooser URL\n w/ redirect_uri,\n and client_id parameters
|
||||||
activate End-User Browser
|
activate End-User Browser
|
||||||
End-User Browser-->Account Chooser:HTTP Get/Put\n Request containing\n redirect_uri and client_id
|
End-User Browser->Account Chooser:HTTP Get/Put\n Request containing\n redirect_uri and client_id
|
||||||
note right of "Account Chooser": Client Id is\nnot supported.\nSo, an error must\nbe returned.
|
note right of "Account Chooser": Client Id is\nnot supported.\nSo, an error must\nbe returned.
|
||||||
activate Account Chooser
|
activate Account Chooser
|
||||||
deactivate End-User Browser
|
deactivate End-User Browser
|
||||||
Account Chooser-->End-User Browser:Returns an\nHTTP Response\ncontaining an\nerror message.
|
Account Chooser->End-User Browser:Returns an\nHTTP Response\ncontaining an\nerror message.
|
||||||
deactivate Account Chooser
|
deactivate Account Chooser
|
||||||
note right of "End-User Browser":The End-User is presented\nan error message\nthus ending the interaction.\n\nOptionally, the message\nMAY contain a HTML link\nto return the End-User\nback to the Client with\nan error and error description\nadded to the query component\nof the redirect_uri.
|
note right of "End-User Browser":The End-User is presented\nan error message\nthus ending the interaction.\n\nOptionally, the message\nMAY contain a HTML link\nto return the End-User\nback to the Client with\nan error and error description\nadded to the query component\nof the redirect_uri.
|
||||||
activate End-User Browser
|
activate End-User Browser
|
||||||
|
@ -38,11 +38,11 @@ End-User Cancels Account Selection
|
||||||
|
|
||||||
Client->End-User Browser: HTTP-Redirect to\n Account Chooser URL\nwith redirect_uri,\nand client_id parameters
|
Client->End-User Browser: HTTP-Redirect to\n Account Chooser URL\nwith redirect_uri,\nand client_id parameters
|
||||||
activate End-User Browser
|
activate End-User Browser
|
||||||
End-User Browser-->Account Chooser:HTTP Get/Put\n Request containing\nredirect_uri and client_id
|
End-User Browser->Account Chooser:HTTP Get/Put\n Request containing\nredirect_uri and client_id
|
||||||
note right of "Account Chooser": End-User refuses\nto select an\naccount via\ncancelling.
|
note right of "Account Chooser": End-User refuses\nto select an\naccount via\ncancelling.
|
||||||
deactivate End-User Browser
|
deactivate End-User Browser
|
||||||
activate Account Chooser
|
activate Account Chooser
|
||||||
Account Chooser-->End-User Browser:HTTP-Redirect\n to Account Chooser\n URL with error,\nand error_description\nparameters
|
Account Chooser->End-User Browser:HTTP-Redirect\n to Account Chooser\n URL with error,\nand error_description\nparameters
|
||||||
activate End-User Browser
|
activate End-User Browser
|
||||||
deactivate Account Chooser
|
deactivate Account Chooser
|
||||||
End-User Browser->Client: HTTP Get Request\ncontaining the error,\nand error_description\nparameter
|
End-User Browser->Client: HTTP Get Request\ncontaining the error,\nand error_description\nparameter
|
||||||
|
|
|
@ -38,9 +38,9 @@
|
||||||
<bean name="AccountChooserConfig" class="org.mitre.account_chooser.AccountChooserConfig">
|
<bean name="AccountChooserConfig" class="org.mitre.account_chooser.AccountChooserConfig">
|
||||||
<property name="issuers">
|
<property name="issuers">
|
||||||
<map>
|
<map>
|
||||||
<entry key="http://sever.example.com:8080/openid-connect-server">
|
<entry key="http://idsandbox.vislab.mitre.org/openid-connect-server">
|
||||||
<bean class="org.mitre.account_chooser.OIDCServer">
|
<bean class="org.mitre.account_chooser.OIDCServer">
|
||||||
<property name="name" value="Example Server" />
|
<property name="name" value="idsandbox openid-connect-server" />
|
||||||
</bean>
|
</bean>
|
||||||
</entry>
|
</entry>
|
||||||
</map>
|
</map>
|
||||||
|
|
|
@ -26,7 +26,9 @@ import java.security.PrivateKey;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -35,6 +37,7 @@ import java.util.Map;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletRequestWrapper;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
@ -70,6 +73,63 @@ import com.google.gson.JsonParser;
|
||||||
public class AbstractOIDCAuthenticationFilter extends
|
public class AbstractOIDCAuthenticationFilter extends
|
||||||
AbstractAuthenticationProcessingFilter {
|
AbstractAuthenticationProcessingFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to remove parameters from a Request before passing it down the chain...
|
||||||
|
*
|
||||||
|
* @author nemonik
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class SanatizedRequest extends HttpServletRequestWrapper {
|
||||||
|
|
||||||
|
private List<String> paramsToBeSanatized;
|
||||||
|
|
||||||
|
public SanatizedRequest(HttpServletRequest request,
|
||||||
|
String[] paramsToBeSanatized) {
|
||||||
|
super(request);
|
||||||
|
|
||||||
|
this.paramsToBeSanatized = Arrays.asList(paramsToBeSanatized);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParameter(String name) {
|
||||||
|
if (paramsToBeSanatized.contains(name)) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return super.getParameter(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String[]> getParameterMap() {
|
||||||
|
Map<String, String[]> params = super.getParameterMap();
|
||||||
|
|
||||||
|
for (String paramToBeSanatized : paramsToBeSanatized) {
|
||||||
|
params.remove(paramToBeSanatized);
|
||||||
|
}
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Enumeration<String> getParameterNames() {
|
||||||
|
|
||||||
|
ArrayList<String> paramNames = Collections.list(super
|
||||||
|
.getParameterNames());
|
||||||
|
|
||||||
|
for (String paramToBeSanatized : paramsToBeSanatized) {
|
||||||
|
paramNames.remove(paramToBeSanatized);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.enumeration(paramNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getParameterValues(String name) {
|
||||||
|
|
||||||
|
if (paramsToBeSanatized.contains(name)) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return super.getParameterValues(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected final static int HTTP_SOCKET_TIMEOUT = 30000;
|
protected final static int HTTP_SOCKET_TIMEOUT = 30000;
|
||||||
protected final static String SCOPE = "openid";
|
protected final static String SCOPE = "openid";
|
||||||
protected final static int KEY_SIZE = 1024;
|
protected final static int KEY_SIZE = 1024;
|
||||||
|
@ -296,29 +356,34 @@ public class AbstractOIDCAuthenticationFilter extends
|
||||||
* javax.servlet.http.HttpServletResponse)
|
* javax.servlet.http.HttpServletResponse)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Authentication attemptAuthentication(HttpServletRequest arg0,
|
public Authentication attemptAuthentication(HttpServletRequest request,
|
||||||
HttpServletResponse arg1) throws AuthenticationException,
|
HttpServletResponse response) throws AuthenticationException,
|
||||||
IOException, ServletException {
|
IOException, ServletException {
|
||||||
|
|
||||||
|
logger.debug("Request: " + request.getRequestURI() + (StringUtils.isNotBlank(request.getQueryString()) ? "?"
|
||||||
|
+ request.getQueryString() : "") );
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the authorization grant response
|
* Handles the authorization grant response
|
||||||
*
|
*
|
||||||
|
* @param authorizationGrant
|
||||||
|
* The Authorization grant code
|
||||||
* @param request
|
* @param request
|
||||||
* The request from which to extract parameters and perform the
|
* The request from which to extract parameters and perform the
|
||||||
* authentication
|
* authentication
|
||||||
* @return The authenticated user token, or null if authentication is
|
* @return The authenticated user token, or null if authentication is
|
||||||
* incomplete.
|
* incomplete.
|
||||||
|
* @throws UnsupportedEncodingException
|
||||||
*/
|
*/
|
||||||
protected Authentication handleAuthorizationGrantResponse(
|
protected Authentication handleAuthorizationGrantResponse(
|
||||||
HttpServletRequest request, OIDCServerConfiguration serverConfig) {
|
String authorizationGrant, HttpServletRequest request,
|
||||||
|
OIDCServerConfiguration serverConfig) {
|
||||||
|
|
||||||
final boolean debug = logger.isDebugEnabled();
|
final boolean debug = logger.isDebugEnabled();
|
||||||
|
|
||||||
String authorizationGrant = request.getParameter("code");
|
|
||||||
|
|
||||||
// Handle Token Endpoint interaction
|
// Handle Token Endpoint interaction
|
||||||
HttpClient httpClient = new DefaultHttpClient();
|
HttpClient httpClient = new DefaultHttpClient();
|
||||||
|
|
||||||
|
@ -329,11 +394,11 @@ public class AbstractOIDCAuthenticationFilter extends
|
||||||
// TODO: basic auth is untested (it wasn't working last I
|
// TODO: basic auth is untested (it wasn't working last I
|
||||||
// tested)
|
// tested)
|
||||||
// UsernamePasswordCredentials credentials = new
|
// UsernamePasswordCredentials credentials = new
|
||||||
// UsernamePasswordCredentials(
|
// UsernamePasswordCredentials(serverConfig.getClientId(),
|
||||||
// clientId, clientSecret);
|
// serverConfig.getClientSecret());
|
||||||
// ((DefaultHttpClient) httpClient).getCredentialsProvider()
|
// ((DefaultHttpClient)
|
||||||
// .setCredentials(AuthScope.ANY, credentials);
|
// httpClient).getCredentialsProvider().setCredentials(AuthScope.ANY,
|
||||||
//
|
// credentials);
|
||||||
|
|
||||||
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(
|
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(
|
||||||
httpClient);
|
httpClient);
|
||||||
|
@ -344,7 +409,7 @@ public class AbstractOIDCAuthenticationFilter extends
|
||||||
form.add("grant_type", "authorization_code");
|
form.add("grant_type", "authorization_code");
|
||||||
form.add("code", authorizationGrant);
|
form.add("code", authorizationGrant);
|
||||||
form.add("redirect_uri", AbstractOIDCAuthenticationFilter
|
form.add("redirect_uri", AbstractOIDCAuthenticationFilter
|
||||||
.buildRedirectURI(request, new String[] { "code" }));
|
.buildRedirectURI(request, null));
|
||||||
|
|
||||||
// pass clientId and clientSecret in post of request
|
// pass clientId and clientSecret in post of request
|
||||||
form.add("client_id", serverConfig.getClientId());
|
form.add("client_id", serverConfig.getClientId());
|
||||||
|
@ -589,8 +654,13 @@ public class AbstractOIDCAuthenticationFilter extends
|
||||||
|
|
||||||
// TODO: display, prompt, request, request_uri
|
// TODO: display, prompt, request, request_uri
|
||||||
|
|
||||||
response.sendRedirect(AbstractOIDCAuthenticationFilter.buildURL(
|
String authRequest = AbstractOIDCAuthenticationFilter
|
||||||
serverConfiguration.getAuthorizationEndpointURI(), urlVariables));
|
.buildURL(serverConfiguration.getAuthorizationEndpointURI(),
|
||||||
|
urlVariables);
|
||||||
|
|
||||||
|
logger.debug("Auth Request: " + authRequest);
|
||||||
|
|
||||||
|
response.sendRedirect(authRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -95,9 +95,11 @@ public class OIDCAuthenticationFilter extends AbstractOIDCAuthenticationFilter {
|
||||||
|
|
||||||
handleError(request, response);
|
handleError(request, response);
|
||||||
|
|
||||||
} else if (request.getParameter("code") != null) {
|
} else if (StringUtils.isNotBlank(request.getParameter("code"))) {
|
||||||
|
|
||||||
return handleAuthorizationGrantResponse(request, oidcServerConfig);
|
return handleAuthorizationGrantResponse(
|
||||||
|
request.getParameter("code"), new SanatizedRequest(request,
|
||||||
|
new String[] { "code" }), oidcServerConfig);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
|
@ -105,22 +105,24 @@ public class OIDCAuthenticationUsingChooserFilter extends
|
||||||
} else if (request.getParameter("code") != null) {
|
} else if (request.getParameter("code") != null) {
|
||||||
|
|
||||||
// Which OIDC configuration?
|
// Which OIDC configuration?
|
||||||
Cookie oidcAliasCookie = WebUtils.getCookie(request,
|
Cookie issuerCookie = WebUtils.getCookie(request,
|
||||||
ISSUER_COOKIE_NAME);
|
ISSUER_COOKIE_NAME);
|
||||||
|
|
||||||
return handleAuthorizationGrantResponse(request,
|
return handleAuthorizationGrantResponse(
|
||||||
oidcServerConfigs.get(oidcAliasCookie.getValue()));
|
request.getParameter("code"), new SanatizedRequest(request,
|
||||||
|
new String[] { "code" }),
|
||||||
|
oidcServerConfigs.get(issuerCookie.getValue()));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
String issuerId = request.getParameter("issuer");
|
String issuer = request.getParameter("issuer");
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(issuerId)) {
|
if (StringUtils.isNotBlank(issuer)) {
|
||||||
|
|
||||||
// Account Chooser UI provided and Issuer Identifier
|
// Account Chooser UI provided and Issuer Identifier
|
||||||
|
|
||||||
OIDCServerConfiguration oidcServerConfig = oidcServerConfigs
|
OIDCServerConfiguration oidcServerConfig = oidcServerConfigs
|
||||||
.get(issuerId);
|
.get(issuer);
|
||||||
|
|
||||||
if (oidcServerConfig != null) {
|
if (oidcServerConfig != null) {
|
||||||
|
|
||||||
|
@ -128,10 +130,11 @@ public class OIDCAuthenticationUsingChooserFilter extends
|
||||||
// Identifier
|
// Identifier
|
||||||
|
|
||||||
Cookie issuerCookie = new Cookie(ISSUER_COOKIE_NAME,
|
Cookie issuerCookie = new Cookie(ISSUER_COOKIE_NAME,
|
||||||
issuerId);
|
issuer);
|
||||||
response.addCookie(issuerCookie);
|
response.addCookie(issuerCookie);
|
||||||
|
|
||||||
handleAuthorizationRequest(request, response,
|
handleAuthorizationRequest(new SanatizedRequest(request,
|
||||||
|
new String[] { "issuer" }), response,
|
||||||
oidcServerConfig);
|
oidcServerConfig);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -140,8 +143,8 @@ public class OIDCAuthenticationUsingChooserFilter extends
|
||||||
// Identifier
|
// Identifier
|
||||||
|
|
||||||
throw new AuthenticationServiceException(
|
throw new AuthenticationServiceException(
|
||||||
"Security Filter not configured for OIDC Alias: "
|
"Security Filter not configured for issuer: "
|
||||||
+ issuerId);
|
+ issuer);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -155,6 +158,8 @@ public class OIDCAuthenticationUsingChooserFilter extends
|
||||||
OIDCAuthenticationUsingChooserFilter.buildRedirectURI(
|
OIDCAuthenticationUsingChooserFilter.buildRedirectURI(
|
||||||
request, null));
|
request, null));
|
||||||
|
|
||||||
|
urlVariables.put("client_id", accountChooserClientID);
|
||||||
|
|
||||||
response.sendRedirect(OIDCAuthenticationUsingChooserFilter
|
response.sendRedirect(OIDCAuthenticationUsingChooserFilter
|
||||||
.buildURL(accountChooserURI, urlVariables));
|
.buildURL(accountChooserURI, urlVariables));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue