Search in sources :

Example 41 with ClientPolicyException

use of org.keycloak.services.clientpolicy.ClientPolicyException in project keycloak by keycloak.

the class FAPI1Test method testFAPIBaselineRedirectUri.

@Test
public void testFAPIBaselineRedirectUri() throws Exception {
    setupPolicyFAPIBaselineForAllClient();
    // Try to register redirect_uri like "http://hostname.com" - should fail
    try {
        String clientUUID = createClientByAdmin("invalid", (ClientRepresentation clientRep) -> {
            clientRep.setRedirectUris(Collections.singletonList("http://hostname.com"));
        });
        fail();
    } catch (ClientPolicyException e) {
        assertEquals(OAuthErrorException.INVALID_CLIENT_METADATA, e.getMessage());
    }
    // Try to register redirect_uri like "https://hostname.com/foo/*" - should fail due the wildcard
    try {
        createClientByAdmin("invalid", (ClientRepresentation clientRep) -> {
            clientRep.setRedirectUris(Collections.singletonList("https://hostname.com/foo/*"));
        });
        fail();
    } catch (ClientPolicyException e) {
        assertEquals(OAuthErrorException.INVALID_CLIENT_METADATA, e.getMessage());
    }
    // Try to register redirect_uri like "https://hostname.com" - should pass
    String clientUUID = createClientByAdmin("invalid", (ClientRepresentation clientRep) -> {
        clientRep.setRedirectUris(Collections.singletonList("https://hostname.com"));
    });
    ClientRepresentation client = getClientByAdmin(clientUUID);
    Assert.assertNames(client.getRedirectUris(), "https://hostname.com");
    getCleanup().addClientUuid(clientUUID);
    // Try to register client with valid root URL. Makes sure that there is not auto-created redirect URI with wildcard at the end (See KEYCLOAK-19556)
    String clientUUID2 = createClientByAdmin("invalid2", (ClientRepresentation clientRep) -> {
        clientRep.setRootUrl("https://hostname2.com");
        clientRep.setRedirectUris(null);
    });
    ClientRepresentation client2 = getClientByAdmin(clientUUID2);
    Assert.assertNames(client2.getRedirectUris(), "https://hostname2.com");
    getCleanup().addClientUuid(clientUUID2);
}
Also used : OIDCClientRepresentation(org.keycloak.representations.oidc.OIDCClientRepresentation) ClientRepresentation(org.keycloak.representations.idm.ClientRepresentation) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException) Test(org.junit.Test)

Example 42 with ClientPolicyException

use of org.keycloak.services.clientpolicy.ClientPolicyException in project keycloak by keycloak.

the class ClientRegistrationAuth method requireDelete.

public void requireDelete(ClientModel client) {
    RegistrationAuth chainType = requireUpdateAuth(client);
    try {
        session.clientPolicy().triggerOnEvent(new DynamicClientUnregisterContext(session, client, jwt, realm));
        ClientRegistrationPolicyManager.triggerBeforeRemove(session, provider, chainType, client);
    } catch (ClientRegistrationPolicyException | ClientPolicyException crpe) {
        throw forbidden(crpe.getMessage());
    }
}
Also used : RegistrationAuth(org.keycloak.services.clientregistration.policy.RegistrationAuth) DynamicClientUnregisterContext(org.keycloak.services.clientpolicy.context.DynamicClientUnregisterContext) ClientRegistrationPolicyException(org.keycloak.services.clientregistration.policy.ClientRegistrationPolicyException) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException)

Example 43 with ClientPolicyException

use of org.keycloak.services.clientpolicy.ClientPolicyException in project keycloak by keycloak.

the class ClientRegistrationAuth method requireView.

public void requireView(ClientModel client, boolean allowPublicClient) {
    RegistrationAuth authType = null;
    boolean authenticated = false;
    init();
    if (isBearerToken()) {
        checkClientProtocol();
        if (hasRole(AdminRoles.MANAGE_CLIENTS, AdminRoles.VIEW_CLIENTS)) {
            if (client == null) {
                throw notFound();
            }
            authenticated = true;
            authType = RegistrationAuth.AUTHENTICATED;
        } else {
            throw forbidden();
        }
    } else if (isRegistrationAccessToken()) {
        if (client != null && client.getRegistrationToken() != null && client.getRegistrationToken().equals(jwt.getId())) {
            checkClientProtocol(client);
            authenticated = true;
            authType = getRegistrationAuth();
        }
    } else if (isInitialAccessToken()) {
        throw unauthorized("Not initial access token allowed");
    } else if (allowPublicClient && authenticatePublicClient(client)) {
        authenticated = true;
        authType = RegistrationAuth.AUTHENTICATED;
    }
    if (authenticated) {
        try {
            session.clientPolicy().triggerOnEvent(new DynamicClientViewContext(session, client, jwt, realm));
            ClientRegistrationPolicyManager.triggerBeforeView(session, provider, authType, client);
        } catch (ClientRegistrationPolicyException | ClientPolicyException crpe) {
            throw forbidden(crpe.getMessage());
        }
    } else {
        throw unauthorized("Not authorized to view client. Not valid token or client credentials provided.");
    }
}
Also used : RegistrationAuth(org.keycloak.services.clientregistration.policy.RegistrationAuth) DynamicClientViewContext(org.keycloak.services.clientpolicy.context.DynamicClientViewContext) ClientRegistrationPolicyException(org.keycloak.services.clientregistration.policy.ClientRegistrationPolicyException) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException)

