diff --git a/jetty-openid/src/main/config/etc/jetty-openid.xml b/jetty-openid/src/main/config/etc/jetty-openid.xml index 65506e85ca8..83b6d798773 100644 --- a/jetty-openid/src/main/config/etc/jetty-openid.xml +++ b/jetty-openid/src/main/config/etc/jetty-openid.xml @@ -2,7 +2,9 @@ - + + + diff --git a/jetty-openid/src/main/config/modules/openid.mod b/jetty-openid/src/main/config/modules/openid.mod index c9a4cc7476e..7f1450c3fe6 100644 --- a/jetty-openid/src/main/config/modules/openid.mod +++ b/jetty-openid/src/main/config/modules/openid.mod @@ -18,11 +18,17 @@ etc/openid-baseloginservice.xml etc/jetty-openid.xml [ini-template] -## The OpenID Identity Provider -# jetty.openid.openIdProvider=https://accounts.google.com/ +## The OpenID Identity Provider's issuer ID (the entire URL *before* ".well-known/openid-configuration") +# jetty.openid.provider=https://id.example.com/~ + +## The OpenID Identity Provider's authorization endpoint (optional if the metadata of the OP is accessible) +# jetty.openid.provider.authorizationEndpoint=https://id.example.com/authorization + +## The OpenID Identity Provider's token endpoint (optional if the metadata of the OP is accessible) +# jetty.openid.provider.tokenEndpoint=https://id.example.com/token ## The Client Identifier -# jetty.openid.clientId=test1234.apps.googleusercontent.com +# jetty.openid.clientId=test1234 ## The Client Secret # jetty.openid.clientSecret=XT_Mafv_aUCGheuCaKY8P diff --git a/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdConfiguration.java b/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdConfiguration.java index f3c9134b4a0..e628f1aaa09 100644 --- a/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdConfiguration.java +++ b/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdConfiguration.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.ajax.JSON; @@ -43,13 +44,11 @@ public class OpenIdConfiguration implements Serializable private static final long serialVersionUID = 2227941990601349102L; private static final String CONFIG_PATH = "/.well-known/openid-configuration"; - private final String openIdProvider; private final String issuer; private final String authEndpoint; private final String tokenEndpoint; private final String clientId; private final String clientSecret; - private final Map discoveryDocument; private final List scopes = new ArrayList<>(); /** @@ -60,10 +59,50 @@ public class OpenIdConfiguration implements Serializable */ public OpenIdConfiguration(String provider, String clientId, String clientSecret) { - this.openIdProvider = provider; + this(provider, null, null, clientId, clientSecret); + } + + /** + * Create an OpenID configuration for a specific OIDC provider. + * @param issuer The URL of the OpenID provider. + * @param authorizationEndpoint the URL of the OpenID provider's authorization endpoint if configured. + * @param tokenEndpoint the URL of the OpenID provider's token endpoint if configured. + * @param clientId OAuth 2.0 Client Identifier valid at the Authorization Server. + * @param clientSecret The client secret known only by the Client and the Authorization Server. + */ + public OpenIdConfiguration(String issuer, String authorizationEndpoint, String tokenEndpoint, String clientId, String clientSecret) + { + this.issuer = issuer; this.clientId = clientId; this.clientSecret = clientSecret; + if (issuer == null) + throw new IllegalArgumentException("Provider was not configured"); + + if (tokenEndpoint == null || authorizationEndpoint == null) + { + Map discoveryDocument = fetchOpenIdConnectMetadata(issuer); + + this.authEndpoint = (String)discoveryDocument.get("authorization_endpoint"); + if (this.authEndpoint == null) + throw new IllegalArgumentException("authorization_endpoint"); + + this.tokenEndpoint = (String)discoveryDocument.get("token_endpoint"); + if (this.tokenEndpoint == null) + throw new IllegalArgumentException("token_endpoint"); + + if (!Objects.equals(discoveryDocument.get("issuer"), issuer)) + LOG.warn("The provider in the metadata is not correct."); + } + else + { + this.authEndpoint = authorizationEndpoint; + this.tokenEndpoint = tokenEndpoint; + } + } + + private static Map fetchOpenIdConnectMetadata(String provider) + { try { if (provider.endsWith("/")) @@ -72,31 +111,16 @@ public class OpenIdConfiguration implements Serializable URI providerUri = URI.create(provider + CONFIG_PATH); InputStream inputStream = providerUri.toURL().openConnection().getInputStream(); String content = IO.toString(inputStream); - discoveryDocument = (Map)JSON.parse(content); + Map discoveryDocument = (Map)JSON.parse(content); if (LOG.isDebugEnabled()) LOG.debug("discovery document {}", discoveryDocument); + + return discoveryDocument; } catch (Throwable e) { throw new IllegalArgumentException("invalid identity provider", e); } - - issuer = (String)discoveryDocument.get("issuer"); - if (issuer == null) - throw new IllegalArgumentException(); - - authEndpoint = (String)discoveryDocument.get("authorization_endpoint"); - if (authEndpoint == null) - throw new IllegalArgumentException("authorization_endpoint"); - - tokenEndpoint = (String)discoveryDocument.get("token_endpoint"); - if (tokenEndpoint == null) - throw new IllegalArgumentException("token_endpoint"); - } - - public Map getDiscoveryDocument() - { - return discoveryDocument; } public String getAuthEndpoint() @@ -119,11 +143,6 @@ public class OpenIdConfiguration implements Serializable return issuer; } - public String getOpenIdProvider() - { - return openIdProvider; - } - public String getTokenEndpoint() { return tokenEndpoint; diff --git a/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdCredentials.java b/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdCredentials.java index 5390e432449..da0f0fac7bd 100644 --- a/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdCredentials.java +++ b/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdCredentials.java @@ -242,7 +242,7 @@ public class OpenIdCredentials implements Serializable { connection.setDoOutput(true); connection.setRequestMethod("POST"); - connection.setRequestProperty("Host", configuration.getOpenIdProvider()); + connection.setRequestProperty("Host", configuration.getIssuer()); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) diff --git a/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdLoginService.java b/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdLoginService.java index 512ff474b71..67ec142825b 100644 --- a/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdLoginService.java +++ b/jetty-openid/src/main/java/org/eclipse/jetty/security/openid/OpenIdLoginService.java @@ -67,7 +67,7 @@ public class OpenIdLoginService extends ContainerLifeCycle implements LoginServi @Override public String getName() { - return _configuration.getOpenIdProvider(); + return _configuration.getIssuer(); } public OpenIdConfiguration getConfiguration()