Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show how to handle multiple OIDC token audiences #40683

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package io.quarkus.it.keycloak;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

import org.eclipse.microprofile.jwt.JsonWebToken;

import io.quarkus.oidc.IdToken;
import io.quarkus.oidc.runtime.DefaultTokenIntrospectionUserInfoCache;
import io.quarkus.security.Authenticated;
import io.vertx.ext.web.RoutingContext;

@Path("/code-flow-verify-id-and-access-tokens")
public class CodeFlowVerifyIdAndAccessTokenResource {

@Inject
@IdToken
JsonWebToken idToken;

@Inject
JsonWebToken accessToken;

@Inject
RoutingContext routingContext;

@Inject
DefaultTokenIntrospectionUserInfoCache tokenCache;

@GET
@Authenticated
public String access() {
return "access token verified: " + (routingContext.get("code_flow_access_token_result") != null)
+ ", id_token issuer: " + idToken.getIssuer()
+ ", access_token issuer: " + accessToken.getIssuer()
+ ", id_token audience: " + idToken.getAudience().iterator().next()
+ ", access_token audience: " + accessToken.getAudience().iterator().next()
+ ", cache size: " + tokenCache.getCacheSize();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,18 @@ quarkus.oidc.code-flow.logout.post-logout-uri-param=returnTo
quarkus.oidc.code-flow.logout.extra-params.client_id=${quarkus.oidc.code-flow.client-id}
quarkus.oidc.code-flow.credentials.secret=secret
quarkus.oidc.code-flow.application-type=web-app
quarkus.oidc.code-flow.token.audience=https://server.example.com
quarkus.oidc.code-flow.token.audience=https://id.server.example.com
quarkus.oidc.code-flow.token.refresh-expired=true
quarkus.oidc.code-flow.token.refresh-token-time-skew=5M

quarkus.oidc.code-flow-verify-id-and-access-tokens.auth-server-url=${keycloak.url}/realms/quarkus/
quarkus.oidc.code-flow-verify-id-and-access-tokens.client-id=quarkus-web-app
quarkus.oidc.code-flow-verify-id-and-access-tokens.authentication.user-info-required=false
quarkus.oidc.code-flow-verify-id-and-access-tokens.authentication.verify-access-token=true
quarkus.oidc.code-flow-verify-id-and-access-tokens.credentials.secret=secret
quarkus.oidc.code-flow-verify-id-and-access-tokens.application-type=web-app
quarkus.oidc.code-flow-verify-id-and-access-tokens.token.audience=any

quarkus.oidc.code-flow-encrypted-id-token-jwk.auth-server-url=${keycloak.url}/realms/quarkus/
quarkus.oidc.code-flow-encrypted-id-token-jwk.client-id=quarkus-web-app
quarkus.oidc.code-flow-encrypted-id-token-jwk.credentials.secret=secret
Expand Down Expand Up @@ -60,7 +68,7 @@ quarkus.oidc.code-flow-form-post.token-path=${keycloak.url}/realms/quarkus/token
quarkus.oidc.code-flow-form-post.jwks-path=${keycloak.url}/realms/quarkus/protocol/openid-connect/certs
quarkus.oidc.code-flow-form-post.logout.backchannel.path=/back-channel-logout
quarkus.oidc.code-flow-form-post.logout.frontchannel.path=/code-flow-form-post/front-channel-logout
quarkus.oidc.code-flow-form-post.token.audience=https://server.example.com
quarkus.oidc.code-flow-form-post.token.audience=https://server.example.com,https://id.server.example.com

quarkus.oidc.code-flow-user-info-only.auth-server-url=${keycloak.url}/realms/quarkus/
quarkus.oidc.code-flow-user-info-only.discovery-enabled=false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,31 @@ public void testCodeFlow() throws IOException {
clearCache();
}

@Test
public void testCodeFlowVerifyIdAndAccessToken() throws IOException {
defineCodeFlowLogoutStub();
try (final WebClient webClient = createWebClient()) {
webClient.getOptions().setRedirectEnabled(true);
HtmlPage page = webClient.getPage("http://localhost:8081/code-flow-verify-id-and-access-tokens");

HtmlForm form = page.getFormByName("form");
form.getInputByName("username").type("alice");
form.getInputByName("password").type("alice");

TextPage textPage = form.getInputByValue("login").click();

assertEquals("access token verified: true,"
+ " id_token issuer: https://server.example.com,"
+ " access_token issuer: https://server.example.com,"
+ " id_token audience: https://id.server.example.com,"
+ " access_token audience: https://server.example.com,"
+ " cache size: 0", textPage.getContent());
assertNotNull(getSessionCookie(webClient, "code-flow-verify-id-and-access-tokens"));
webClient.getCookieManager().clearCookies();
}
clearCache();
}

@Test
public void testCodeFlowEncryptedIdTokenJwk() throws IOException {
doTestCodeFlowEncryptedIdToken("code-flow-encrypted-id-token-jwk", KeyEncryptionAlgorithm.DIR);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public class OidcWiremockTestResource implements QuarkusTestResourceLifecycleMan
"https://server.example.com");
private static final String TOKEN_AUDIENCE = System.getProperty("quarkus.test.oidc.token.audience",
"https://server.example.com");
private static final String ID_TOKEN_AUDIENCE = System.getProperty("quarkus.test.oidc.idtoken.audience",
"https://id.server.example.com");
private static final String TOKEN_SUBJECT = "123456";
private static final String BEARER_TOKEN_TYPE = "Bearer";
private static final String ID_TOKEN_TYPE = "ID";
Expand Down Expand Up @@ -385,10 +387,11 @@ public static String generateJwtToken(String userName, Set<String> groups, Strin
}

public static String generateJwtToken(String userName, Set<String> groups, String sub, String type) {
final String audience = ID_TOKEN_TYPE.equals(type) ? ID_TOKEN_AUDIENCE : TOKEN_AUDIENCE;
JwtClaimsBuilder builder = Jwt.preferredUserName(userName)
.groups(groups)
.issuer(TOKEN_ISSUER)
.audience(TOKEN_AUDIENCE)
.audience(audience)
.claim("sid", "session-id")
.subject(sub);
if (type != null) {
Expand Down