diff --git a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java index 1c23d2eb94c90..2202a7cc74ae4 100644 --- a/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java +++ b/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java @@ -123,6 +123,19 @@ public Uni apply(UserInfo userInfo, Throwable t) { } }); } else { + final Uni primaryTokenUni; + if (isInternalIdToken(request)) { + if (vertxContext.get(NEW_AUTHENTICATION) == Boolean.TRUE) { + // No need to verify it in this case as 'CodeAuthenticationMechanism' has just created it + primaryTokenUni = Uni.createFrom() + .item(new TokenVerificationResult(OidcUtils.decodeJwtContent(request.getToken().getToken()), null)); + } else { + primaryTokenUni = verifySelfSignedTokenUni(resolvedContext, request.getToken().getToken()); + } + } else { + primaryTokenUni = verifyTokenUni(resolvedContext, request.getToken().getToken(), isIdToken(request), null); + } + // Verify Code Flow access token first if it is available and has to be verified. // It may be refreshed if it has or has nearly expired Uni codeAccessTokenUni = verifyCodeFlowAccessTokenUni(vertxContext, request, @@ -143,7 +156,7 @@ public Uni apply(TokenVerificationResult codeAccessTokenResult } vertxContext.put(CODE_ACCESS_TOKEN_RESULT, codeAccessTokenResult); } - return getUserInfoAndCreateIdentity(vertxContext, request, resolvedContext); + return getUserInfoAndCreateIdentity(primaryTokenUni, vertxContext, request, resolvedContext); } }); @@ -168,12 +181,16 @@ public Uni apply(TokenVerificationResult codeAccessToken, Thro vertxContext.put(CODE_ACCESS_TOKEN_RESULT, codeAccessToken); } - return createSecurityIdentityWithOidcServer(vertxContext, request, resolvedContext, userInfo); + Uni tokenUni = verifyTokenUni(resolvedContext, request.getToken().getToken(), + false, userInfo); + + return createSecurityIdentityWithOidcServer(tokenUni, vertxContext, request, resolvedContext, userInfo); } }); } - private Uni getUserInfoAndCreateIdentity(RoutingContext vertxContext, TokenAuthenticationRequest request, + private Uni getUserInfoAndCreateIdentity(Uni tokenUni, + RoutingContext vertxContext, TokenAuthenticationRequest request, TenantConfigContext resolvedContext) { Uni userInfo = resolvedContext.oidcConfig.authentication.isUserInfoRequired().orElse(false) @@ -187,7 +204,7 @@ public Uni apply(UserInfo userInfo, Throwable t) { if (t != null) { return Uni.createFrom().failure(new AuthenticationFailedException(t)); } - return createSecurityIdentityWithOidcServer(vertxContext, request, resolvedContext, userInfo); + return createSecurityIdentityWithOidcServer(tokenUni, vertxContext, request, resolvedContext, userInfo); } }); } @@ -205,20 +222,9 @@ private boolean isOpaqueAccessToken(RoutingContext vertxContext, TokenAuthentica return false; } - private Uni createSecurityIdentityWithOidcServer(RoutingContext vertxContext, - TokenAuthenticationRequest request, TenantConfigContext resolvedContext, final UserInfo userInfo) { - Uni tokenUni = null; - if (isInternalIdToken(request)) { - if (vertxContext.get(NEW_AUTHENTICATION) == Boolean.TRUE) { - // No need to verify it in this case as 'CodeAuthenticationMechanism' has just created it - tokenUni = Uni.createFrom() - .item(new TokenVerificationResult(OidcUtils.decodeJwtContent(request.getToken().getToken()), null)); - } else { - tokenUni = verifySelfSignedTokenUni(resolvedContext, request.getToken().getToken()); - } - } else { - tokenUni = verifyTokenUni(resolvedContext, request.getToken().getToken(), isIdToken(request), userInfo); - } + private Uni createSecurityIdentityWithOidcServer(Uni tokenUni, + RoutingContext vertxContext, TokenAuthenticationRequest request, TenantConfigContext resolvedContext, + final UserInfo userInfo) { return tokenUni.onItemOrFailure() .transformToUni(new BiFunction>() { diff --git a/integration-tests/oidc-tenancy/src/main/resources/application.properties b/integration-tests/oidc-tenancy/src/main/resources/application.properties index af8297b86a941..8337049ec45c6 100644 --- a/integration-tests/oidc-tenancy/src/main/resources/application.properties +++ b/integration-tests/oidc-tenancy/src/main/resources/application.properties @@ -83,8 +83,12 @@ quarkus.oidc.tenant-hybrid-service.application-type=service # Tenant Hybrid Web-App quarkus.oidc.tenant-hybrid-webapp.auth-server-url=${keycloak.url}/realms/quarkus-hybrid +quarkus.oidc.tenant-hybrid-webapp.user-info-path=http://localhost:8081/oidc/userinfo quarkus.oidc.tenant-hybrid-webapp.client-id=quarkus-app-hybrid quarkus.oidc.tenant-hybrid-webapp.credentials.secret=secret +quarkus.oidc.tenant-hybrid-webapp.authentication.user-info-required=true +quarkus.oidc.tenant-hybrid-webapp.allow-user-info-cache=false +quarkus.oidc.tenant-hybrid-webapp.authentication.remove-redirect-parameters=false quarkus.oidc.tenant-hybrid-webapp.application-type=web-app # Tenant Hybrid Web-App Service diff --git a/integration-tests/oidc-tenancy/src/test/java/io/quarkus/it/keycloak/BearerTokenAuthorizationTest.java b/integration-tests/oidc-tenancy/src/test/java/io/quarkus/it/keycloak/BearerTokenAuthorizationTest.java index 151454eeb2d71..12c500bd7bb76 100644 --- a/integration-tests/oidc-tenancy/src/test/java/io/quarkus/it/keycloak/BearerTokenAuthorizationTest.java +++ b/integration-tests/oidc-tenancy/src/test/java/io/quarkus/it/keycloak/BearerTokenAuthorizationTest.java @@ -173,6 +173,7 @@ public Boolean call() throws Exception { @Test public void testHybridWebApp() throws IOException { + RestAssured.when().post("/oidc/userinfo-endpoint-call-count").then().body(equalTo("0")); try (final WebClient webClient = createWebClient()) { HtmlPage page = webClient.getPage("http://localhost:8081/tenants/tenant-hybrid/api/user"); assertNotNull(getStateCookie(webClient, "tenant-hybrid-webapp")); @@ -184,6 +185,7 @@ public void testHybridWebApp() throws IOException { assertEquals("alice:web-app", page.getBody().asNormalizedText()); webClient.getCookieManager().clearCookies(); } + RestAssured.when().get("/oidc/userinfo-endpoint-call-count").then().body(equalTo("1")); } @Test