use of io.quarkus.oidc.AuthorizationCodeTokens in project quarkus by quarkusio.
the class DefaultTokenStateManager method getTokens.
@Override
public Uni<AuthorizationCodeTokens> getTokens(RoutingContext routingContext, OidcTenantConfig oidcConfig, String tokenState, OidcRequestContext<AuthorizationCodeTokens> requestContext) {
String[] tokens = CodeAuthenticationMechanism.COOKIE_PATTERN.split(tokenState);
String idToken = decryptToken(tokens[0], routingContext, oidcConfig);
String accessToken = null;
String refreshToken = null;
if (oidcConfig.tokenStateManager.strategy == OidcTenantConfig.TokenStateManager.Strategy.KEEP_ALL_TOKENS) {
if (!oidcConfig.tokenStateManager.splitTokens) {
accessToken = decryptToken(tokens[1], routingContext, oidcConfig);
refreshToken = decryptToken(tokens[2], routingContext, oidcConfig);
} else {
Cookie atCookie = getAccessTokenCookie(routingContext, oidcConfig);
if (atCookie != null) {
accessToken = decryptToken(atCookie.getValue(), routingContext, oidcConfig);
}
Cookie rtCookie = getRefreshTokenCookie(routingContext, oidcConfig);
if (rtCookie != null) {
refreshToken = decryptToken(rtCookie.getValue(), routingContext, oidcConfig);
}
}
} else if (oidcConfig.tokenStateManager.strategy == OidcTenantConfig.TokenStateManager.Strategy.ID_REFRESH_TOKENS) {
if (!oidcConfig.tokenStateManager.splitTokens) {
refreshToken = decryptToken(tokens[2], routingContext, oidcConfig);
} else {
Cookie rtCookie = getRefreshTokenCookie(routingContext, oidcConfig);
if (rtCookie != null) {
refreshToken = decryptToken(rtCookie.getValue(), routingContext, oidcConfig);
}
}
}
return Uni.createFrom().item(new AuthorizationCodeTokens(idToken, accessToken, refreshToken));
}
use of io.quarkus.oidc.AuthorizationCodeTokens in project quarkus by quarkusio.
the class OidcUtils method validateAndCreateIdentity.
static QuarkusSecurityIdentity validateAndCreateIdentity(RoutingContext vertxContext, TokenCredential credential, TenantConfigContext resolvedContext, JsonObject tokenJson, JsonObject rolesJson, UserInfo userInfo, TokenIntrospection introspectionResult) {
OidcTenantConfig config = resolvedContext.oidcConfig;
QuarkusSecurityIdentity.Builder builder = QuarkusSecurityIdentity.builder();
builder.addCredential(credential);
AuthorizationCodeTokens codeTokens = vertxContext != null ? vertxContext.get(AuthorizationCodeTokens.class.getName()) : null;
if (codeTokens != null) {
RefreshToken refreshTokenCredential = new RefreshToken(codeTokens.getRefreshToken());
builder.addCredential(refreshTokenCredential);
builder.addCredential(new AccessTokenCredential(codeTokens.getAccessToken(), refreshTokenCredential));
}
JsonWebToken jwtPrincipal;
try {
JwtClaims jwtClaims = JwtClaims.parse(tokenJson.encode());
jwtClaims.setClaim(Claims.raw_token.name(), credential.getToken());
jwtPrincipal = new OidcJwtCallerPrincipal(jwtClaims, credential, config.token.principalClaim.isPresent() ? config.token.principalClaim.get() : null);
} catch (InvalidJwtException e) {
throw new AuthenticationFailedException(e);
}
builder.addAttribute(QUARKUS_IDENTITY_EXPIRE_TIME, jwtPrincipal.getExpirationTime());
builder.setPrincipal(jwtPrincipal);
setRoutingContextAttribute(builder, vertxContext);
setSecurityIdentityRoles(builder, config, rolesJson);
setSecurityIdentityUserInfo(builder, userInfo);
setSecurityIdentityIntrospecton(builder, introspectionResult);
setSecurityIdentityConfigMetadata(builder, resolvedContext);
setBlockinApiAttribute(builder, vertxContext);
setTenantIdAttribute(builder, config);
return builder.build();
}
use of io.quarkus.oidc.AuthorizationCodeTokens in project quarkus by quarkusio.
the class OidcProviderClient method getAuthorizationCodeTokens.
private AuthorizationCodeTokens getAuthorizationCodeTokens(HttpResponse<Buffer> resp) {
JsonObject json = getJsonObject(resp);
final String idToken = json.getString(OidcConstants.ID_TOKEN_VALUE);
final String accessToken = json.getString(OidcConstants.ACCESS_TOKEN_VALUE);
final String refreshToken = json.getString(OidcConstants.REFRESH_TOKEN_VALUE);
return new AuthorizationCodeTokens(idToken, accessToken, refreshToken);
}
use of io.quarkus.oidc.AuthorizationCodeTokens in project quarkus by quarkusio.
the class CodeAuthenticationMechanism method reAuthenticate.
private Uni<SecurityIdentity> reAuthenticate(Cookie sessionCookie, RoutingContext context, IdentityProviderManager identityProviderManager, TenantConfigContext configContext) {
context.put(TenantConfigContext.class.getName(), configContext);
return resolver.getTokenStateManager().getTokens(context, configContext.oidcConfig, sessionCookie.getValue(), getTokenStateRequestContext).chain(new Function<AuthorizationCodeTokens, Uni<? extends SecurityIdentity>>() {
@Override
public Uni<? extends SecurityIdentity> apply(AuthorizationCodeTokens session) {
if (isBackChannelLogoutPendingAndValid(configContext, session.getIdToken())) {
return OidcUtils.removeSessionCookie(context, configContext.oidcConfig, sessionCookie.getName(), resolver.getTokenStateManager()).chain(new Function<Void, Uni<? extends SecurityIdentity>>() {
@Override
public Uni<SecurityIdentity> apply(Void t) {
return Uni.createFrom().nullItem();
}
});
}
context.put(OidcConstants.ACCESS_TOKEN_VALUE, session.getAccessToken());
context.put(AuthorizationCodeTokens.class.getName(), session);
return authenticate(identityProviderManager, context, new IdTokenCredential(session.getIdToken(), isInternalIdToken(session.getIdToken(), configContext))).call(new Function<SecurityIdentity, Uni<?>>() {
@Override
public Uni<Void> apply(SecurityIdentity identity) {
if (isLogout(context, configContext)) {
fireEvent(SecurityEvent.Type.OIDC_LOGOUT_RP_INITIATED, identity);
return buildLogoutRedirectUriUni(context, configContext, session.getIdToken());
}
return VOID_UNI;
}
}).onFailure().recoverWithUni(new Function<Throwable, Uni<? extends SecurityIdentity>>() {
@Override
public Uni<? extends SecurityIdentity> apply(Throwable t) {
if (t instanceof AuthenticationRedirectException) {
throw (AuthenticationRedirectException) t;
}
if (!(t instanceof TokenAutoRefreshException)) {
boolean expired = (t.getCause() instanceof InvalidJwtException) && ((InvalidJwtException) t.getCause()).hasErrorCode(ErrorCodes.EXPIRED);
if (!expired) {
LOG.debugf("Authentication failure: %s", t.getCause());
throw new AuthenticationCompletionException(t.getCause());
}
if (!configContext.oidcConfig.token.refreshExpired) {
LOG.debug("Token has expired, token refresh is not allowed");
throw new AuthenticationCompletionException(t.getCause());
}
LOG.debug("Token has expired, trying to refresh it");
return refreshSecurityIdentity(configContext, session.getRefreshToken(), context, identityProviderManager, false, null);
} else {
return refreshSecurityIdentity(configContext, session.getRefreshToken(), context, identityProviderManager, true, ((TokenAutoRefreshException) t).getSecurityIdentity());
}
}
});
}
});
}
use of io.quarkus.oidc.AuthorizationCodeTokens in project quarkus by quarkusio.
the class CodeAuthenticationMechanism method performCodeFlow.
private Uni<SecurityIdentity> performCodeFlow(IdentityProviderManager identityProviderManager, RoutingContext context, TenantConfigContext configContext, MultiMap requestParams, String[] parsedStateCookieValue) {
String userPath = null;
String userQuery = null;
// This is an original redirect from IDP, check if the original request path and query need to be restored
CodeAuthenticationStateBean stateBean = getCodeAuthenticationBean(parsedStateCookieValue, configContext);
if (stateBean != null && stateBean.getRestorePath() != null) {
String restorePath = stateBean.getRestorePath();
int userQueryIndex = restorePath.indexOf("?");
if (userQueryIndex >= 0) {
userPath = restorePath.substring(0, userQueryIndex);
if (userQueryIndex + 1 < restorePath.length()) {
userQuery = restorePath.substring(userQueryIndex + 1);
}
} else {
userPath = restorePath;
}
}
final String finalUserPath = userPath;
final String finalUserQuery = userQuery;
final String code = requestParams.get(OidcConstants.CODE_FLOW_CODE);
Uni<AuthorizationCodeTokens> codeFlowTokensUni = getCodeFlowTokensUni(context, configContext, code, stateBean != null ? stateBean.getCodeVerifier() : null);
return codeFlowTokensUni.onItemOrFailure().transformToUni(new BiFunction<AuthorizationCodeTokens, Throwable, Uni<? extends SecurityIdentity>>() {
@Override
public Uni<SecurityIdentity> apply(final AuthorizationCodeTokens tokens, final Throwable tOuter) {
if (tOuter != null) {
LOG.debugf("Exception during the code to token exchange: %s", tOuter.getMessage());
return Uni.createFrom().failure(new AuthenticationCompletionException(tOuter));
}
boolean internalIdToken = !configContext.oidcConfig.authentication.isIdTokenRequired().orElse(true);
if (tokens.getIdToken() == null) {
if (!internalIdToken) {
return Uni.createFrom().failure(new AuthenticationCompletionException("ID Token is not available"));
} else {
tokens.setIdToken(generateInternalIdToken(configContext.oidcConfig, null));
}
}
context.put(NEW_AUTHENTICATION, Boolean.TRUE);
context.put(OidcConstants.ACCESS_TOKEN_VALUE, tokens.getAccessToken());
context.put(AuthorizationCodeTokens.class.getName(), tokens);
return authenticate(identityProviderManager, context, new IdTokenCredential(tokens.getIdToken(), internalIdToken)).call(new Function<SecurityIdentity, Uni<?>>() {
@Override
public Uni<Void> apply(SecurityIdentity identity) {
if (internalIdToken && configContext.oidcConfig.allowUserInfoCache && configContext.oidcConfig.cacheUserInfoInIdtoken) {
tokens.setIdToken(generateInternalIdToken(configContext.oidcConfig, identity.getAttribute(OidcUtils.USER_INFO_ATTRIBUTE)));
}
return processSuccessfulAuthentication(context, configContext, tokens, identity);
}
}).map(new Function<SecurityIdentity, SecurityIdentity>() {
@Override
public SecurityIdentity apply(SecurityIdentity identity) {
boolean removeRedirectParams = configContext.oidcConfig.authentication.isRemoveRedirectParameters();
if (removeRedirectParams || finalUserPath != null || finalUserQuery != null) {
URI absoluteUri = URI.create(context.request().absoluteURI());
StringBuilder finalUriWithoutQuery = new StringBuilder(buildUri(context, isForceHttps(configContext.oidcConfig), absoluteUri.getAuthority(), (finalUserPath != null ? finalUserPath : absoluteUri.getRawPath())));
if (!removeRedirectParams) {
finalUriWithoutQuery.append('?').append(getRequestParametersAsQuery(absoluteUri, requestParams, configContext.oidcConfig));
}
if (finalUserQuery != null) {
finalUriWithoutQuery.append(!removeRedirectParams ? "" : "?");
finalUriWithoutQuery.append(finalUserQuery);
}
String finalRedirectUri = finalUriWithoutQuery.toString();
LOG.debugf("Final redirect URI: %s", finalRedirectUri);
throw new AuthenticationRedirectException(finalRedirectUri);
} else {
return identity;
}
}
}).onFailure().transform(new Function<Throwable, Throwable>() {
@Override
public Throwable apply(Throwable tInner) {
if (tInner instanceof AuthenticationRedirectException) {
return tInner;
}
return new AuthenticationCompletionException(tInner);
}
});
}
});
}
Aggregations