Search in sources :

Example 21 with InvalidRequestException

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

the class OAuth2AuthHandlerImpl method parseAuthorization.

private void parseAuthorization(RoutingContext context, Handler<AsyncResult<String>> handler) {
    final HttpServerRequest request = context.request();
    final String authorization = request.headers().get(io.vertx.core.http.HttpHeaders.AUTHORIZATION);
    String authToken = null;
    try {
        if (authorization != null) {
            // authorization header has been found check the value
            int idx = authorization.indexOf(' ');
            if (idx <= 0) {
                handler.handle(Future.failedFuture(new InvalidRequestException("The access token must be sent using the Authorization header field")));
                return;
            }
            if (!BEARER.equalsIgnoreCase(authorization.substring(0, idx))) {
                handler.handle(Future.failedFuture(new HttpException(401)));
                return;
            }
            authToken = authorization.substring(idx + 1);
        } else {
            // if no authorization header found, check authorization in body
            authToken = request.getParam(ACCESS_TOKEN);
        }
        if (authToken == null) {
            handler.handle(Future.failedFuture(new HttpException(401)));
            return;
        }
        handler.handle(Future.succeededFuture(authToken));
    } catch (RuntimeException e) {
        handler.handle(Future.failedFuture(e));
    }
}
Also used : HttpServerRequest(io.vertx.reactivex.core.http.HttpServerRequest) InvalidRequestException(io.gravitee.am.common.exception.oauth2.InvalidRequestException) HttpException(io.vertx.ext.web.handler.HttpException)

Example 22 with InvalidRequestException

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

the class AuthorizationCodeTokenGranter method parseRequest.

@Override
protected Single<TokenRequest> parseRequest(TokenRequest tokenRequest, Client client) {
    MultiValueMap<String, String> parameters = tokenRequest.parameters();
    String code = parameters.getFirst(Parameters.CODE);
    if (code == null || code.isEmpty()) {
        return Single.error(new InvalidRequestException("Missing parameter: code"));
    }
    return super.parseRequest(tokenRequest, client).flatMap(tokenRequest1 -> authorizationCodeService.remove(code, client).flatMap(authorizationCode -> authenticationFlowContextService.removeContext(authorizationCode.getTransactionId(), authorizationCode.getContextVersion()).onErrorResumeNext(error -> (exitOnError) ? Maybe.error(error) : Maybe.just(new AuthenticationFlowContext())).map(ctx -> {
        checkRedirectUris(tokenRequest1, authorizationCode);
        checkPKCE(tokenRequest1, authorizationCode);
        // set resource owner
        tokenRequest1.setSubject(authorizationCode.getSubject());
        // set original scopes
        tokenRequest1.setScopes(authorizationCode.getScopes());
        // set authorization code initial request parameters (step1 of authorization code flow)
        if (authorizationCode.getRequestParameters() != null) {
            authorizationCode.getRequestParameters().forEach((key, value) -> tokenRequest1.parameters().putIfAbsent(key, value));
        }
        // set decoded authorization code to the current request
        Map<String, Object> decodedAuthorizationCode = new HashMap<>();
        decodedAuthorizationCode.put("code", authorizationCode.getCode());
        decodedAuthorizationCode.put("transactionId", authorizationCode.getTransactionId());
        tokenRequest1.setAuthorizationCode(decodedAuthorizationCode);
        // store only the AuthenticationFlowContext.data attributes in order to simplify EL templating
        // and provide an up to date set of data if the enrichAuthFlow Policy ius used multiple time in a step
        // {#context.attributes['authFlow']['entry']}
        tokenRequest1.getContext().put(ConstantKeys.AUTH_FLOW_CONTEXT_ATTRIBUTES_KEY, ctx.getData());
        return tokenRequest1;
    })).toSingle());
}
Also used : CodeChallengeMethod(io.gravitee.am.common.oauth2.CodeChallengeMethod) Client(io.gravitee.am.model.oidc.Client) MultiValueMap(io.gravitee.common.util.MultiValueMap) Maybe(io.reactivex.Maybe) LoggerFactory(org.slf4j.LoggerFactory) ConstantKeys(io.gravitee.am.common.utils.ConstantKeys) HashMap(java.util.HashMap) TokenService(io.gravitee.am.gateway.handler.oauth2.service.token.TokenService) Single(io.reactivex.Single) InvalidRequestException(io.gravitee.am.common.exception.oauth2.InvalidRequestException) TokenRequestResolver(io.gravitee.am.gateway.handler.oauth2.service.request.TokenRequestResolver) Map(java.util.Map) User(io.gravitee.am.model.User) PKCEUtils(io.gravitee.am.gateway.handler.oauth2.service.pkce.PKCEUtils) InvalidGrantException(io.gravitee.am.gateway.handler.oauth2.exception.InvalidGrantException) AuthenticationFlowContextService(io.gravitee.am.service.AuthenticationFlowContextService) GrantType(io.gravitee.am.common.oauth2.GrantType) Logger(org.slf4j.Logger) UserAuthenticationManager(io.gravitee.am.gateway.handler.common.auth.user.UserAuthenticationManager) TokenRequest(io.gravitee.am.gateway.handler.oauth2.service.request.TokenRequest) AbstractTokenGranter(io.gravitee.am.gateway.handler.oauth2.service.granter.AbstractTokenGranter) AuthorizationCodeService(io.gravitee.am.gateway.handler.oauth2.service.code.AuthorizationCodeService) AuthorizationCode(io.gravitee.am.repository.oauth2.model.AuthorizationCode) Environment(org.springframework.core.env.Environment) AuthenticationFlowContext(io.gravitee.am.model.AuthenticationFlowContext) Parameters(io.gravitee.am.common.oauth2.Parameters) AuthenticationFlowContext(io.gravitee.am.model.AuthenticationFlowContext) InvalidRequestException(io.gravitee.am.common.exception.oauth2.InvalidRequestException) MultiValueMap(io.gravitee.common.util.MultiValueMap) HashMap(java.util.HashMap) Map(java.util.Map)

