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

Fix OIDC token verification failure message #35005

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
Expand Up @@ -424,12 +424,12 @@ private Uni<TokenVerificationResult> verifyTokenUni(TenantConfigContext resolved
}
}
LOG.debug("Starting the opaque token introspection");
return introspectTokenUni(resolvedContext, token);
return introspectTokenUni(resolvedContext, token, false);
} else if (resolvedContext.provider.getMetadata().getJsonWebKeySetUri() == null
|| resolvedContext.oidcConfig.token.requireJwtIntrospectionOnly) {
// Verify JWT token with the remote introspection
LOG.debug("Starting the JWT token introspection");
return introspectTokenUni(resolvedContext, token);
return introspectTokenUni(resolvedContext, token, false);
} else {
// Verify JWT token with the local JWK keys with a possible remote introspection fallback
try {
Expand Down Expand Up @@ -458,32 +458,47 @@ private Uni<TokenVerificationResult> verifySelfSignedTokenUni(TenantConfigContex
private Uni<TokenVerificationResult> refreshJwksAndVerifyTokenUni(TenantConfigContext resolvedContext, String token,
boolean enforceAudienceVerification) {
return resolvedContext.provider.refreshJwksAndVerifyJwtToken(token, enforceAudienceVerification)
.onFailure(f -> f.getCause() instanceof UnresolvableKeyException
&& resolvedContext.oidcConfig.token.allowJwtIntrospection)
.recoverWithUni(f -> introspectTokenUni(resolvedContext, token));
.onFailure(f -> fallbackToIntrospectionIfNoMatchingKey(f, resolvedContext))
.recoverWithUni(f -> introspectTokenUni(resolvedContext, token, true));
}

private Uni<TokenVerificationResult> introspectTokenUni(TenantConfigContext resolvedContext, final String token) {
private static boolean fallbackToIntrospectionIfNoMatchingKey(Throwable f, TenantConfigContext resolvedContext) {
if (!(f.getCause() instanceof UnresolvableKeyException)) {
LOG.debug("Local JWT token verification has failed, skipping the token introspection");
return false;
} else if (!resolvedContext.oidcConfig.token.allowJwtIntrospection) {
LOG.debug("JWT token does not have a matching verification key but JWT token introspection is disabled");
return false;
} else {
LOG.debug("Local JWT token verification has failed, attempting the token introspection");
return true;
}

}

private Uni<TokenVerificationResult> introspectTokenUni(TenantConfigContext resolvedContext, final String token,
boolean fallbackFromJwkMatch) {
TokenIntrospectionCache tokenIntrospectionCache = tenantResolver.getTokenIntrospectionCache();
Uni<TokenIntrospection> tokenIntrospectionUni = tokenIntrospectionCache == null ? null
: tokenIntrospectionCache
.getIntrospection(token, resolvedContext.oidcConfig, getIntrospectionRequestContext);
if (tokenIntrospectionUni == null) {
tokenIntrospectionUni = newTokenIntrospectionUni(resolvedContext, token);
tokenIntrospectionUni = newTokenIntrospectionUni(resolvedContext, token, fallbackFromJwkMatch);
} else {
tokenIntrospectionUni = tokenIntrospectionUni.onItem().ifNull()
.switchTo(new Supplier<Uni<? extends TokenIntrospection>>() {
@Override
public Uni<TokenIntrospection> get() {
return newTokenIntrospectionUni(resolvedContext, token);
return newTokenIntrospectionUni(resolvedContext, token, fallbackFromJwkMatch);
}
});
}
return tokenIntrospectionUni.onItem().transform(t -> new TokenVerificationResult(null, t));
}

private Uni<TokenIntrospection> newTokenIntrospectionUni(TenantConfigContext resolvedContext, String token) {
Uni<TokenIntrospection> tokenIntrospectionUni = resolvedContext.provider.introspectToken(token);
private Uni<TokenIntrospection> newTokenIntrospectionUni(TenantConfigContext resolvedContext, String token,
boolean fallbackFromJwkMatch) {
Uni<TokenIntrospection> tokenIntrospectionUni = resolvedContext.provider.introspectToken(token, fallbackFromJwkMatch);
if (tenantResolver.getTokenIntrospectionCache() == null || !resolvedContext.oidcConfig.allowTokenIntrospectionCache) {
return tokenIntrospectionUni;
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,13 +267,15 @@ public Uni<? extends TokenVerificationResult> apply(Void v) {
});
}

public Uni<TokenIntrospection> introspectToken(String token) {
public Uni<TokenIntrospection> introspectToken(String token, boolean fallbackFromJwkMatch) {
if (client.getMetadata().getIntrospectionUri() == null) {
LOG.debugf(
"Token issued to client %s can not be introspected because the introspection endpoint address is unknown - "
+ "please check if your OpenId Connect Provider supports the token introspection",
String errorMessage = String.format("Token issued to client %s "
+ (fallbackFromJwkMatch ? "does not have a matching verification key and it " : "")
+ "can not be introspected because the introspection endpoint address is unknown - "
+ "please check if your OpenId Connect Provider supports the token introspection",
oidcConfig.clientId.get());
throw new AuthenticationFailedException();

throw new AuthenticationFailedException(errorMessage);
}
return client.introspectToken(token).onItemOrFailure()
.transform(new BiFunction<TokenIntrospection, Throwable, TokenIntrospection>() {
Expand Down