Example 44 with ClientPolicyException

use of org.keycloak.services.clientpolicy.ClientPolicyException in project keycloak by keycloak.

the class LogoutEndpoint method logoutToken.

/**
 * Logout a session via a non-browser invocation.  Similar signature to refresh token except there is no grant_type.
 * You must pass in the refresh token and
 * authenticate the client if it is not public.
 *
 * If the client is a confidential client
 * you must include the client-id and secret in an Basic Auth Authorization header.
 *
 * If the client is a public client, then you must include a "client_id" form parameter.
 *
 * returns 204 if successful, 400 if not with a json error response.
 *
 * @return
 */
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response logoutToken() {
    cors = Cors.add(request).auth().allowedMethods("POST").auth().exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS);
    MultivaluedMap<String, String> form = request.getDecodedFormParameters();
    checkSsl();
    event.event(EventType.LOGOUT);
    ClientModel client = authorizeClient();
    String refreshToken = form.getFirst(OAuth2Constants.REFRESH_TOKEN);
    if (refreshToken == null) {
        event.error(Errors.INVALID_TOKEN);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "No refresh token", Response.Status.BAD_REQUEST);
    }
    try {
        session.clientPolicy().triggerOnEvent(new LogoutRequestContext(form));
    } catch (ClientPolicyException cpe) {
        throw new CorsErrorResponseException(cors, cpe.getError(), cpe.getErrorDetail(), cpe.getErrorStatus());
    }
    RefreshToken token = null;
    try {
        // KEYCLOAK-6771 Certificate Bound Token
        token = tokenManager.verifyRefreshToken(session, realm, client, request, refreshToken, false);
        boolean offline = TokenUtil.TOKEN_TYPE_OFFLINE.equals(token.getType());
        UserSessionModel userSessionModel;
        if (offline) {
            UserSessionManager sessionManager = new UserSessionManager(session);
            userSessionModel = sessionManager.findOfflineUserSession(realm, token.getSessionState());
        } else {
            userSessionModel = session.sessions().getUserSession(realm, token.getSessionState());
        }
        if (userSessionModel != null) {
            checkTokenIssuedAt(token, userSessionModel);
            logout(userSessionModel, offline);
        }
    } catch (OAuthErrorException e) {
        // KEYCLOAK-6771 Certificate Bound Token
        if (MtlsHoKTokenUtil.CERT_VERIFY_ERROR_DESC.equals(e.getDescription())) {
            event.error(Errors.NOT_ALLOWED);
            throw new CorsErrorResponseException(cors, e.getError(), e.getDescription(), Response.Status.UNAUTHORIZED);
        } else {
            event.error(Errors.INVALID_TOKEN);
            throw new CorsErrorResponseException(cors, e.getError(), e.getDescription(), Response.Status.BAD_REQUEST);
        }
    }
    return cors.builder(Response.noContent()).build();
}
Also used : UserSessionManager(org.keycloak.services.managers.UserSessionManager) ClientModel(org.keycloak.models.ClientModel) UserSessionModel(org.keycloak.models.UserSessionModel) RefreshToken(org.keycloak.representations.RefreshToken) OAuthErrorException(org.keycloak.OAuthErrorException) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) LogoutRequestContext(org.keycloak.services.clientpolicy.context.LogoutRequestContext) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes)

Example 45 with ClientPolicyException

use of org.keycloak.services.clientpolicy.ClientPolicyException in project keycloak by keycloak.

the class TokenEndpoint method resourceOwnerPasswordCredentialsGrant.