Example 23 with InvalidRequestException

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

the class RefreshTokenGranter method parseRequest.

@Override
protected Single<TokenRequest> parseRequest(TokenRequest tokenRequest, Client client) {
    String refreshToken = tokenRequest.parameters().getFirst(Parameters.REFRESH_TOKEN);
    if (refreshToken == null || refreshToken.isEmpty()) {
        return Single.error(new InvalidRequestException("A refresh token must be supplied."));
    }
    return super.parseRequest(tokenRequest, client).flatMap(tokenRequest1 -> getTokenService().refresh(refreshToken, tokenRequest, client).map(refreshToken1 -> {
        // set resource owner
        if (refreshToken1.getSubject() != null) {
            tokenRequest1.setSubject(refreshToken1.getSubject());
        }
        // set scopes
        // The requested scope MUST NOT include any scope
        // not originally granted by the resource owner, and if omitted is
        // treated as equal to the scope originally granted by the resource owner.
        final Set<String> originalScopes = (refreshToken1.getScope() != null ? new HashSet(Arrays.asList(refreshToken1.getScope().split("\\s+"))) : null);
        final Set<String> requestedScopes = tokenRequest1.getScopes();
        if (requestedScopes == null || requestedScopes.isEmpty()) {
            tokenRequest1.setScopes(originalScopes);
        } else if (originalScopes != null && !originalScopes.isEmpty()) {
            Set<String> filteredScopes = requestedScopes.stream().filter(requestedScope -> originalScopes.contains(requestedScope)).collect(Collectors.toSet());
            tokenRequest1.setScopes(filteredScopes);
        }
        // set decoded refresh token to the current request
        tokenRequest1.setRefreshToken(refreshToken1.getAdditionalInformation());
        return tokenRequest1;
    }));
}
Also used : InvalidGrantException(io.gravitee.am.gateway.handler.oauth2.exception.InvalidGrantException) Arrays(java.util.Arrays) GrantType(io.gravitee.am.common.oauth2.GrantType) UserAuthenticationManager(io.gravitee.am.gateway.handler.common.auth.user.UserAuthenticationManager) TokenRequest(io.gravitee.am.gateway.handler.oauth2.service.request.TokenRequest) Client(io.gravitee.am.model.oidc.Client) Maybe(io.reactivex.Maybe) Set(java.util.Set) AbstractTokenGranter(io.gravitee.am.gateway.handler.oauth2.service.granter.AbstractTokenGranter) TokenService(io.gravitee.am.gateway.handler.oauth2.service.token.TokenService) Single(io.reactivex.Single) Collectors(java.util.stream.Collectors) HashSet(java.util.HashSet) InvalidRequestException(io.gravitee.am.common.exception.oauth2.InvalidRequestException) TokenRequestResolver(io.gravitee.am.gateway.handler.oauth2.service.request.TokenRequestResolver) User(io.gravitee.am.model.User) Parameters(io.gravitee.am.common.oauth2.Parameters) Set(java.util.Set) HashSet(java.util.HashSet) InvalidRequestException(io.gravitee.am.common.exception.oauth2.InvalidRequestException) HashSet(java.util.HashSet)

