/** * Copyright (C) 2015 The Gravitee team (http://gravitee.io) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.gravitee.am.gateway.handler.oauth2.resources.handler.authorization.consent; import io.gravitee.am.common.exception.oauth2.InvalidRequestException; import io.gravitee.am.gateway.handler.common.client.ClientSyncService; import io.gravitee.am.gateway.handler.oauth2.exception.AccessDeniedException; import io.gravitee.am.gateway.handler.oauth2.exception.ServerErrorException; import io.gravitee.am.gateway.handler.oauth2.service.request.AuthorizationRequest; import io.gravitee.am.gateway.handler.oauth2.service.utils.OAuth2Constants; import io.gravitee.am.model.oidc.Client; import io.vertx.core.AsyncResult; import io.vertx.core.Future; import io.vertx.core.Handler; import io.vertx.reactivex.ext.auth.User; import io.vertx.reactivex.ext.web.RoutingContext; /** * @author Titouan COMPIEGNE (titouan.compiegne at graviteesource.com) * @author GraviteeSource Team */ public class UserConsentPrepareContextHandler implements Handler<RoutingContext> { private static final String CLIENT_CONTEXT_KEY = "client"; private static final String USER_CONTEXT_KEY = "user"; private static final String AUTHORIZATION_REQUEST_CONTEXT_KEY = "authorizationRequest"; private static final String ID_TOKEN_SESSION_CONTEXT_KEY = "id_token"; private static final String ID_TOKEN_CONTEXT_KEY = "idToken"; private ClientSyncService clientSyncService; public UserConsentPrepareContextHandler(ClientSyncService clientSyncService) { this.clientSyncService = clientSyncService; } @Override public void handle(RoutingContext routingContext) { // user must redirected here after an authorization request AuthorizationRequest authorizationRequest = routingContext.session().get(OAuth2Constants.AUTHORIZATION_REQUEST); if (authorizationRequest == null) { routingContext.response().setStatusCode(400).end("An authorization request is required to handle user approval"); return; } // check client authenticate(authorizationRequest.getClientId(), resultHandler -> { if (resultHandler.failed()) { routingContext.fail(resultHandler.cause()); return; } // check user User authenticatedUser = routingContext.user(); if (authenticatedUser == null || ! (authenticatedUser.getDelegate() instanceof io.gravitee.am.gateway.handler.common.vertx.web.auth.user.User)) { routingContext.fail(new AccessDeniedException()); return; } // prepare context Client safeClient = new Client(resultHandler.result()); safeClient.setClientSecret(null); io.gravitee.am.model.User user = ((io.gravitee.am.gateway.handler.common.vertx.web.auth.user.User) authenticatedUser.getDelegate()).getUser(); prepareContext(routingContext, safeClient, user, authorizationRequest); routingContext.next(); }); } private void authenticate(String clientId, Handler<AsyncResult<Client>> authHandler) { clientSyncService .findByClientId(clientId) .subscribe( client -> authHandler.handle(Future.succeededFuture(client)), error -> authHandler.handle(Future.failedFuture(new ServerErrorException("Server error: unable to find client with client_id " + clientId))), () -> authHandler.handle(Future.failedFuture(new InvalidRequestException("No client found for client_id " + clientId))) ); } private void prepareContext(RoutingContext context, Client client, io.gravitee.am.model.User user, AuthorizationRequest authorizationRequest) { context.put(CLIENT_CONTEXT_KEY, client); context.put(USER_CONTEXT_KEY, user); context.put(AUTHORIZATION_REQUEST_CONTEXT_KEY, authorizationRequest); // add id_token if exists String idToken = context.session().get(ID_TOKEN_SESSION_CONTEXT_KEY); if (idToken != null) { context.put(ID_TOKEN_CONTEXT_KEY, idToken); } } }