feat(auth): OidcProviderNameDeriver — issuer URI → display label

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-26 18:53:31 +02:00
parent f1aa1ea19f
commit ddb18c4f17
2 changed files with 94 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
package com.cameleer.server.app.security;
import java.net.URI;
/**
* Pure utility — derives a display label for an OIDC provider from its issuer URI.
* Used by {@link AuthCapabilitiesController} so the SPA can render
* "Sign in with {providerName}" on the login page.
*
* <p>Pattern-match only — never network-discover. If the issuer doesn't match a
* known vendor pattern, we return the generic "Single Sign-On" label rather than
* leaking hostnames into the UI.
*/
public final class OidcProviderNameDeriver {
private static final String GENERIC = "Single Sign-On";
private OidcProviderNameDeriver() {}
public static String deriveName(String issuerUri) {
if (issuerUri == null || issuerUri.isBlank()) {
return GENERIC;
}
String host;
try {
URI uri = URI.create(issuerUri.trim());
host = uri.getHost();
} catch (IllegalArgumentException e) {
return GENERIC;
}
if (host == null || host.isBlank()) {
return GENERIC;
}
String h = host.toLowerCase();
if (h.contains("logto")) return "Logto";
if (h.contains("keycloak")) return "Keycloak";
if (h.endsWith("auth0.com")) return "Auth0";
if (h.endsWith("okta.com") || h.endsWith("oktapreview.com")) return "Okta";
return GENERIC;
}
}

View File

@@ -0,0 +1,53 @@
package com.cameleer.server.app.security;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/** Unit tests for {@link OidcProviderNameDeriver}. No Spring context. */
class OidcProviderNameDeriverTest {
@Test
void logtoIssuer_returnsLogto() {
assertThat(OidcProviderNameDeriver.deriveName("https://auth.logto.example/")).isEqualTo("Logto");
assertThat(OidcProviderNameDeriver.deriveName("https://logto.cameleer.local")).isEqualTo("Logto");
}
@Test
void keycloakIssuer_returnsKeycloak() {
assertThat(OidcProviderNameDeriver.deriveName("https://keycloak.example/realms/cameleer")).isEqualTo("Keycloak");
}
@Test
void auth0Issuer_returnsAuth0() {
assertThat(OidcProviderNameDeriver.deriveName("https://example.auth0.com/")).isEqualTo("Auth0");
}
@Test
void oktaIssuer_returnsOkta() {
assertThat(OidcProviderNameDeriver.deriveName("https://dev-123.okta.com/")).isEqualTo("Okta");
assertThat(OidcProviderNameDeriver.deriveName("https://login.oktapreview.com/")).isEqualTo("Okta");
}
@Test
void unknownIssuer_returnsGenericLabel() {
assertThat(OidcProviderNameDeriver.deriveName("https://idp.example.com/")).isEqualTo("Single Sign-On");
}
@Test
void blankOrNullIssuer_returnsGenericLabel() {
assertThat(OidcProviderNameDeriver.deriveName("")).isEqualTo("Single Sign-On");
assertThat(OidcProviderNameDeriver.deriveName(null)).isEqualTo("Single Sign-On");
assertThat(OidcProviderNameDeriver.deriveName(" ")).isEqualTo("Single Sign-On");
}
@Test
void malformedUri_returnsGenericLabel() {
assertThat(OidcProviderNameDeriver.deriveName("not a url")).isEqualTo("Single Sign-On");
}
@Test
void caseInsensitiveMatching() {
assertThat(OidcProviderNameDeriver.deriveName("https://AUTH.LOGTO.EXAMPLE/")).isEqualTo("Logto");
}
}