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);
}
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());
}
}
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.");
}
}
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();
}
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();
}
Aggregations