Example 24 with InvalidRequestException

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

the class CibaAuthenticationRequestResolver method validateLoginHintToken.

private Single<CibaAuthenticationRequest> validateLoginHintToken(CibaAuthenticationRequest authRequest, JWT jwt) {
    try {
        final Date expirationTime = jwt.getJWTClaimsSet().getExpirationTime();
        if (expirationTime != null) {
            evaluateExp(expirationTime.toInstant().getEpochSecond(), Instant.now(), 0);
        }
        final JSONObject subIdObject = jwt.getJWTClaimsSet().getJSONObjectClaim("sub_id");
        /*
                sub_id is an object specifying the field identifying the user (through format entry)
                Supported format : email and username
                {
                  "sub_id": {
                    "format": "email",
                    "email": "user@acme.fr"
                  }
                }
             */
        final FilterCriteria criteria = new FilterCriteria();
        criteria.setQuoteFilterValue(false);
        final String field = subIdObject.getAsString("format");
        if (!"email".equals(field) && !"username".equals(field)) {
            return Single.error(new InvalidRequestException("Invalid hint, only email and username are supported"));
        }
        criteria.setFilterName(field);
        criteria.setFilterValue(subIdObject.getAsString(field));
        return userService.findByDomainAndCriteria(domain.getId(), criteria).flatMap(users -> {
            if (users.size() != 1) {
                LOGGER.warn("login_hint_token match multiple users or no one");
                return Single.error(new InvalidRequestException("Invalid hint"));
            }
            authRequest.setSubject(users.get(0).getId());
            return Single.just(authRequest);
        });
    } catch (ExpiredJWTException e) {
        return Single.error(new ExpiredLoginHintTokenException("login_token_hint expired"));
    } catch (ParseException e) {
        // should never happen
        LOGGER.warn("login_hint_token can't be read", e);
        return Single.error(new ExpiredLoginHintTokenException("invalid login_token_hint"));
    }
}
Also used : JSONObject(net.minidev.json.JSONObject) ExpiredLoginHintTokenException(io.gravitee.am.common.exception.oauth2.ExpiredLoginHintTokenException) ExpiredJWTException(io.gravitee.am.common.exception.jwt.ExpiredJWTException) InvalidRequestException(io.gravitee.am.common.exception.oauth2.InvalidRequestException) FilterCriteria(io.gravitee.am.repository.management.api.search.FilterCriteria) ParseException(java.text.ParseException) Date(java.util.Date)

