Search in sources :

Example 6 with ErrorPageException

use of org.keycloak.services.ErrorPageException in project keycloak by keycloak.

the class IdentityBrokerService method clientInitiatedAccountLinking.

@GET
@NoCache
@Path("/{provider_id}/link")
public Response clientInitiatedAccountLinking(@PathParam("provider_id") String providerId, @QueryParam("redirect_uri") String redirectUri, @QueryParam("client_id") String clientId, @QueryParam("nonce") String nonce, @QueryParam("hash") String hash) {
    this.event.event(EventType.CLIENT_INITIATED_ACCOUNT_LINKING);
    checkRealm();
    ClientModel client = checkClient(clientId);
    redirectUri = RedirectUtils.verifyRedirectUri(session, redirectUri, client);
    if (redirectUri == null) {
        event.error(Errors.INVALID_REDIRECT_URI);
        throw new ErrorPageException(session, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
    }
    event.detail(Details.REDIRECT_URI, redirectUri);
    if (nonce == null || hash == null) {
        event.error(Errors.INVALID_REDIRECT_URI);
        throw new ErrorPageException(session, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
    }
    AuthenticationManager.AuthResult cookieResult = AuthenticationManager.authenticateIdentityCookie(session, realmModel, true);
    String errorParam = "link_error";
    if (cookieResult == null) {
        event.error(Errors.NOT_LOGGED_IN);
        UriBuilder builder = UriBuilder.fromUri(redirectUri).queryParam(errorParam, Errors.NOT_LOGGED_IN).queryParam("nonce", nonce);
        return Response.status(302).location(builder.build()).build();
    }
    cookieResult.getSession();
    event.session(cookieResult.getSession());
    event.user(cookieResult.getUser());
    event.detail(Details.USERNAME, cookieResult.getUser().getUsername());
    AuthenticatedClientSessionModel clientSession = null;
    for (AuthenticatedClientSessionModel cs : cookieResult.getSession().getAuthenticatedClientSessions().values()) {
        if (cs.getClient().getClientId().equals(clientId)) {
            byte[] decoded = Base64Url.decode(hash);
            MessageDigest md = null;
            try {
                md = MessageDigest.getInstance("SHA-256");
            } catch (NoSuchAlgorithmException e) {
                throw new ErrorPageException(session, Response.Status.INTERNAL_SERVER_ERROR, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST);
            }
            String input = nonce + cookieResult.getSession().getId() + clientId + providerId;
            byte[] check = md.digest(input.getBytes(StandardCharsets.UTF_8));
            if (MessageDigest.isEqual(decoded, check)) {
                clientSession = cs;
                break;
            }
        }
    }
    if (clientSession == null) {
        event.error(Errors.INVALID_TOKEN);
        throw new ErrorPageException(session, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
    }
    event.detail(Details.IDENTITY_PROVIDER, providerId);
    ClientModel accountService = this.realmModel.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
    if (!accountService.getId().equals(client.getId())) {
        RoleModel manageAccountRole = accountService.getRole(AccountRoles.MANAGE_ACCOUNT);
        // Ensure user has role and client has "role scope" for this role
        ClientSessionContext ctx = DefaultClientSessionContext.fromClientSessionScopeParameter(clientSession, session);
        Set<RoleModel> userAccountRoles = ctx.getRolesStream().collect(Collectors.toSet());
        if (!userAccountRoles.contains(manageAccountRole)) {
            RoleModel linkRole = accountService.getRole(AccountRoles.MANAGE_ACCOUNT_LINKS);
            if (!userAccountRoles.contains(linkRole)) {
                event.error(Errors.NOT_ALLOWED);
                UriBuilder builder = UriBuilder.fromUri(redirectUri).queryParam(errorParam, Errors.NOT_ALLOWED).queryParam("nonce", nonce);
                return Response.status(302).location(builder.build()).build();
            }
        }
    }
    IdentityProviderModel identityProviderModel = realmModel.getIdentityProviderByAlias(providerId);
    if (identityProviderModel == null) {
        event.error(Errors.UNKNOWN_IDENTITY_PROVIDER);
        UriBuilder builder = UriBuilder.fromUri(redirectUri).queryParam(errorParam, Errors.UNKNOWN_IDENTITY_PROVIDER).queryParam("nonce", nonce);
        return Response.status(302).location(builder.build()).build();
    }
    // Create AuthenticationSessionModel with same ID like userSession and refresh cookie
    UserSessionModel userSession = cookieResult.getSession();
    // Auth session with ID corresponding to our userSession may already exists in some rare cases (EG. if some client tried to login in another browser tab with "prompt=login")
    RootAuthenticationSessionModel rootAuthSession = session.authenticationSessions().getRootAuthenticationSession(realmModel, userSession.getId());
    if (rootAuthSession == null) {
        rootAuthSession = session.authenticationSessions().createRootAuthenticationSession(realmModel, userSession.getId());
    }
    AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(client);
    // Refresh the cookie
    new AuthenticationSessionManager(session).setAuthSessionCookie(userSession.getId(), realmModel);
    ClientSessionCode<AuthenticationSessionModel> clientSessionCode = new ClientSessionCode<>(session, realmModel, authSession);
    clientSessionCode.setAction(AuthenticationSessionModel.Action.AUTHENTICATE.name());
    clientSessionCode.getOrGenerateCode();
    authSession.setProtocol(client.getProtocol());
    authSession.setRedirectUri(redirectUri);
    authSession.setClientNote(OIDCLoginProtocol.STATE_PARAM, UUID.randomUUID().toString());
    authSession.setAuthNote(LINKING_IDENTITY_PROVIDER, cookieResult.getSession().getId() + clientId + providerId);
    event.detail(Details.CODE_ID, userSession.getId());
    event.success();
    try {
        IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
        Response response = identityProvider.performLogin(createAuthenticationRequest(providerId, clientSessionCode));
        if (response != null) {
            if (isDebugEnabled()) {
                logger.debugf("Identity provider [%s] is going to send a request [%s].", identityProvider, response);
            }
            return response;
        }
    } catch (IdentityBrokerException e) {
        return redirectToErrorPage(authSession, Response.Status.INTERNAL_SERVER_ERROR, Messages.COULD_NOT_SEND_AUTHENTICATION_REQUEST, e, providerId);
    } catch (Exception e) {
        return redirectToErrorPage(authSession, Response.Status.INTERNAL_SERVER_ERROR, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST, e, providerId);
    }
    return redirectToErrorPage(authSession, Response.Status.INTERNAL_SERVER_ERROR, Messages.COULD_NOT_PROCEED_WITH_AUTHENTICATION_REQUEST);
}
Also used : UserSessionModel(org.keycloak.models.UserSessionModel) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) RoleModel(org.keycloak.models.RoleModel) SocialIdentityProvider(org.keycloak.broker.social.SocialIdentityProvider) IdentityProvider(org.keycloak.broker.provider.IdentityProvider) ErrorPageException(org.keycloak.services.ErrorPageException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) IdentityProviderModel(org.keycloak.models.IdentityProviderModel) ClientSessionCode(org.keycloak.services.managers.ClientSessionCode) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) WebApplicationException(javax.ws.rs.WebApplicationException) IOException(java.io.IOException) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) OAuthErrorException(org.keycloak.OAuthErrorException) NotFoundException(javax.ws.rs.NotFoundException) ErrorPageException(org.keycloak.services.ErrorPageException) AuthenticationManager(org.keycloak.services.managers.AuthenticationManager) AuthenticationSessionManager(org.keycloak.services.managers.AuthenticationSessionManager) Response(javax.ws.rs.core.Response) ErrorResponse(org.keycloak.services.ErrorResponse) ClientModel(org.keycloak.models.ClientModel) DefaultClientSessionContext(org.keycloak.services.util.DefaultClientSessionContext) ClientSessionContext(org.keycloak.models.ClientSessionContext) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) IdentityBrokerException(org.keycloak.broker.provider.IdentityBrokerException) UriBuilder(javax.ws.rs.core.UriBuilder) MessageDigest(java.security.MessageDigest) Path(javax.ws.rs.Path) GET(javax.ws.rs.GET) NoCache(org.jboss.resteasy.annotations.cache.NoCache)

