Search in sources :

Example 1 with InvalidTokenException

use of io.gravitee.am.common.exception.oauth2.InvalidTokenException in project gravitee-access-management by gravitee-io.

the class UserInfoEndpointHandlerTest method shouldNotInvokeUserEndpoint_unknownToken.

@Test
public void shouldNotInvokeUserEndpoint_unknownToken() throws Exception {
    JWT jwt = new JWT();
    jwt.setAud("client-id");
    router.route().order(-1).handler(createOAuth2AuthHandler(oAuth2AuthProvider(new InvalidTokenException())));
    testRequest(HttpMethod.GET, "/userinfo", req -> req.putHeader(HttpHeaders.AUTHORIZATION, "Bearer test-token"), HttpStatusCode.UNAUTHORIZED_401, "Unauthorized", null);
}
Also used : InvalidTokenException(io.gravitee.am.common.exception.oauth2.InvalidTokenException) JWT(io.gravitee.am.common.jwt.JWT) Test(org.junit.Test)

Example 2 with InvalidTokenException

use of io.gravitee.am.common.exception.oauth2.InvalidTokenException in project gravitee-access-management by gravitee-io.

the class UserInfoEndpoint method handle.

@Override
public void handle(RoutingContext context) {
    JWT accessToken = context.get(ConstantKeys.TOKEN_CONTEXT_KEY);
    Client client = context.get(ConstantKeys.CLIENT_CONTEXT_KEY);
    String subject = accessToken.getSub();
    userService.findById(subject).switchIfEmpty(Maybe.error(new InvalidTokenException("No user found for this token"))).flatMapSingle(user -> enhance(user, accessToken)).map(user -> processClaims(user, accessToken)).flatMap(claims -> {
        if (!expectSignedOrEncryptedUserInfo(client)) {
            context.response().putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
            return Single.just(Json.encodePrettily(claims));
        } else {
            context.response().putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JWT);
            JWT jwt = new JWT(claims);
            jwt.setIss(openIDDiscoveryService.getIssuer(UriBuilderRequest.resolveProxyRequest(context)));
            jwt.setSub(accessToken.getSub());
            jwt.setAud(accessToken.getAud());
            jwt.setIat(new Date().getTime() / 1000l);
            jwt.setExp(accessToken.getExp() / 1000l);
            return // Sign if needed, else return unsigned JWT
            jwtService.encodeUserinfo(jwt, client).flatMap(// Encrypt if needed, else return JWT
            userinfo -> jweService.encryptUserinfo(userinfo, client));
        }
    }).subscribe(buffer -> context.response().putHeader(HttpHeaders.CACHE_CONTROL, "no-store").putHeader(HttpHeaders.PRAGMA, "no-cache").end(buffer), error -> context.fail(error));
}
Also used : IDTokenService(io.gravitee.am.gateway.handler.oidc.service.idtoken.IDTokenService) Json(io.vertx.core.json.Json) java.util(java.util) HttpHeaders(io.gravitee.common.http.HttpHeaders) Client(io.gravitee.am.model.oidc.Client) Role(io.gravitee.am.model.Role) UserService(io.gravitee.am.service.UserService) Maybe(io.reactivex.Maybe) ConstantKeys(io.gravitee.am.common.utils.ConstantKeys) InvalidTokenException(io.gravitee.am.common.exception.oauth2.InvalidTokenException) Single(io.reactivex.Single) ClaimsRequest(io.gravitee.am.gateway.handler.oidc.service.request.ClaimsRequest) InvalidRequestException(io.gravitee.am.common.exception.oauth2.InvalidRequestException) JWTService(io.gravitee.am.gateway.handler.common.jwt.JWTService) User(io.gravitee.am.model.User) StandardClaims(io.gravitee.am.common.oidc.StandardClaims) JWT(io.gravitee.am.common.jwt.JWT) JWEService(io.gravitee.am.gateway.handler.oidc.service.jwe.JWEService) Optional.ofNullable(java.util.Optional.ofNullable) Scope(io.gravitee.am.common.oidc.Scope) RoutingContext(io.vertx.reactivex.ext.web.RoutingContext) Collectors(java.util.stream.Collectors) UriBuilderRequest(io.gravitee.am.gateway.handler.common.vertx.utils.UriBuilderRequest) MediaType(io.gravitee.common.http.MediaType) CustomClaims(io.gravitee.am.common.oidc.CustomClaims) Handler(io.vertx.core.Handler) OpenIDDiscoveryService(io.gravitee.am.gateway.handler.oidc.service.discovery.OpenIDDiscoveryService) InvalidTokenException(io.gravitee.am.common.exception.oauth2.InvalidTokenException) JWT(io.gravitee.am.common.jwt.JWT) Client(io.gravitee.am.model.oidc.Client)

Example 3 with InvalidTokenException

use of io.gravitee.am.common.exception.oauth2.InvalidTokenException in project gravitee-access-management by gravitee-io.