Example 25 with InvalidRequestException

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

the class AuthorizationRequestParseIdTokenHintHandler method handle.

@Override
public void handle(RoutingContext routingContext) {
    final Client client = routingContext.get(ConstantKeys.CLIENT_CONTEXT_KEY);
    final String idTokenHint = getOAuthParameter(routingContext, Parameters.ID_TOKEN_HINT);
    final String prompt = getOAuthParameter(routingContext, Parameters.PROMPT);
    // if no id_token_hint parameter, continue;
    if (idTokenHint == null) {
        routingContext.next();
        return;
    }
    // id_token_hint parameter should be present when prompt=none is used, if not respond with invalid_request exception
    if (prompt == null) {
        throw new InvalidRequestException("prompt parameter must be present when id_token_hint is used");
    }
    // retrieve prompt values (prompt parameter is a space delimited, case sensitive list of ASCII string values)
    // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
    List<String> promptValues = Arrays.asList(prompt.split("\\s+"));
    if (!promptValues.contains("none")) {
        throw new InvalidRequestException("prompt=none must be present when id_token_hint is used");
    }
    // if client has not enabled this option, continue
    if (!client.isSilentReAuthentication()) {
        routingContext.next();
        return;
    }
    // process silent re-authentication
    extractUser(idTokenHint, client, h -> {
        if (h.failed()) {
            // if no user, continue
            logger.debug("An error has occurred when extracting user from the ID token", h.cause());
            routingContext.next();
            return;
        }
        // set user in context and continue
        io.gravitee.am.model.User endUser = h.result();
        if (routingContext.user() == null) {
            routingContext.setUser(User.newInstance(new io.gravitee.am.gateway.handler.common.vertx.web.auth.user.User(endUser)));
            routingContext.next();
            return;
        }
        // if current user is not the same as the id token one, return login_required error
        io.gravitee.am.model.User loggedInUser = ((io.gravitee.am.gateway.handler.common.vertx.web.auth.user.User) routingContext.user().getDelegate()).getUser();
        if (!loggedInUser.getId().equals(endUser.getId())) {
            logger.debug("The End-User identified by the ID Token is not the same as the logged in End-User.");
            routingContext.fail(new LoginRequiredException("Login required"));
        } else {
            routingContext.next();
        }
    });
}
Also used : LoginRequiredException(io.gravitee.am.gateway.handler.oauth2.exception.LoginRequiredException) User(io.vertx.reactivex.ext.auth.User) InvalidRequestException(io.gravitee.am.common.exception.oauth2.InvalidRequestException) Client(io.gravitee.am.model.oidc.Client)

Aggregations

InvalidRequestException (io.gravitee.am.common.exception.oauth2.InvalidRequestException)37 Client (io.gravitee.am.model.oidc.Client)20 ConstantKeys (io.gravitee.am.common.utils.ConstantKeys)10 User (io.gravitee.am.model.User)9 RoutingContext (io.vertx.reactivex.ext.web.RoutingContext)9 JsonObject (io.vertx.core.json.JsonObject)8 Domain (io.gravitee.am.model.Domain)6 ParseException (java.text.ParseException)6 Date (java.util.Date)6 Parameters (io.gravitee.am.common.oauth2.Parameters)5 DefaultUser (io.gravitee.am.identityprovider.api.DefaultUser)5 Handler (io.vertx.core.Handler)5 Collectors (java.util.stream.Collectors)5 Logger (org.slf4j.Logger)5 LoggerFactory (org.slf4j.LoggerFactory)5 JWTClaimsSet (com.nimbusds.jwt.JWTClaimsSet)4 AsyncResult (io.vertx.core.AsyncResult)4 Future (io.vertx.core.Future)4 HttpServerRequest (io.vertx.reactivex.core.http.HttpServerRequest)4 StandardCharsets (java.nio.charset.StandardCharsets)4