Example 7 with ErrorPageException

use of org.keycloak.services.ErrorPageException in project keycloak by keycloak.

the class AuthorizationEndpointRequestParserProcessor method parseRequest.

public static AuthorizationEndpointRequest parseRequest(EventBuilder event, KeycloakSession session, ClientModel client, MultivaluedMap<String, String> requestParams) {
    try {
        AuthorizationEndpointRequest request = new AuthorizationEndpointRequest();
        AuthzEndpointQueryStringParser parser = new AuthzEndpointQueryStringParser(requestParams);
        parser.parseRequest(request);
        if (parser.getInvalidRequestMessage() != null) {
            request.invalidRequestMessage = parser.getInvalidRequestMessage();
            return request;
        }
        String requestParam = requestParams.getFirst(OIDCLoginProtocol.REQUEST_PARAM);
        String requestUriParam = requestParams.getFirst(OIDCLoginProtocol.REQUEST_URI_PARAM);
        if (requestParam != null && requestUriParam != null) {
            throw new RuntimeException("Illegal to use both 'request' and 'request_uri' parameters together");
        }
        String requestObjectRequired = OIDCAdvancedConfigWrapper.fromClientModel(client).getRequestObjectRequired();
        if (OIDCConfigAttributes.REQUEST_OBJECT_REQUIRED_REQUEST_OR_REQUEST_URI.equals(requestObjectRequired) && requestParam == null && requestUriParam == null) {
            throw new RuntimeException("Client is required to use 'request' or 'request_uri' parameter.");
        } else if (OIDCConfigAttributes.REQUEST_OBJECT_REQUIRED_REQUEST.equals(requestObjectRequired) && requestParam == null) {
            throw new RuntimeException("Client is required to use 'request' parameter.");
        } else if (OIDCConfigAttributes.REQUEST_OBJECT_REQUIRED_REQUEST_URI.equals(requestObjectRequired) && requestUriParam == null) {
            throw new RuntimeException("Client is required to use 'request_uri' parameter.");
        }
        if (requestParam != null) {
            new AuthzEndpointRequestObjectParser(session, requestParam, client).parseRequest(request);
        } else if (requestUriParam != null) {
            // Define, if the request is `PAR` or usual `Request Object`.
            RequestUriType requestUriType = getRequestUriType(requestUriParam);
            if (requestUriType == RequestUriType.PAR) {
                new AuthzEndpointParParser(session, client, requestUriParam).parseRequest(request);
            } else {
                // Validate "requestUriParam" with allowed requestUris
                List<String> requestUris = OIDCAdvancedConfigWrapper.fromClientModel(client).getRequestUris();
                String requestUri = RedirectUtils.verifyRedirectUri(session, client.getRootUrl(), requestUriParam, new HashSet<>(requestUris), false);
                if (requestUri == null) {
                    throw new RuntimeException("Specified 'request_uri' not allowed for this client.");
                }
                try (InputStream is = session.getProvider(HttpClientProvider.class).get(requestUri)) {
                    String retrievedRequest = StreamUtil.readString(is);
                    new AuthzEndpointRequestObjectParser(session, retrievedRequest, client).parseRequest(request);
                }
            }
        }
        if (Profile.isFeatureEnabled(Profile.Feature.DYNAMIC_SCOPES)) {
            request.authorizationRequestContext = AuthorizationContextUtil.getAuthorizationRequestContextFromScopes(session, request.getScope());
        }
        return request;
    } catch (Exception e) {
        ServicesLogger.LOGGER.invalidRequest(e);
        event.error(Errors.INVALID_REQUEST);
        throw new ErrorPageException(session, Response.Status.BAD_REQUEST, Messages.INVALID_REQUEST);
    }
}
Also used : InputStream(java.io.InputStream) List(java.util.List) ErrorPageException(org.keycloak.services.ErrorPageException) AuthzEndpointParParser(org.keycloak.protocol.oidc.par.endpoints.request.AuthzEndpointParParser) ErrorPageException(org.keycloak.services.ErrorPageException) HashSet(java.util.HashSet)

Aggregations

ErrorPageException (org.keycloak.services.ErrorPageException)7 ClientModel (org.keycloak.models.ClientModel)4 ClientSessionContext (org.keycloak.models.ClientSessionContext)2 UserSessionModel (org.keycloak.models.UserSessionModel)2 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 MessageDigest (java.security.MessageDigest)1 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)1 HashSet (java.util.HashSet)1 List (java.util.List)1 GET (javax.ws.rs.GET)1 NotFoundException (javax.ws.rs.NotFoundException)1 Path (javax.ws.rs.Path)1 WebApplicationException (javax.ws.rs.WebApplicationException)1 Response (javax.ws.rs.core.Response)1 UriBuilder (javax.ws.rs.core.UriBuilder)1 NoCache (org.jboss.resteasy.annotations.cache.NoCache)1 OAuthErrorException (org.keycloak.OAuthErrorException)1 IdentityBrokerException (org.keycloak.broker.provider.IdentityBrokerException)1 IdentityProvider (org.keycloak.broker.provider.IdentityProvider)1