From b1c89783ff7b7564a1210dc38231a39144d90e63 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Thu, 14 Mar 2013 16:04:42 -0400 Subject: [PATCH] added functionality for account chooser and third-party login support --- .../client/OIDCAuthenticationFilter.java | 46 +++++---- .../client/model/IssuerServiceResponse.java | 93 +++++++++++++++++++ .../connect/client/service/IssuerService.java | 4 +- .../impl/StaticSingleIssuerService.java | 5 +- .../service/impl/ThirdPartyIssuerService.java | 71 ++++++++++++++ 5 files changed, 197 insertions(+), 22 deletions(-) create mode 100644 openid-connect-client/src/main/java/org/mitre/openid/connect/client/model/IssuerServiceResponse.java create mode 100644 openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/ThirdPartyIssuerService.java 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 e88e152b6..87afddd3b 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 @@ -34,6 +34,7 @@ import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.impl.client.DefaultHttpClient; import org.mitre.jwt.signer.service.JwtSigningAndValidationService; import org.mitre.jwt.signer.service.impl.JWKSetSigningAndValidationServiceCacheService; +import org.mitre.openid.connect.client.model.IssuerServiceResponse; import org.mitre.openid.connect.client.service.AuthRequestUrlBuilder; import org.mitre.openid.connect.client.service.ClientConfigurationService; import org.mitre.openid.connect.client.service.IssuerService; @@ -149,27 +150,34 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi HttpSession session = request.getSession(); - String issuer = issuerService.getIssuer(request); - session.setAttribute(ISSUER_SESSION_VARIABLE, issuer); + IssuerServiceResponse issResp = issuerService.getIssuer(request); - ServerConfiguration serverConfig = servers.getServerConfiguration(issuer); - ClientDetails clientConfig = clients.getClientConfiguration(issuer); - - // our redirect URI is this current URL, with no query parameters - String redirectUri = request.getRequestURL().toString(); - session.setAttribute(REDIRECT_URI_SESION_VARIABLE, redirectUri); - - // this value comes back in the id token and is checked there - String nonce = createNonce(session); - - // this value comes back in the auth code response - String state = createState(session); + if (issResp.shouldRedirect()) { + response.sendRedirect(issResp.getRedirectUrl()); + } else { + String issuer = issResp.getIssuer(); - String authRequest = authRequestBuilder.buildAuthRequestUrl(serverConfig, clientConfig, redirectUri, nonce, state); - - logger.debug("Auth Request: " + authRequest); - - response.sendRedirect(authRequest); + session.setAttribute(ISSUER_SESSION_VARIABLE, issuer); + + ServerConfiguration serverConfig = servers.getServerConfiguration(issuer); + ClientDetails clientConfig = clients.getClientConfiguration(issuer); + + // our redirect URI is this current URL, with no query parameters + String redirectUri = request.getRequestURL().toString(); + session.setAttribute(REDIRECT_URI_SESION_VARIABLE, redirectUri); + + // this value comes back in the id token and is checked there + String nonce = createNonce(session); + + // this value comes back in the auth code response + String state = createState(session); + + String authRequest = authRequestBuilder.buildAuthRequestUrl(serverConfig, clientConfig, redirectUri, nonce, state); + + logger.debug("Auth Request: " + authRequest); + + response.sendRedirect(authRequest); + } } /** diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/model/IssuerServiceResponse.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/model/IssuerServiceResponse.java new file mode 100644 index 000000000..338ebb442 --- /dev/null +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/model/IssuerServiceResponse.java @@ -0,0 +1,93 @@ +/** + * + */ +package org.mitre.openid.connect.client.model; + +/** + * + * Data container to facilitate returns from the IssuerService API. + * + * @author jricher + * + */ +public class IssuerServiceResponse { + + private String issuer; + private String loginHint; + private String targetLinkUri; + private String redirectUrl; + + /** + * @param issuer + * @param loginHint + * @param targetLinkUri + */ + public IssuerServiceResponse(String issuer, String loginHint, String targetLinkUri) { + this.issuer = issuer; + this.loginHint = loginHint; + this.targetLinkUri = targetLinkUri; + } + + /** + * @param redirectUrl + */ + public IssuerServiceResponse(String redirectUrl) { + this.redirectUrl = redirectUrl; + } + /** + * @return the issuer + */ + public String getIssuer() { + return issuer; + } + /** + * @param issuer the issuer to set + */ + public void setIssuer(String issuer) { + this.issuer = issuer; + } + /** + * @return the loginHint + */ + public String getLoginHint() { + return loginHint; + } + /** + * @param loginHint the loginHint to set + */ + public void setLoginHint(String loginHint) { + this.loginHint = loginHint; + } + /** + * @return the targetLinkUri + */ + public String getTargetLinkUri() { + return targetLinkUri; + } + /** + * @param targetLinkUri the targetLinkUri to set + */ + public void setTargetLinkUri(String targetLinkUri) { + this.targetLinkUri = targetLinkUri; + } + /** + * @return the redirectUrl + */ + public String getRedirectUrl() { + return redirectUrl; + } + /** + * @param redirectUrl the redirectUrl to set + */ + public void setRedirectUrl(String redirectUrl) { + this.redirectUrl = redirectUrl; + } + + /** + * If the redirect url has been set, then we should send a redirect using it instead of processing things. + */ + public boolean shouldRedirect() { + return this.redirectUrl != null; + } + +} diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/IssuerService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/IssuerService.java index 4abd092ba..c755e4e1e 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/IssuerService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/IssuerService.java @@ -5,6 +5,8 @@ package org.mitre.openid.connect.client.service; import javax.servlet.http.HttpServletRequest; +import org.mitre.openid.connect.client.model.IssuerServiceResponse; + /** * * Gets an issuer for the given request. Might do dynamic discovery, or might be statically configured. @@ -14,6 +16,6 @@ import javax.servlet.http.HttpServletRequest; */ public interface IssuerService { - public String getIssuer(HttpServletRequest request); + public IssuerServiceResponse getIssuer(HttpServletRequest request); } diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticSingleIssuerService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticSingleIssuerService.java index 500d0f7d8..908b439dd 100644 --- a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticSingleIssuerService.java +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/StaticSingleIssuerService.java @@ -5,6 +5,7 @@ package org.mitre.openid.connect.client.service.impl; import javax.servlet.http.HttpServletRequest; +import org.mitre.openid.connect.client.model.IssuerServiceResponse; import org.mitre.openid.connect.client.service.IssuerService; import org.springframework.beans.factory.InitializingBean; @@ -38,8 +39,8 @@ public class StaticSingleIssuerService implements IssuerService, InitializingBea * @see org.mitre.openid.connect.client.service.IssuerService#getIssuer(javax.servlet.http.HttpServletRequest) */ @Override - public String getIssuer(HttpServletRequest request) { - return getIssuer(); + public IssuerServiceResponse getIssuer(HttpServletRequest request) { + return new IssuerServiceResponse(getIssuer(), null, null); } /* (non-Javadoc) diff --git a/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/ThirdPartyIssuerService.java b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/ThirdPartyIssuerService.java new file mode 100644 index 000000000..7ae7e7b6f --- /dev/null +++ b/openid-connect-client/src/main/java/org/mitre/openid/connect/client/service/impl/ThirdPartyIssuerService.java @@ -0,0 +1,71 @@ +/** + * + */ +package org.mitre.openid.connect.client.service.impl; + +import java.net.URISyntaxException; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.http.client.utils.URIBuilder; +import org.mitre.openid.connect.client.model.IssuerServiceResponse; +import org.mitre.openid.connect.client.service.IssuerService; +import org.springframework.security.authentication.AuthenticationServiceException; + +import com.google.common.base.Strings; + +/** + * + * Determines the issuer using an account chooser or other third-party-initiated login + * + * @author jricher + * + */ +public class ThirdPartyIssuerService implements IssuerService { + + private String accountChooserUrl; + + /* (non-Javadoc) + * @see org.mitre.openid.connect.client.service.IssuerService#getIssuer(javax.servlet.http.HttpServletRequest) + */ + @Override + public IssuerServiceResponse getIssuer(HttpServletRequest request) { + + // if the issuer is passed in, return that + if (!Strings.isNullOrEmpty(request.getParameter("iss"))) { + return new IssuerServiceResponse(request.getParameter("iss"), request.getParameter("login_hint"), request.getParameter("target_link_uri")); + } else { + + try { + // otherwise, need to forward to the account chooser + String redirectUri = request.getRequestURL().toString(); + URIBuilder builder = new URIBuilder(accountChooserUrl); + + builder.addParameter("redirect_uri", redirectUri); + + return new IssuerServiceResponse(builder.build().toString()); + + } catch (URISyntaxException e) { + throw new AuthenticationServiceException("Account Chooser URL is not valid", e); + } + + + } + + } + + /** + * @return the accountChooserUrl + */ + public String getAccountChooserUrl() { + return accountChooserUrl; + } + + /** + * @param accountChooserUrl the accountChooserUrl to set + */ + public void setAccountChooserUrl(String accountChooserUrl) { + this.accountChooserUrl = accountChooserUrl; + } + +}