diff --git a/account-chooser/docs/cancel.png b/account-chooser/docs/cancel.png index 98446ba51..3117848a9 100644 Binary files a/account-chooser/docs/cancel.png and b/account-chooser/docs/cancel.png differ diff --git a/account-chooser/docs/not_supported.png b/account-chooser/docs/not_supported.png index c7e70ad1e..e527e39a9 100644 Binary files a/account-chooser/docs/not_supported.png and b/account-chooser/docs/not_supported.png differ diff --git a/account-chooser/docs/protocol.pdf b/account-chooser/docs/protocol.pdf index 388a7d3a7..f65869c56 100644 Binary files a/account-chooser/docs/protocol.pdf and b/account-chooser/docs/protocol.pdf differ diff --git a/account-chooser/docs/success.png b/account-chooser/docs/success.png index fb4c1a0c0..2c3f31bd2 100644 Binary files a/account-chooser/docs/success.png and b/account-chooser/docs/success.png differ diff --git a/account-chooser/docs/webSequenceDiagram.txt b/account-chooser/docs/webSequenceDiagram.txt index 478561ccf..5f71a1243 100644 --- a/account-chooser/docs/webSequenceDiagram.txt +++ b/account-chooser/docs/webSequenceDiagram.txt @@ -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 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 deactivate End-User Browser 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 deactivate Account Chooser 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 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. activate Account Chooser 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 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 @@ -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 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. deactivate End-User Browser 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 deactivate Account Chooser End-User Browser->Client: HTTP Get Request\ncontaining the error,\nand error_description\nparameter diff --git a/account-chooser/src/main/java/org/mitre/account_chooser/AccountChooserController.java b/account-chooser/src/main/java/org/mitre/account_chooser/AccountChooserController.java index 1bab2c8e2..028b52b43 100644 --- a/account-chooser/src/main/java/org/mitre/account_chooser/AccountChooserController.java +++ b/account-chooser/src/main/java/org/mitre/account_chooser/AccountChooserController.java @@ -163,7 +163,7 @@ public class AccountChooserController { Map urlVariables = new HashMap(); urlVariables.put("issuer", issuer); - + response.sendRedirect(AccountChooserController.buildURL(redirectUri, urlVariables)); } @@ -194,8 +194,8 @@ public class AccountChooserController { Map urlVariables = new HashMap(); urlVariables.put("error", "end_user_cancelled"); urlVariables.put("error_description", - "The end-user refused to select an Account."); - + "The end-user refused to select an Account."); + response.sendRedirect(AccountChooserController.buildURL(redirectUri, urlVariables)); diff --git a/account-chooser/src/main/webapp/WEB-INF/spring-servlet.xml b/account-chooser/src/main/webapp/WEB-INF/spring-servlet.xml index 66a11ca0b..41bc413ca 100644 --- a/account-chooser/src/main/webapp/WEB-INF/spring-servlet.xml +++ b/account-chooser/src/main/webapp/WEB-INF/spring-servlet.xml @@ -38,9 +38,9 @@ - + - + diff --git a/openid-connect-client/.classpath b/openid-connect-client/.classpath index 1b28ee5d7..f5c551598 100644 --- a/openid-connect-client/.classpath +++ b/openid-connect-client/.classpath @@ -1,11 +1,11 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/openid-connect-client/.project b/openid-connect-client/.project index 218cc5642..2b767d57b 100644 --- a/openid-connect-client/.project +++ b/openid-connect-client/.project @@ -1,36 +1,36 @@ - - - openid-connect-client - - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - org.eclipse.wst.common.project.facet.core.nature - - + + + openid-connect-client + + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + + diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AbstractOIDCAuthenticationFilter.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AbstractOIDCAuthenticationFilter.java index bc961161d..49c775859 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AbstractOIDCAuthenticationFilter.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/AbstractOIDCAuthenticationFilter.java @@ -26,7 +26,9 @@ import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Signature; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.List; @@ -35,6 +37,7 @@ import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; import org.apache.commons.codec.binary.Base64; @@ -70,6 +73,63 @@ import com.google.gson.JsonParser; public class AbstractOIDCAuthenticationFilter extends AbstractAuthenticationProcessingFilter { + /** + * Used to remove parameters from a Request before passing it down the chain... + * + * @author nemonik + * + */ + class SanatizedRequest extends HttpServletRequestWrapper { + + private List 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 getParameterMap() { + Map params = super.getParameterMap(); + + for (String paramToBeSanatized : paramsToBeSanatized) { + params.remove(paramToBeSanatized); + } + + return params; + } + + public Enumeration getParameterNames() { + + ArrayList 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 String SCOPE = "openid"; protected final static int KEY_SIZE = 1024; @@ -105,9 +165,9 @@ public class AbstractOIDCAuthenticationFilter extends String name = (String) e.nextElement(); if ((ignore == null) || (!ignore.contains(name))) { - + // Assume for simplicity that there is only one value - + String value = request.getParameter(name); if (value == null) { @@ -152,19 +212,19 @@ public class AbstractOIDCAuthenticationFilter extends char appendChar = '?'; for (Map.Entry param : queryStringFields.entrySet()) { - + try { - + URLBuilder.append(appendChar).append(param.getKey()) .append('=') .append(URLEncoder.encode(param.getValue(), "UTF-8")); - + } catch (UnsupportedEncodingException uee) { - + throw new IllegalStateException(uee); - + } - + appendChar = '&'; } @@ -196,11 +256,11 @@ public class AbstractOIDCAuthenticationFilter extends .replace("=", ""); } catch (GeneralSecurityException generalSecurityException) { - + // generalSecurityException.printStackTrace(); - + throw new IllegalStateException(generalSecurityException); - + } return signature; @@ -227,17 +287,17 @@ public class AbstractOIDCAuthenticationFilter extends return signer.verify(sigBytes); } catch (GeneralSecurityException generalSecurityException) { - + // generalSecurityException.printStackTrace(); - + throw new IllegalStateException(generalSecurityException); - + } catch (UnsupportedEncodingException unsupportedEncodingException) { - + // unsupportedEncodingException.printStackTrace(); - + throw new IllegalStateException(unsupportedEncodingException); - + } } @@ -296,29 +356,34 @@ public class AbstractOIDCAuthenticationFilter extends * javax.servlet.http.HttpServletResponse) */ @Override - public Authentication attemptAuthentication(HttpServletRequest arg0, - HttpServletResponse arg1) throws AuthenticationException, + public Authentication attemptAuthentication(HttpServletRequest request, + HttpServletResponse response) throws AuthenticationException, IOException, ServletException { + logger.debug("Request: " + request.getRequestURI() + (StringUtils.isNotBlank(request.getQueryString()) ? "?" + + request.getQueryString() : "") ); + return null; } /** * Handles the authorization grant response * + * @param authorizationGrant + * The Authorization grant code * @param request * The request from which to extract parameters and perform the * authentication * @return The authenticated user token, or null if authentication is * incomplete. + * @throws UnsupportedEncodingException */ protected Authentication handleAuthorizationGrantResponse( - HttpServletRequest request, OIDCServerConfiguration serverConfig) { + String authorizationGrant, HttpServletRequest request, + OIDCServerConfiguration serverConfig) { final boolean debug = logger.isDebugEnabled(); - String authorizationGrant = request.getParameter("code"); - // Handle Token Endpoint interaction HttpClient httpClient = new DefaultHttpClient(); @@ -329,11 +394,11 @@ public class AbstractOIDCAuthenticationFilter extends // TODO: basic auth is untested (it wasn't working last I // tested) // UsernamePasswordCredentials credentials = new - // UsernamePasswordCredentials( - // clientId, clientSecret); - // ((DefaultHttpClient) httpClient).getCredentialsProvider() - // .setCredentials(AuthScope.ANY, credentials); - // + // UsernamePasswordCredentials(serverConfig.getClientId(), + // serverConfig.getClientSecret()); + // ((DefaultHttpClient) + // httpClient).getCredentialsProvider().setCredentials(AuthScope.ANY, + // credentials); HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory( httpClient); @@ -344,7 +409,7 @@ public class AbstractOIDCAuthenticationFilter extends form.add("grant_type", "authorization_code"); form.add("code", authorizationGrant); form.add("redirect_uri", AbstractOIDCAuthenticationFilter - .buildRedirectURI(request, new String[] { "code" })); + .buildRedirectURI(request, null)); // pass clientId and clientSecret in post of request form.add("client_id", serverConfig.getClientId()); @@ -589,8 +654,13 @@ public class AbstractOIDCAuthenticationFilter extends // TODO: display, prompt, request, request_uri - response.sendRedirect(AbstractOIDCAuthenticationFilter.buildURL( - serverConfiguration.getAuthorizationEndpointURI(), urlVariables)); + String authRequest = AbstractOIDCAuthenticationFilter + .buildURL(serverConfiguration.getAuthorizationEndpointURI(), + urlVariables); + + logger.debug("Auth Request: " + authRequest); + + response.sendRedirect(authRequest); } /** diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java index 4f9f0d877..c7697048b 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationFilter.java @@ -95,9 +95,11 @@ public class OIDCAuthenticationFilter extends AbstractOIDCAuthenticationFilter { 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 { diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationUsingChooserFilter.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationUsingChooserFilter.java index 119779128..9a420dc65 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationUsingChooserFilter.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/OIDCAuthenticationUsingChooserFilter.java @@ -105,22 +105,24 @@ public class OIDCAuthenticationUsingChooserFilter extends } else if (request.getParameter("code") != null) { // Which OIDC configuration? - Cookie oidcAliasCookie = WebUtils.getCookie(request, + Cookie issuerCookie = WebUtils.getCookie(request, ISSUER_COOKIE_NAME); - return handleAuthorizationGrantResponse(request, - oidcServerConfigs.get(oidcAliasCookie.getValue())); + return handleAuthorizationGrantResponse( + request.getParameter("code"), new SanatizedRequest(request, + new String[] { "code" }), + oidcServerConfigs.get(issuerCookie.getValue())); } 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 OIDCServerConfiguration oidcServerConfig = oidcServerConfigs - .get(issuerId); + .get(issuer); if (oidcServerConfig != null) { @@ -128,10 +130,11 @@ public class OIDCAuthenticationUsingChooserFilter extends // Identifier Cookie issuerCookie = new Cookie(ISSUER_COOKIE_NAME, - issuerId); + issuer); response.addCookie(issuerCookie); - handleAuthorizationRequest(request, response, + handleAuthorizationRequest(new SanatizedRequest(request, + new String[] { "issuer" }), response, oidcServerConfig); } else { @@ -140,8 +143,8 @@ public class OIDCAuthenticationUsingChooserFilter extends // Identifier throw new AuthenticationServiceException( - "Security Filter not configured for OIDC Alias: " - + issuerId); + "Security Filter not configured for issuer: " + + issuer); } } else { @@ -154,6 +157,8 @@ public class OIDCAuthenticationUsingChooserFilter extends urlVariables.put("redirect_uri", OIDCAuthenticationUsingChooserFilter.buildRedirectURI( request, null)); + + urlVariables.put("client_id", accountChooserClientID); response.sendRedirect(OIDCAuthenticationUsingChooserFilter .buildURL(accountChooserURI, urlVariables)); diff --git a/openid-connect-common/.classpath b/openid-connect-common/.classpath index 1b28ee5d7..f5c551598 100644 --- a/openid-connect-common/.classpath +++ b/openid-connect-common/.classpath @@ -1,11 +1,11 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/openid-connect-server/.classpath b/openid-connect-server/.classpath index 8ca8f4c92..5abeb50d1 100644 --- a/openid-connect-server/.classpath +++ b/openid-connect-server/.classpath @@ -1,14 +1,14 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/openid-connect-server/.project b/openid-connect-server/.project index 4c7c87524..fbf502c55 100644 --- a/openid-connect-server/.project +++ b/openid-connect-server/.project @@ -1,43 +1,43 @@ - - - openid - Reference implementation of OpenID Connect spec (http://openid.net/connect/). NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. - - spring-security-oauth2 - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.jdt.core.javanature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.wst.jsdt.core.jsNature - org.eclipse.m2e.core.maven2Nature - - + + + openid + Reference implementation of OpenID Connect spec (http://openid.net/connect/). NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + spring-security-oauth2 + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jdt.core.javanature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + org.eclipse.m2e.core.maven2Nature + +