the class AuthenticationRequestServiceTest method shouldNotUpdateStatus_InvalidSignature.

@Test
public void shouldNotUpdateStatus_InvalidSignature() {
    final String STATE = "state";
    final String EXTERNAL_ID = "externalId";
    final boolean requestValidated = new Random().nextBoolean();
    AuthenticationDeviceNotifierProvider provider = mock(AuthenticationDeviceNotifierProvider.class);
    when(notifierManager.getAuthDeviceNotifierProviders()).thenReturn(List.of(provider));
    when(provider.extractUserResponse(any())).thenReturn(Single.just(Optional.of(new ADUserResponse(EXTERNAL_ID, STATE, requestValidated))));
    final JWT stateJwt = new JWT();
    stateJwt.setJti(EXTERNAL_ID);
    when(this.jwtService.decode(STATE)).thenReturn(Single.just(stateJwt));
    when(this.clientService.findByClientId(any())).thenReturn(Maybe.just(new Client()));
    when(this.jwtService.decodeAndVerify(anyString(), any(Client.class))).thenReturn(Single.error(new InvalidTokenException()));
    final ADCallbackContext context = new ADCallbackContext(MultiMap.caseInsensitiveMultiMap(), MultiMap.caseInsensitiveMultiMap());
    final TestObserver<Void> observer = this.service.validateUserResponse(context).test();
    observer.awaitTerminalEvent();
    observer.assertError(InvalidRequestException.class);
    verify(clientService).findByClientId(any());
    verify(requestRepository, never()).updateStatus(any(), any());
}
Also used : InvalidTokenException(io.gravitee.am.common.exception.oauth2.InvalidTokenException) ADCallbackContext(io.gravitee.am.authdevice.notifier.api.model.ADCallbackContext) ADUserResponse(io.gravitee.am.authdevice.notifier.api.model.ADUserResponse) JWT(io.gravitee.am.common.jwt.JWT) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) Client(io.gravitee.am.model.oidc.Client) AuthenticationDeviceNotifierProvider(io.gravitee.am.authdevice.notifier.api.AuthenticationDeviceNotifierProvider) Test(org.junit.Test)

Example 4 with InvalidTokenException

use of io.gravitee.am.common.exception.oauth2.InvalidTokenException in project gravitee-access-management by gravitee-io.

the class OAuth2AuthHandlerImpl method handle.

@Override
public void handle(RoutingContext context) {
    parseAuthorization(context, parseHandler -> {
        if (parseHandler.failed()) {
            processException(context, parseHandler.cause());
            return;
        }
        final String jwtToken = parseHandler.result();
        // set raw token to the current context
        if (extractRawToken) {
            context.put(ConstantKeys.RAW_TOKEN_CONTEXT_KEY, jwtToken);
        }
        oAuth2AuthProvider.decodeToken(jwtToken, offlineVerification, handler -> {
            if (handler.failed()) {
                processException(context, handler.cause());
                return;
            }
            OAuth2AuthResponse response = handler.result();
            JWT token = response.getToken();
            Client client = response.getClient();
            // set token to the current context
            if (extractToken) {
                context.put(ConstantKeys.TOKEN_CONTEXT_KEY, token);
            }
            // set client to the current context
            if (extractClient) {
                context.put(ConstantKeys.CLIENT_CONTEXT_KEY, client);
            }
            // check if current subject can access its own resources
            if (selfResource) {
                final String resourceId = context.request().getParam(resourceParameter);
                if (resourceId != null && resourceId.equals(token.getSub())) {
                    if (resourceRequiredScope == null || token.hasScope(resourceRequiredScope)) {
                        context.next();
                        return;
                    }
                }
            }
            if (forceEndUserToken) {
                if (token.getSub().equals(token.getAud())) {
                    // token for end user must not contain clientId as subject
                    processException(context, new InvalidTokenException("The access token was not issued for an End-User"));
                    return;
                }
            }
            if (forceClientToken) {
                if (!token.getSub().equals(token.getAud())) {
                    // token for end user must not contain clientId as subject
                    processException(context, new InvalidTokenException("The access token was not issued for a Client"));
                    return;
                }
            }
            // check required scope
            if (requiredScope != null) {
                if (!token.hasScope(requiredScope)) {
                    processException(context, new InsufficientScopeException("Invalid access token scopes. The access token should have at least '" + requiredScope + "' scope"));
                    return;
                }
            }
            context.next();
        });
    });
}
Also used : OAuth2AuthResponse(io.gravitee.am.gateway.handler.common.vertx.web.auth.handler.OAuth2AuthResponse) InvalidTokenException(io.gravitee.am.common.exception.oauth2.InvalidTokenException) InsufficientScopeException(io.gravitee.am.common.exception.oauth2.InsufficientScopeException) JWT(io.gravitee.am.common.jwt.JWT) Client(io.gravitee.am.model.oidc.Client)

Example 5 with InvalidTokenException

use of io.gravitee.am.common.exception.oauth2.InvalidTokenException in project gravitee-access-management by gravitee-io.

