Search in sources :

Example 1 with AuthenticationRedirectException

use of io.quarkus.security.AuthenticationRedirectException in project quarkus by quarkusio.

the class CodeAuthenticationMechanism method processRedirectFromOidc.

private Uni<SecurityIdentity> processRedirectFromOidc(RoutingContext context, OidcTenantConfig oidcTenantConfig, IdentityProviderManager identityProviderManager, Cookie stateCookie, MultiMap requestParams) {
    String[] parsedStateCookieValue = COOKIE_PATTERN.split(stateCookie.getValue());
    OidcUtils.removeCookie(context, oidcTenantConfig, stateCookie.getName());
    if (!isStateValid(requestParams, parsedStateCookieValue[0])) {
        return Uni.createFrom().failure(new AuthenticationCompletionException());
    }
    if (requestParams.contains(OidcConstants.CODE_FLOW_CODE)) {
        // start a new session by starting the code flow dance
        Uni<TenantConfigContext> resolvedContext = resolver.resolveContext(context);
        return resolvedContext.onItem().transformToUni(new Function<TenantConfigContext, Uni<? extends SecurityIdentity>>() {

            @Override
            public Uni<SecurityIdentity> apply(TenantConfigContext tenantContext) {
                return performCodeFlow(identityProviderManager, context, tenantContext, requestParams, parsedStateCookieValue);
            }
        });
    } else if (requestParams.contains(OidcConstants.CODE_FLOW_ERROR)) {
        OidcUtils.removeCookie(context, oidcTenantConfig, stateCookie.getName());
        String error = requestParams.get(OidcConstants.CODE_FLOW_ERROR);
        String errorDescription = requestParams.get(OidcConstants.CODE_FLOW_ERROR_DESCRIPTION);
        LOG.debugf("Authentication has failed, error: %s, description: %s", error, errorDescription);
        if (oidcTenantConfig.authentication.errorPath.isPresent()) {
            URI absoluteUri = URI.create(context.request().absoluteURI());
            StringBuilder errorUri = new StringBuilder(buildUri(context, isForceHttps(oidcTenantConfig), absoluteUri.getAuthority(), oidcTenantConfig.authentication.errorPath.get()));
            errorUri.append('?').append(getRequestParametersAsQuery(absoluteUri, requestParams, oidcTenantConfig));
            String finalErrorUri = errorUri.toString();
            LOG.debugf("Error URI: %s", finalErrorUri);
            return Uni.createFrom().failure(new AuthenticationRedirectException(finalErrorUri));
        } else {
            return Uni.createFrom().failure(new AuthenticationCompletionException());
        }
    } else {
        LOG.debug("State cookie is present but neither 'code' nor 'error' query parameter is returned");
        return Uni.createFrom().failure(new AuthenticationCompletionException());
    }
}
Also used : SecurityIdentity(io.quarkus.security.identity.SecurityIdentity) Uni(io.smallrye.mutiny.Uni) AuthenticationRedirectException(io.quarkus.security.AuthenticationRedirectException) AuthenticationCompletionException(io.quarkus.security.AuthenticationCompletionException) URI(java.net.URI)

Example 2 with AuthenticationRedirectException

use of io.quarkus.security.AuthenticationRedirectException in project quarkus-resteasy-problem by TietoEVRY.

the class AuthenticationRedirectExceptionMapperTest method shouldProduceHttp302WithAllNeededHeaders.

@Test
void shouldProduceHttp302WithAllNeededHeaders() {
    AuthenticationRedirectException exception = new AuthenticationRedirectException("/login");
    Response response = mapper.toResponse(exception);
    assertThat(response.getStatus()).isEqualTo(302);
    assertThat(response.getHeaderString(HttpHeaders.LOCATION)).isEqualTo("/login");
    assertThat(response.getHeaderString(HttpHeaders.CACHE_CONTROL)).isEqualTo("no-store");
    assertThat(response.getHeaderString("Pragma")).isEqualTo("no-cache");
}
Also used : Response(javax.ws.rs.core.Response) AuthenticationRedirectException(io.quarkus.security.AuthenticationRedirectException) Test(org.junit.jupiter.api.Test)

Example 3 with AuthenticationRedirectException

use of io.quarkus.security.AuthenticationRedirectException 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 4 with AuthenticationRedirectException

use of io.quarkus.security.AuthenticationRedirectException 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

AuthenticationRedirectException (io.quarkus.security.AuthenticationRedirectException)4 AuthenticationCompletionException (io.quarkus.security.AuthenticationCompletionException)3 SecurityIdentity (io.quarkus.security.identity.SecurityIdentity)3 Uni (io.smallrye.mutiny.Uni)3 AuthorizationCodeTokens (io.quarkus.oidc.AuthorizationCodeTokens)2 IdTokenCredential (io.quarkus.oidc.IdTokenCredential)2 URI (java.net.URI)2 BiFunction (java.util.function.BiFunction)2 Function (java.util.function.Function)2 Response (javax.ws.rs.core.Response)1 InvalidJwtException (org.jose4j.jwt.consumer.InvalidJwtException)1 Test (org.junit.jupiter.api.Test)1