public Response resourceOwnerPasswordCredentialsGrant() {
    event.detail(Details.AUTH_METHOD, "oauth_credentials");
    if (!client.isDirectAccessGrantsEnabled()) {
        event.error(Errors.NOT_ALLOWED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.UNAUTHORIZED_CLIENT, "Client not allowed for direct access grants", Response.Status.BAD_REQUEST);
    }
    if (client.isConsentRequired()) {
        event.error(Errors.CONSENT_DENIED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_CLIENT, "Client requires user consent", Response.Status.BAD_REQUEST);
    }
    try {
        session.clientPolicy().triggerOnEvent(new ResourceOwnerPasswordCredentialsContext(formParams));
    } catch (ClientPolicyException cpe) {
        event.error(cpe.getError());
        throw new CorsErrorResponseException(cors, cpe.getError(), cpe.getErrorDetail(), cpe.getErrorStatus());
    }
    String scope = getRequestedScopes();
    RootAuthenticationSessionModel rootAuthSession = new AuthenticationSessionManager(session).createAuthenticationSession(realm, false);
    AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(client);
    authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
    authSession.setAction(AuthenticatedClientSessionModel.Action.AUTHENTICATE.name());
    authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName()));
    authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, scope);
    AuthenticationFlowModel flow = AuthenticationFlowResolver.resolveDirectGrantFlow(authSession);
    String flowId = flow.getId();
    AuthenticationProcessor processor = new AuthenticationProcessor();
    processor.setAuthenticationSession(authSession).setFlowId(flowId).setConnection(clientConnection).setEventBuilder(event).setRealm(realm).setSession(session).setUriInfo(session.getContext().getUri()).setRequest(request);
    Response challenge = processor.authenticateOnly();
    if (challenge != null) {
        // Remove authentication session as "Resource Owner Password Credentials Grant" is single-request scoped authentication
        new AuthenticationSessionManager(session).removeAuthenticationSession(realm, authSession, false);
        cors.build(httpResponse);
        return challenge;
    }
    processor.evaluateRequiredActionTriggers();
    UserModel user = authSession.getAuthenticatedUser();
    if (user.getRequiredActionsStream().count() > 0 || authSession.getRequiredActions().size() > 0) {
        // Remove authentication session as "Resource Owner Password Credentials Grant" is single-request scoped authentication
        new AuthenticationSessionManager(session).removeAuthenticationSession(realm, authSession, false);
        event.error(Errors.RESOLVE_REQUIRED_ACTIONS);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "Account is not fully set up", Response.Status.BAD_REQUEST);
    }
    AuthenticationManager.setClientScopesInSession(authSession);
    ClientSessionContext clientSessionCtx = processor.attachSession();
    UserSessionModel userSession = processor.getUserSession();
    updateUserSessionFromClientAuth(userSession);
    TokenManager.AccessTokenResponseBuilder responseBuilder = tokenManager.responseBuilder(realm, client, event, session, userSession, clientSessionCtx).generateAccessToken();
    if (OIDCAdvancedConfigWrapper.fromClientModel(client).isUseRefreshToken()) {
        responseBuilder.generateRefreshToken();
    }
    String scopeParam = clientSessionCtx.getClientSession().getNote(OAuth2Constants.SCOPE);
    if (TokenUtil.isOIDCRequest(scopeParam)) {
        responseBuilder.generateIDToken().generateAccessTokenHash();
    }
    // TODO : do the same as codeToToken()
    AccessTokenResponse res = responseBuilder.build();
    event.success();
    AuthenticationManager.logSuccess(session, authSession);
    return cors.builder(Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).build();
}
Also used : AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) UserSessionModel(org.keycloak.models.UserSessionModel) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException) AuthenticationSessionManager(org.keycloak.services.managers.AuthenticationSessionManager) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse) Response(javax.ws.rs.core.Response) HttpResponse(org.jboss.resteasy.spi.HttpResponse) UserModel(org.keycloak.models.UserModel) DefaultClientSessionContext(org.keycloak.services.util.DefaultClientSessionContext) ClientSessionContext(org.keycloak.models.ClientSessionContext) ResourceOwnerPasswordCredentialsContext(org.keycloak.services.clientpolicy.context.ResourceOwnerPasswordCredentialsContext) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) AuthenticationFlowModel(org.keycloak.models.AuthenticationFlowModel) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) AuthenticationProcessor(org.keycloak.authentication.AuthenticationProcessor) TokenManager(org.keycloak.protocol.oidc.TokenManager) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse)

Aggregations

ClientPolicyException (org.keycloak.services.clientpolicy.ClientPolicyException)62 ClientRepresentation (org.keycloak.representations.idm.ClientRepresentation)23 Test (org.junit.Test)22 OIDCClientRepresentation (org.keycloak.representations.oidc.OIDCClientRepresentation)19 ClientPoliciesBuilder (org.keycloak.testsuite.util.ClientPoliciesUtil.ClientPoliciesBuilder)14 ClientPolicyBuilder (org.keycloak.testsuite.util.ClientPoliciesUtil.ClientPolicyBuilder)14 ClientProfileBuilder (org.keycloak.testsuite.util.ClientPoliciesUtil.ClientProfileBuilder)13 ClientProfilesBuilder (org.keycloak.testsuite.util.ClientPoliciesUtil.ClientProfilesBuilder)13 ClientModel (org.keycloak.models.ClientModel)11 ErrorResponseException (org.keycloak.services.ErrorResponseException)10 OAuthErrorException (org.keycloak.OAuthErrorException)9 UserSessionModel (org.keycloak.models.UserSessionModel)9 CorsErrorResponseException (org.keycloak.services.CorsErrorResponseException)9 UserModel (org.keycloak.models.UserModel)8 IOException (java.io.IOException)6 Consumes (javax.ws.rs.Consumes)6 POST (javax.ws.rs.POST)6 Response (javax.ws.rs.core.Response)6 ClientSessionContext (org.keycloak.models.ClientSessionContext)6 RegistrationAuth (org.keycloak.services.clientregistration.policy.RegistrationAuth)6