the class IntrospectionTokenServiceImpl method introspect.

@Override
public Single<JWT> introspect(String token, boolean offlineVerification) {
    return jwtService.decode(token).flatMapMaybe(jwt -> clientService.findByDomainAndClientId(jwt.getDomain(), jwt.getAud())).switchIfEmpty(Maybe.error(new InvalidTokenException("Invalid or unknown client for this token"))).flatMapSingle(client -> jwtService.decodeAndVerify(token, client)).flatMap(jwt -> {
        // or if the token has just been created (could not be in database so far because of async database storing process delay)
        if (offlineVerification || Instant.now().isBefore(Instant.ofEpochSecond(jwt.getIat() + OFFLINE_VERIFICATION_TIMER_SECONDS))) {
            return Single.just(jwt);
        }
        // check if token is not revoked
        return accessTokenRepository.findByToken(jwt.getJti()).switchIfEmpty(Single.error(new InvalidTokenException("The token is invalid", "Token with JTI [" + jwt.getJti() + "] not found in the database", jwt))).map(accessToken -> {
            if (accessToken.getExpireAt().before(new Date())) {
                throw new InvalidTokenException("The token expired", "Token with JTI [" + jwt.getJti() + "] is expired", jwt);
            }
            return jwt;
        });
    }).onErrorResumeNext(ex -> {
        if (ex instanceof JWTException) {
            LOGGER.debug("An error occurs while decoding JWT access token : {}", token, ex);
            return Single.error(new InvalidTokenException(ex.getMessage(), ex));
        }
        if (ex instanceof InvalidTokenException) {
            InvalidTokenException invalidTokenException = (InvalidTokenException) ex;
            String details = invalidTokenException.getDetails();
            JWT jwt = invalidTokenException.getJwt();
            LOGGER.debug("An error occurs while checking JWT access token validity: {}\n\t - details: {}\n\t - decoded jwt: {}", token, details != null ? details : "none", jwt != null ? jwt.toString() : "{}", invalidTokenException);
        }
        return Single.error(ex);
    });
}
Also used : AccessTokenRepository(io.gravitee.am.repository.oauth2.api.AccessTokenRepository) Logger(org.slf4j.Logger) JWT(io.gravitee.am.common.jwt.JWT) Date(java.util.Date) Maybe(io.reactivex.Maybe) LoggerFactory(org.slf4j.LoggerFactory) Autowired(org.springframework.beans.factory.annotation.Autowired) InvalidTokenException(io.gravitee.am.common.exception.oauth2.InvalidTokenException) Instant(java.time.Instant) Single(io.reactivex.Single) JWTException(io.gravitee.am.common.exception.jwt.JWTException) IntrospectionTokenService(io.gravitee.am.gateway.handler.common.oauth2.IntrospectionTokenService) JWTService(io.gravitee.am.gateway.handler.common.jwt.JWTService) Lazy(org.springframework.context.annotation.Lazy) ClientSyncService(io.gravitee.am.gateway.handler.common.client.ClientSyncService) InvalidTokenException(io.gravitee.am.common.exception.oauth2.InvalidTokenException) JWTException(io.gravitee.am.common.exception.jwt.JWTException) JWT(io.gravitee.am.common.jwt.JWT) Date(java.util.Date)

Aggregations

InvalidTokenException (io.gravitee.am.common.exception.oauth2.InvalidTokenException)5 JWT (io.gravitee.am.common.jwt.JWT)5 Client (io.gravitee.am.model.oidc.Client)3 JWTService (io.gravitee.am.gateway.handler.common.jwt.JWTService)2 Maybe (io.reactivex.Maybe)2 Single (io.reactivex.Single)2 Test (org.junit.Test)2 AuthenticationDeviceNotifierProvider (io.gravitee.am.authdevice.notifier.api.AuthenticationDeviceNotifierProvider)1 ADCallbackContext (io.gravitee.am.authdevice.notifier.api.model.ADCallbackContext)1 ADUserResponse (io.gravitee.am.authdevice.notifier.api.model.ADUserResponse)1 JWTException (io.gravitee.am.common.exception.jwt.JWTException)1 InsufficientScopeException (io.gravitee.am.common.exception.oauth2.InsufficientScopeException)1 InvalidRequestException (io.gravitee.am.common.exception.oauth2.InvalidRequestException)1 CustomClaims (io.gravitee.am.common.oidc.CustomClaims)1 Scope (io.gravitee.am.common.oidc.Scope)1 StandardClaims (io.gravitee.am.common.oidc.StandardClaims)1 ConstantKeys (io.gravitee.am.common.utils.ConstantKeys)1 ClientSyncService (io.gravitee.am.gateway.handler.common.client.ClientSyncService)1 IntrospectionTokenService (io.gravitee.am.gateway.handler.common.oauth2.IntrospectionTokenService)1 UriBuilderRequest (io.gravitee.am.gateway.handler.common.vertx.utils.UriBuilderRequest)1