Search in sources :

Example 1 with AuthorizationCodeTokens

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));
}
Also used : Cookie(io.vertx.core.http.Cookie) ServerCookie(io.vertx.core.http.impl.ServerCookie) AuthorizationCodeTokens(io.quarkus.oidc.AuthorizationCodeTokens)

Example 2 with AuthorizationCodeTokens

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();
}
Also used : InvalidJwtException(org.jose4j.jwt.consumer.InvalidJwtException) RefreshToken(io.quarkus.oidc.RefreshToken) QuarkusSecurityIdentity(io.quarkus.security.runtime.QuarkusSecurityIdentity) JwtClaims(org.jose4j.jwt.JwtClaims) AuthenticationFailedException(io.quarkus.security.AuthenticationFailedException) Builder(io.quarkus.security.runtime.QuarkusSecurityIdentity.Builder) AuthorizationCodeTokens(io.quarkus.oidc.AuthorizationCodeTokens) AccessTokenCredential(io.quarkus.oidc.AccessTokenCredential) JsonWebToken(org.eclipse.microprofile.jwt.JsonWebToken) OidcTenantConfig(io.quarkus.oidc.OidcTenantConfig)

Example 3 with AuthorizationCodeTokens

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);
}
Also used : JsonObject(io.vertx.core.json.JsonObject) AuthorizationCodeTokens(io.quarkus.oidc.AuthorizationCodeTokens)

Example 4 with AuthorizationCodeTokens

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());
                    }
                }
            });
        }
    });
}
Also used : InvalidJwtException(org.jose4j.jwt.consumer.InvalidJwtException) AuthorizationCodeTokens(io.quarkus.oidc.AuthorizationCodeTokens) SecurityIdentity(io.quarkus.security.identity.SecurityIdentity) Uni(io.smallrye.mutiny.Uni) BiFunction(java.util.function.BiFunction) Function(java.util.function.Function) AuthenticationRedirectException(io.quarkus.security.AuthenticationRedirectException) AuthenticationCompletionException(io.quarkus.security.AuthenticationCompletionException) IdTokenCredential(io.quarkus.oidc.IdTokenCredential)

Example 5 with AuthorizationCodeTokens

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);
                }
            });
        }
    });
}
Also used : AuthorizationCodeTokens(io.quarkus.oidc.AuthorizationCodeTokens) URI(java.net.URI) SecurityIdentity(io.quarkus.security.identity.SecurityIdentity) Uni(io.smallrye.mutiny.Uni) BiFunction(java.util.function.BiFunction) Function(java.util.function.Function) AuthenticationRedirectException(io.quarkus.security.AuthenticationRedirectException) AuthenticationCompletionException(io.quarkus.security.AuthenticationCompletionException) IdTokenCredential(io.quarkus.oidc.IdTokenCredential)

Aggregations

AuthorizationCodeTokens (io.quarkus.oidc.AuthorizationCodeTokens)5 IdTokenCredential (io.quarkus.oidc.IdTokenCredential)2 AuthenticationCompletionException (io.quarkus.security.AuthenticationCompletionException)2 AuthenticationRedirectException (io.quarkus.security.AuthenticationRedirectException)2 SecurityIdentity (io.quarkus.security.identity.SecurityIdentity)2 Uni (io.smallrye.mutiny.Uni)2 BiFunction (java.util.function.BiFunction)2 Function (java.util.function.Function)2 InvalidJwtException (org.jose4j.jwt.consumer.InvalidJwtException)2 AccessTokenCredential (io.quarkus.oidc.AccessTokenCredential)1 OidcTenantConfig (io.quarkus.oidc.OidcTenantConfig)1 RefreshToken (io.quarkus.oidc.RefreshToken)1 AuthenticationFailedException (io.quarkus.security.AuthenticationFailedException)1 QuarkusSecurityIdentity (io.quarkus.security.runtime.QuarkusSecurityIdentity)1 Builder (io.quarkus.security.runtime.QuarkusSecurityIdentity.Builder)1 Cookie (io.vertx.core.http.Cookie)1 ServerCookie (io.vertx.core.http.impl.ServerCookie)1 JsonObject (io.vertx.core.json.JsonObject)1 URI (java.net.URI)1 JsonWebToken (org.eclipse.microprofile.jwt.JsonWebToken)1