From 9ab4a6e303c0e8a4997252b4c6a8b2dd601d73af Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 5 Apr 2023 17:40:11 +0100 Subject: Implement OpenID auto discovery --- src/main/java/org/traccar/config/Keys.java | 15 ++++++-- .../java/org/traccar/database/OpenIdProvider.java | 44 ++++++++++++++++++++-- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/traccar/config/Keys.java b/src/main/java/org/traccar/config/Keys.java index 3ff423ad1..3ed6c6026 100644 --- a/src/main/java/org/traccar/config/Keys.java +++ b/src/main/java/org/traccar/config/Keys.java @@ -636,11 +636,20 @@ public final class Keys { "openid.clientSecret", List.of(KeyType.CONFIG)); + /** + * OpenID Connect Issuer (Base) URL. + * This is used to automatically configure the authorization, token and user info URLs if + * they are not provided. + */ + public static final ConfigKey OPENID_ISSUERURL = new StringConfigKey( + "openid.issuerUrl", + List.of(KeyType.CONFIG)); + /** * OpenID Connect Authorization URL. * This can usually be found in the documentation of your identity provider or by using the well-known * configuration endpoint, eg. https://auth.example.com//.well-known/openid-configuration - * Required to enable SSO. + * Required to enable SSO if openid.issuerUrl is not set. */ public static final ConfigKey OPENID_AUTHURL = new StringConfigKey( "openid.authUrl", @@ -648,7 +657,7 @@ public final class Keys { /** * OpenID Connect Token URL. * This can be found in the same ways at openid.authUrl. - * Required to enable SSO. + * Required to enable SSO if openid.issuerUrl is not set. */ public static final ConfigKey OPENID_TOKENURL = new StringConfigKey( "openid.tokenUrl", @@ -657,7 +666,7 @@ public final class Keys { /** * OpenID Connect User Info URL. * This can be found in the same ways at openid.authUrl. - * Required to enable SSO. + * Required to enable SSO if openid.issuerUrl is not set. */ public static final ConfigKey OPENID_USERINFOURL = new StringConfigKey( "openid.userInfoUrl", diff --git a/src/main/java/org/traccar/database/OpenIdProvider.java b/src/main/java/org/traccar/database/OpenIdProvider.java index 537319b31..2b0f9d290 100644 --- a/src/main/java/org/traccar/database/OpenIdProvider.java +++ b/src/main/java/org/traccar/database/OpenIdProvider.java @@ -26,9 +26,16 @@ import org.traccar.helper.ServletHelper; import java.net.URI; import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse.BodyHandlers; import java.security.GeneralSecurityException; +import java.util.Map; import java.io.IOException; import javax.servlet.http.HttpServletRequest; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -82,12 +89,43 @@ public class OpenIdProvider { try { callbackUrl = new URI(config.getString(Keys.WEB_URL, "") + "/api/session/openid/callback"); - authUrl = new URI(config.getString(Keys.OPENID_AUTHURL, "")); - tokenUrl = new URI(config.getString(Keys.OPENID_TOKENURL, "")); - userInfoUrl = new URI(config.getString(Keys.OPENID_USERINFOURL, "")); baseUrl = new URI(config.getString(Keys.WEB_URL, "")); + + if ( + config.hasKey(Keys.OPENID_ISSUERURL) + && ( + !config.hasKey(Keys.OPENID_AUTHURL) + || !config.hasKey(Keys.OPENID_TOKENURL) + || !config.hasKey(Keys.OPENID_USERINFOURL)) + ) { + HttpClient httpClient = HttpClient.newHttpClient(); + + HttpRequest httpRequest = HttpRequest.newBuilder( + URI.create( + config.getString(Keys.OPENID_ISSUERURL) + "/.well-known/openid-configuration") + ) + .header("accept", "application/json") + .build(); + + String httpResponse = httpClient.send(httpRequest, BodyHandlers.ofString()).body(); + + Map discoveryMap = new ObjectMapper().readValue( + httpResponse, new TypeReference>() { }); + + authUrl = new URI(discoveryMap.get("authorization_endpoint").toString()); + tokenUrl = new URI(discoveryMap.get("token_endpoint").toString()); + userInfoUrl = new URI(discoveryMap.get("userinfo_endpoint").toString()); + + LOGGER.info("OpenID Connect auto discovery successful"); + } else { + authUrl = new URI(config.getString(Keys.OPENID_AUTHURL)); + tokenUrl = new URI(config.getString(Keys.OPENID_TOKENURL)); + userInfoUrl = new URI(config.getString(Keys.OPENID_USERINFOURL)); + } } catch (URISyntaxException error) { LOGGER.error("Invalid URIs provided in OpenID configuration"); + } catch (InterruptedException | IOException error) { + LOGGER.error("OpenID Connect auto discovery failed"); } adminGroup = config.getString(Keys.OPENID_ADMINGROUP); -- cgit v1.2.3