From f026f58014e720c6427e7e5f2dd43d35b18cc286 Mon Sep 17 00:00:00 2001 From: Sergey Beryozkin Date: Thu, 20 Jan 2022 17:03:34 +0000 Subject: [PATCH] Avoid treating IdTokens issued by providers as internal IdTokens --- .../runtime/CodeAuthenticationMechanism.java | 17 +++++++++++++++-- .../java/io/quarkus/oidc/runtime/OidcUtils.java | 9 +++++++++ .../src/main/resources/application.properties | 1 + 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CodeAuthenticationMechanism.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CodeAuthenticationMechanism.java index 89219a14c1cc2..a65f5855da1b8 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CodeAuthenticationMechanism.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/CodeAuthenticationMechanism.java @@ -53,6 +53,7 @@ public class CodeAuthenticationMechanism extends AbstractOidcAuthenticationMecha static final Uni VOID_UNI = Uni.createFrom().voidItem(); static final Integer MAX_COOKIE_VALUE_LENGTH = 4096; + private static final String INTERNAL_IDTOKEN_HEADER = "internal"; private static final Logger LOG = Logger.getLogger(CodeAuthenticationMechanism.class); private final BlockingTaskRunner createTokenStateRequestContext = new BlockingTaskRunner(); @@ -106,7 +107,7 @@ public Uni apply(AuthorizationCodeTokens session) { context.put(AuthorizationCodeTokens.class.getName(), session); return authenticate(identityProviderManager, context, new IdTokenCredential(session.getIdToken(), - !configContext.oidcConfig.authentication.isIdTokenRequired().orElse(true))) + isInternalIdToken(session.getIdToken(), configContext))) .call(new Function>() { @Override public Uni apply(SecurityIdentity identity) { @@ -153,9 +154,20 @@ public Uni apply(Throwable t) { } }); } + }); } + private boolean isInternalIdToken(String idToken, TenantConfigContext configContext) { + if (!configContext.oidcConfig.authentication.idTokenRequired.orElse(true)) { + JsonObject headers = OidcUtils.decodeJwtHeaders(idToken); + if (headers != null) { + return headers.getBoolean(INTERNAL_IDTOKEN_HEADER, false); + } + } + return false; + } + private boolean isJavaScript(RoutingContext context) { String value = context.request().getHeader("X-Requested-With"); return "JavaScript".equals(value) || "XMLHttpRequest".equals(value); @@ -361,7 +373,8 @@ public Throwable apply(Throwable tInner) { } private String generateInternalIdToken(OidcTenantConfig oidcConfig) { - return Jwt.claims().sign(KeyUtils.createSecretKeyFromSecret(oidcConfig.credentials.secret.get())); + return Jwt.claims().jws().header(INTERNAL_IDTOKEN_HEADER, true) + .sign(KeyUtils.createSecretKeyFromSecret(oidcConfig.credentials.secret.get())); } private Uni processSuccessfulAuthentication(RoutingContext context, diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java index 6029c7bc47174..d05d3a166bf89 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcUtils.java @@ -80,6 +80,10 @@ public static JsonObject decodeJwtContent(String jwt) { if (tokens.countTokens() != 1) { return null; } + return decodeAsJsonObject(encodedContent); + } + + private static JsonObject decodeAsJsonObject(String encodedContent) { try { return new JsonObject(new String(Base64.getUrlDecoder().decode(encodedContent), StandardCharsets.UTF_8)); } catch (IllegalArgumentException ex) { @@ -87,6 +91,11 @@ public static JsonObject decodeJwtContent(String jwt) { } } + public static JsonObject decodeJwtHeaders(String jwt) { + StringTokenizer tokens = new StringTokenizer(jwt, "."); + return decodeAsJsonObject(tokens.nextToken()); + } + public static List findRoles(String clientId, OidcTenantConfig.Roles rolesConfig, JsonObject json) { // If the user configured a specific path - check and enforce a claim at this path exists if (rolesConfig.getRoleClaimPath().isPresent()) { diff --git a/integration-tests/oidc-tenancy/src/main/resources/application.properties b/integration-tests/oidc-tenancy/src/main/resources/application.properties index 46dc3fbf98267..671d1b748f0f4 100644 --- a/integration-tests/oidc-tenancy/src/main/resources/application.properties +++ b/integration-tests/oidc-tenancy/src/main/resources/application.properties @@ -59,6 +59,7 @@ quarkus.oidc.tenant-web-app-no-discovery.client-id=quarkus-app-webapp quarkus.oidc.tenant-web-app-no-discovery.credentials.secret=secret quarkus.oidc.tenant-web-app-no-discovery.application-type=web-app quarkus.oidc.tenant-web-app-no-discovery.authentication.user-info-required=true +quarkus.oidc.tenant-web-app-no-discovery.authentication.id-token-required=false quarkus.oidc.tenant-web-app-no-discovery.roles.source=userinfo quarkus.oidc.tenant-web-app-no-discovery.allow-user-info-cache=false