- rework grant type resolution to use supports() in addition to grant type
- replace initialize() with setContext() - use EnvironmentDependentProviderFactory instead of runtime checks - move OAuth2GrantTypeManager to server-spi-private - javadocs, imports, minor fixes Signed-off-by: Dmitry Telegin <demetrio@carretti.pro>
This commit is contained in:
parent
cc9c8fe78a
commit
854ec17fd3
14 changed files with 192 additions and 144 deletions
|
@ -161,7 +161,10 @@ public enum EventType implements EnumWithStableIndex {
|
|||
USER_DISABLED_BY_PERMANENT_LOCKOUT_ERROR(0x10000 + USER_DISABLED_BY_PERMANENT_LOCKOUT.getStableIndex(), false),
|
||||
|
||||
USER_DISABLED_BY_TEMPORARY_LOCKOUT(53,true),
|
||||
USER_DISABLED_BY_TEMPORARY_LOCKOUT_ERROR(0x10000 + USER_DISABLED_BY_TEMPORARY_LOCKOUT.getStableIndex(), false);
|
||||
USER_DISABLED_BY_TEMPORARY_LOCKOUT_ERROR(0x10000 + USER_DISABLED_BY_TEMPORARY_LOCKOUT.getStableIndex(), false),
|
||||
|
||||
OAUTH2_EXTENSION_GRANT(54, true),
|
||||
OAUTH2_EXTENSION_GRANT_ERROR(0x10000 + OAUTH2_EXTENSION_GRANT.getStableIndex(), true);
|
||||
|
||||
private final int stableIndex;
|
||||
private final boolean saveByDefault;
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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 org.keycloak.protocol.oidc.grants;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
import org.keycloak.events.EventType;
|
||||
|
||||
/**
|
||||
* A class to register and resolve OAuth 2.0 Grant Type implementations
|
||||
*
|
||||
* @author <a href="mailto:demetrio@carretti.pro">Dmitry Telegin</a>
|
||||
*/
|
||||
public class OAuth2GrantManager {
|
||||
|
||||
private static final MultivaluedHashMap<String, OAuth2GrantType> GRANT_TYPE_MAP = new MultivaluedHashMap<>();
|
||||
private static final Map<String, EventType> EVENT_TYPE_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
EVENT_TYPE_MAP.put(OAuth2Constants.AUTHORIZATION_CODE, EventType.CODE_TO_TOKEN);
|
||||
EVENT_TYPE_MAP.put(OAuth2Constants.REFRESH_TOKEN, EventType.REFRESH_TOKEN);
|
||||
EVENT_TYPE_MAP.put(OAuth2Constants.PASSWORD, EventType.LOGIN);
|
||||
EVENT_TYPE_MAP.put(OAuth2Constants.CLIENT_CREDENTIALS, EventType.CLIENT_LOGIN);
|
||||
EVENT_TYPE_MAP.put(OAuth2Constants.TOKEN_EXCHANGE_GRANT_TYPE, EventType.TOKEN_EXCHANGE);
|
||||
EVENT_TYPE_MAP.put(OAuth2Constants.UMA_GRANT_TYPE, EventType.PERMISSION_TOKEN);
|
||||
EVENT_TYPE_MAP.put(OAuth2Constants.CIBA_GRANT_TYPE, EventType.AUTHREQID_TO_TOKEN);
|
||||
EVENT_TYPE_MAP.put(OAuth2Constants.DEVICE_CODE_GRANT_TYPE, EventType.OAUTH2_DEVICE_CODE_TO_TOKEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register OAuth 2.0 grant type
|
||||
* @param grant grant type to register
|
||||
*/
|
||||
public static void register(OAuth2GrantType grant) {
|
||||
GRANT_TYPE_MAP.add(grant.getGrantType(), grant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve grant type implementation from grant type and request context
|
||||
* @param grantType grant type
|
||||
* @param context grant request context
|
||||
* @return grant type implementation
|
||||
*/
|
||||
public static Optional<OAuth2GrantType> resolve(String grantType, OAuth2GrantType.Context context) {
|
||||
return resolve(resolve(grantType), context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return registered implementations for the given grant type
|
||||
* @param grantType grant type
|
||||
* @return list of implementations
|
||||
*/
|
||||
public static List<OAuth2GrantType> resolve(String grantType) {
|
||||
return GRANT_TYPE_MAP.get(grantType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the "best" grant type implementation from a list of candidates, using supports() and then priority
|
||||
* @param grants a list of candidate implementations
|
||||
* @param context grant request context
|
||||
* @return grant type implementation
|
||||
*/
|
||||
public static Optional<OAuth2GrantType> resolve(List<OAuth2GrantType> grants, OAuth2GrantType.Context context) {
|
||||
Optional<OAuth2GrantType> grant;
|
||||
|
||||
switch (grants.size()) {
|
||||
case 0:
|
||||
grant = Optional.empty();
|
||||
break;
|
||||
case 1:
|
||||
grant = Optional.of(grants.get(0));
|
||||
break;
|
||||
default:
|
||||
grant = grants.stream().filter(g -> g.supports(context)).sorted((g1, g2) -> g2.order() - g1.order()).findFirst();
|
||||
break;
|
||||
}
|
||||
|
||||
return grant.map(g -> g.create(context.getSession()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Map well-known OAuth 2.0 grant types to Keycloak event types
|
||||
* @param grantType
|
||||
* @return
|
||||
*/
|
||||
public static EventType grantToEvent(String grantType) {
|
||||
return EVENT_TYPE_MAP.getOrDefault(grantType, EventType.OAUTH2_EXTENSION_GRANT);
|
||||
}
|
||||
|
||||
}
|
|
@ -18,6 +18,7 @@
|
|||
package org.keycloak.protocol.oidc.grants;
|
||||
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.core.MultivaluedHashMap;
|
||||
import jakarta.ws.rs.core.MultivaluedMap;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
|
@ -25,7 +26,6 @@ import java.util.Map;
|
|||
|
||||
import org.keycloak.common.ClientConnection;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.http.HttpRequest;
|
||||
import org.keycloak.http.HttpResponse;
|
||||
import org.keycloak.models.ClientModel;
|
||||
|
@ -42,13 +42,6 @@ import org.keycloak.representations.dpop.DPoP;
|
|||
*/
|
||||
public interface OAuth2GrantType extends Provider, ProviderFactory<OAuth2GrantType> {
|
||||
|
||||
/**
|
||||
* Returns EventType associated with this grant type
|
||||
*
|
||||
* @return event type
|
||||
*/
|
||||
EventType getEventType();
|
||||
|
||||
/**
|
||||
* Returns the name of the OAuth 2.0 grant type implemented by this provider.
|
||||
* This value will be matched against the "grant_type" token request parameter.
|
||||
|
@ -58,11 +51,27 @@ public interface OAuth2GrantType extends Provider, ProviderFactory<OAuth2GrantTy
|
|||
String getGrantType();
|
||||
|
||||
/**
|
||||
* Processes grant request.
|
||||
* Checks if the grant implementation supports the request.
|
||||
* The check will be performed after the initial matching against the "grant_type" parameter.
|
||||
* @param context grant request context
|
||||
* @return request supported
|
||||
*/
|
||||
default boolean supports(Context context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets grant request context.
|
||||
* @param context grant request context
|
||||
*/
|
||||
void setContext(Context context);
|
||||
|
||||
/**
|
||||
* Processes grant request.
|
||||
*
|
||||
* @return token response
|
||||
*/
|
||||
Response process(Context context);
|
||||
Response process();
|
||||
|
||||
public static class Context {
|
||||
protected KeycloakSession session;
|
||||
|
@ -117,6 +126,14 @@ public interface OAuth2GrantType extends Provider, ProviderFactory<OAuth2GrantTy
|
|||
this.dPoP = context.dPoP;
|
||||
}
|
||||
|
||||
public KeycloakSession getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
public void setFormParams(MultivaluedHashMap<String, String> formParams) {
|
||||
this.formParams = formParams;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -89,6 +89,7 @@ import jakarta.ws.rs.core.Response.Status;
|
|||
import javax.xml.namespace.QName;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -117,9 +118,10 @@ public class TokenEndpoint {
|
|||
private final RealmModel realm;
|
||||
private final EventBuilder event;
|
||||
|
||||
private OAuth2GrantType grant;
|
||||
|
||||
private String grantType;
|
||||
private List<OAuth2GrantType> grants;
|
||||
private OAuth2GrantType grant;
|
||||
private OAuth2GrantType.Context context;
|
||||
|
||||
private Cors cors;
|
||||
|
||||
|
@ -158,16 +160,18 @@ public class TokenEndpoint {
|
|||
checkRealm();
|
||||
checkGrantType();
|
||||
|
||||
if (!grant.getGrantType().equals(OAuth2Constants.UMA_GRANT_TYPE)) {
|
||||
if (!grantType.equals(OAuth2Constants.UMA_GRANT_TYPE)) {
|
||||
checkClient();
|
||||
checkParameterDuplicated();
|
||||
}
|
||||
|
||||
OAuth2GrantType.Context context = new OAuth2GrantType.Context(session, realm,
|
||||
context = new OAuth2GrantType.Context(session, realm,
|
||||
client, clientConfig, clientConnection, clientAuthAttributes,
|
||||
request, httpResponse, headers, formParams, event, cors, tokenManager, dPoP);
|
||||
|
||||
return grant.process(context);
|
||||
resolveGrantType();
|
||||
grant.setContext(context);
|
||||
return grant.process();
|
||||
}
|
||||
|
||||
@Path("introspect")
|
||||
|
@ -215,12 +219,19 @@ public class TokenEndpoint {
|
|||
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "Missing form parameter: " + OIDCLoginProtocol.GRANT_TYPE_PARAM, Response.Status.BAD_REQUEST);
|
||||
}
|
||||
|
||||
grant = OAuth2GrantManager.resolve(session, grantType).orElseThrow(() -> newUnsupportedGrantTypeException());
|
||||
grants = OAuth2GrantManager.resolve(grantType);
|
||||
if (grants.isEmpty()) {
|
||||
throw newUnsupportedGrantTypeException();
|
||||
}
|
||||
|
||||
event.event(grant.getEventType());
|
||||
event.event(OAuth2GrantManager.grantToEvent(grantType));
|
||||
event.detail(Details.GRANT_TYPE, grantType);
|
||||
}
|
||||
|
||||
private void resolveGrantType() {
|
||||
grant = OAuth2GrantManager.resolve(grants, context).orElseThrow(() -> newUnsupportedGrantTypeException());
|
||||
}
|
||||
|
||||
private CorsErrorResponseException newUnsupportedGrantTypeException() {
|
||||
return new CorsErrorResponseException(cors, OAuthErrorException.UNSUPPORTED_GRANT_TYPE,
|
||||
"Unsupported " + OIDCLoginProtocol.GRANT_TYPE_PARAM, Status.BAD_REQUEST);
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.keycloak.OAuthErrorException;
|
|||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.common.util.KeycloakUriBuilder;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||
import org.keycloak.models.ClientScopeModel;
|
||||
import org.keycloak.models.ClientSessionContext;
|
||||
|
@ -60,9 +59,7 @@ public class AuthorizationCodeGrantType extends OAuth2GrantTypeBase {
|
|||
private static final String PROVIDER_ID = "authorization_code";
|
||||
|
||||
@Override
|
||||
public Response process(Context context) {
|
||||
initialize(context);
|
||||
|
||||
public Response process() {
|
||||
checkAndRetrieveDPoPProof(Profile.isFeatureEnabled(Profile.Feature.DPOP));
|
||||
|
||||
String code = formParams.getFirst(OAuth2Constants.CODE);
|
||||
|
@ -210,9 +207,4 @@ public class AuthorizationCodeGrantType extends OAuth2GrantTypeBase {
|
|||
return OAuth2Constants.AUTHORIZATION_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventType getEventType() {
|
||||
return EventType.CODE_TO_TOKEN;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.keycloak.OAuthErrorException;
|
|||
import org.keycloak.common.constants.ServiceAccountConstants;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.ClientSessionContext;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
@ -61,9 +60,7 @@ public class ClientCredentialsGrantType extends OAuth2GrantTypeBase {
|
|||
private static final Logger logger = Logger.getLogger(ClientCredentialsGrantType.class);
|
||||
|
||||
@Override
|
||||
public Response process(Context context) {
|
||||
initialize(context);
|
||||
|
||||
public Response process() {
|
||||
if (client.isBearerOnly()) {
|
||||
event.error(Errors.INVALID_CLIENT);
|
||||
throw new CorsErrorResponseException(cors, OAuthErrorException.UNAUTHORIZED_CLIENT, "Bearer-only client not allowed to retrieve service account", Response.Status.UNAUTHORIZED);
|
||||
|
@ -192,9 +189,4 @@ public class ClientCredentialsGrantType extends OAuth2GrantTypeBase {
|
|||
return OAuth2Constants.CLIENT_CREDENTIALS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventType getEventType() {
|
||||
return EventType.CLIENT_LOGIN;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright 2024 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* 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 org.keycloak.protocol.oidc.grants;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
|
||||
/**
|
||||
* A class to register and resolve OAuth 2.0 Grant Type implementations according to provider priorities
|
||||
*
|
||||
* @author <a href="mailto:demetrio@carretti.pro">Dmitry Telegin</a>
|
||||
*/
|
||||
public class OAuth2GrantManager {
|
||||
|
||||
private static final Map<String, OAuth2GrantType> MAP = new HashMap<>();
|
||||
|
||||
public static void register(OAuth2GrantType grant) {
|
||||
MAP.merge(grant.getGrantType(), grant, (g1, g2) -> g1.order() > g2.order() ? g1 : g2);
|
||||
}
|
||||
|
||||
public static Optional<OAuth2GrantType> resolve(KeycloakSession session, String grantType) {
|
||||
return Optional.ofNullable(MAP.get(grantType)).map(g -> g.create(session));
|
||||
}
|
||||
|
||||
}
|
|
@ -73,6 +73,8 @@ public abstract class OAuth2GrantTypeBase implements OAuth2GrantType {
|
|||
|
||||
private static final Logger logger = Logger.getLogger(OAuth2GrantTypeBase.class);
|
||||
|
||||
protected OAuth2GrantType.Context context;
|
||||
|
||||
protected KeycloakSession session;
|
||||
protected RealmModel realm;
|
||||
protected ClientModel client;
|
||||
|
@ -88,7 +90,9 @@ public abstract class OAuth2GrantTypeBase implements OAuth2GrantType {
|
|||
protected HttpResponse response;
|
||||
protected HttpHeaders headers;
|
||||
|
||||
protected void initialize(Context context) {
|
||||
@Override
|
||||
public void setContext(Context context) {
|
||||
this.context = context;
|
||||
this.session = context.session;
|
||||
this.realm = context.realm;
|
||||
this.client = context.client;
|
||||
|
@ -104,6 +108,7 @@ public abstract class OAuth2GrantTypeBase implements OAuth2GrantType {
|
|||
this.tokenManager = (TokenManager) context.tokenManager;
|
||||
this.dPoP = context.dPoP;
|
||||
}
|
||||
|
||||
protected Response createTokenResponse(UserModel user, UserSessionModel userSession, ClientSessionContext clientSessionCtx,
|
||||
String scopeParam, boolean code, Function<TokenManager.AccessTokenResponseBuilder, ClientPolicyContext> clientPolicyContextGenerator) {
|
||||
AccessToken token = tokenManager.createClientAccessToken(session, realm, client, user, userSession, clientSessionCtx);
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.keycloak.authorization.authorization.AuthorizationTokenService;
|
|||
import org.keycloak.authorization.util.Tokens;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.jose.jws.JWSInputException;
|
||||
import org.keycloak.models.ClientModel;
|
||||
|
@ -51,9 +50,7 @@ public class PermissionGrantType extends OAuth2GrantTypeBase {
|
|||
private static final String PROVIDER_ID = "uma_ticket";
|
||||
|
||||
@Override
|
||||
public Response process(Context context) {
|
||||
initialize(context);
|
||||
|
||||
public Response process() {
|
||||
event.detail(Details.AUTH_METHOD, "oauth_credentials");
|
||||
|
||||
String accessTokenString = null;
|
||||
|
@ -117,9 +114,10 @@ public class PermissionGrantType extends OAuth2GrantTypeBase {
|
|||
} else {
|
||||
// Clients need to authenticate in order to obtain a RPT from the server.
|
||||
// In order to support cases where the client is obtaining permissions on its on behalf, we issue a temporary access token
|
||||
OAuth2GrantType clientCredentialsGrant = OAuth2GrantManager.resolve(session, OAuth2Constants.CLIENT_CREDENTIALS).get();
|
||||
Context clientCredentialsContext = new Context(session, realm, client, clientConfig, clientConnection, clientAuthAttributes, request, response, headers, formParams, event, cors, tokenManager, dPoP);
|
||||
accessTokenString = AccessTokenResponse.class.cast(clientCredentialsGrant.process(clientCredentialsContext).getEntity()).getToken();
|
||||
Context clientCredentialsContext = new Context(context);
|
||||
OAuth2GrantType clientCredentialsGrant = OAuth2GrantManager.resolve(OAuth2Constants.CLIENT_CREDENTIALS, clientCredentialsContext).get();
|
||||
clientCredentialsGrant.setContext(context);
|
||||
accessTokenString = AccessTokenResponse.class.cast(clientCredentialsGrant.process().getEntity()).getToken();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,11 +192,6 @@ public class PermissionGrantType extends OAuth2GrantTypeBase {
|
|||
return OAuth2Constants.UMA_GRANT_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventType getEventType() {
|
||||
return EventType.PERMISSION_TOKEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2GrantType create(KeycloakSession session) {
|
||||
return new PermissionGrantType();
|
||||
|
|
|
@ -26,7 +26,6 @@ import org.keycloak.OAuth2Constants;
|
|||
import org.keycloak.OAuthErrorException;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
|
@ -50,9 +49,7 @@ public class RefreshTokenGrantType extends OAuth2GrantTypeBase {
|
|||
private static final Logger logger = Logger.getLogger(RefreshTokenGrantType.class);
|
||||
|
||||
@Override
|
||||
public Response process(Context context) {
|
||||
initialize(context);
|
||||
|
||||
public Response process() {
|
||||
checkAndRetrieveDPoPProof(Profile.isFeatureEnabled(Profile.Feature.DPOP));
|
||||
|
||||
String refreshToken = formParams.getFirst(OAuth2Constants.REFRESH_TOKEN);
|
||||
|
@ -113,11 +110,6 @@ public class RefreshTokenGrantType extends OAuth2GrantTypeBase {
|
|||
return OAuth2Constants.REFRESH_TOKEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventType getEventType() {
|
||||
return EventType.REFRESH_TOKEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2GrantType create(KeycloakSession session) {
|
||||
return new RefreshTokenGrantType();
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.keycloak.OAuthErrorException;
|
|||
import org.keycloak.authentication.AuthenticationProcessor;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||
import org.keycloak.models.AuthenticationFlowModel;
|
||||
import org.keycloak.models.ClientSessionContext;
|
||||
|
@ -61,9 +60,7 @@ public class ResourceOwnerPasswordCredentialsGrantType extends OAuth2GrantTypeBa
|
|||
private static final Logger logger = Logger.getLogger(ResourceOwnerPasswordCredentialsGrantType.class);
|
||||
|
||||
@Override
|
||||
public Response process(Context context) {
|
||||
initialize(context);
|
||||
|
||||
public Response process() {
|
||||
event.detail(Details.AUTH_METHOD, "oauth_credentials");
|
||||
|
||||
if (!client.isDirectAccessGrantsEnabled()) {
|
||||
|
@ -161,11 +158,6 @@ public class ResourceOwnerPasswordCredentialsGrantType extends OAuth2GrantTypeBa
|
|||
return OAuth2Constants.PASSWORD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventType getEventType() {
|
||||
return EventType.LOGIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2GrantType create(KeycloakSession session) {
|
||||
return new ResourceOwnerPasswordCredentialsGrantType();
|
||||
|
|
|
@ -23,10 +23,10 @@ import jakarta.ws.rs.core.Response;
|
|||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.common.Profile;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.protocol.oidc.TokenExchangeContext;
|
||||
import org.keycloak.protocol.oidc.TokenExchangeProvider;
|
||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||
import org.keycloak.utils.ProfileHelper;
|
||||
|
||||
/**
|
||||
|
@ -35,15 +35,12 @@ import org.keycloak.utils.ProfileHelper;
|
|||
*
|
||||
* @author <a href="mailto:demetrio@carretti.pro">Dmitry Telegin</a> (et al.)
|
||||
*/
|
||||
public class TokenExchangeGrantType extends OAuth2GrantTypeBase {
|
||||
public class TokenExchangeGrantType extends OAuth2GrantTypeBase implements EnvironmentDependentProviderFactory {
|
||||
|
||||
private static final String PROVIDER_ID = "token_exchange";
|
||||
|
||||
@Override
|
||||
public Response process(Context context) {
|
||||
initialize(context);
|
||||
ProfileHelper.requireFeature(Profile.Feature.TOKEN_EXCHANGE);
|
||||
|
||||
public Response process() {
|
||||
event.detail(Details.AUTH_METHOD, "token_exchange");
|
||||
event.client(client);
|
||||
|
||||
|
@ -75,13 +72,13 @@ public class TokenExchangeGrantType extends OAuth2GrantTypeBase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public EventType getEventType() {
|
||||
return EventType.TOKEN_EXCHANGE;
|
||||
public OAuth2GrantType create(KeycloakSession session) {
|
||||
return new TokenExchangeGrantType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2GrantType create(KeycloakSession session) {
|
||||
return new TokenExchangeGrantType();
|
||||
public boolean isSupported() {
|
||||
return Profile.isFeatureEnabled(Profile.Feature.TOKEN_EXCHANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
package org.keycloak.protocol.oidc.grants.ciba;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.UriBuilder;
|
||||
|
||||
|
@ -29,7 +31,6 @@ import org.keycloak.common.Profile;
|
|||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||
import org.keycloak.models.ClientScopeModel;
|
||||
import org.keycloak.models.ClientSessionContext;
|
||||
|
@ -42,12 +43,14 @@ import org.keycloak.models.utils.KeycloakModelUtils;
|
|||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
|
||||
import org.keycloak.protocol.oidc.TokenManager;
|
||||
import org.keycloak.protocol.oidc.grants.OAuth2GrantType;
|
||||
import org.keycloak.protocol.oidc.grants.OAuth2GrantTypeBase;
|
||||
import org.keycloak.protocol.oidc.grants.ciba.channel.CIBAAuthenticationRequest;
|
||||
import org.keycloak.protocol.oidc.grants.ciba.clientpolicy.context.BackchannelTokenRequestContext;
|
||||
import org.keycloak.protocol.oidc.grants.ciba.clientpolicy.context.BackchannelTokenResponseContext;
|
||||
import org.keycloak.protocol.oidc.grants.ciba.endpoints.CibaRootEndpoint;
|
||||
import org.keycloak.protocol.oidc.grants.device.DeviceGrantType;
|
||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||
import org.keycloak.services.CorsErrorResponseException;
|
||||
import org.keycloak.services.ErrorResponseException;
|
||||
import org.keycloak.services.Urls;
|
||||
|
@ -58,10 +61,6 @@ import org.keycloak.services.managers.UserConsentManager;
|
|||
import org.keycloak.services.util.DefaultClientSessionContext;
|
||||
import org.keycloak.sessions.AuthenticationSessionModel;
|
||||
import org.keycloak.sessions.RootAuthenticationSessionModel;
|
||||
import org.keycloak.utils.ProfileHelper;
|
||||
|
||||
import java.util.Map;
|
||||
import org.keycloak.protocol.oidc.grants.OAuth2GrantType;
|
||||
|
||||
/**
|
||||
* OpenID Connect Client-Initiated Backchannel Authentication Flow
|
||||
|
@ -69,7 +68,7 @@ import org.keycloak.protocol.oidc.grants.OAuth2GrantType;
|
|||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class CibaGrantType extends OAuth2GrantTypeBase {
|
||||
public class CibaGrantType extends OAuth2GrantTypeBase implements EnvironmentDependentProviderFactory {
|
||||
|
||||
private static final String PROVIDER_ID = "ciba";
|
||||
private static final Logger logger = Logger.getLogger(CibaGrantType.class);
|
||||
|
@ -111,11 +110,7 @@ public class CibaGrantType extends OAuth2GrantTypeBase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Response process(Context context) {
|
||||
initialize(context);
|
||||
|
||||
ProfileHelper.requireFeature(Profile.Feature.CIBA);
|
||||
|
||||
public Response process() {
|
||||
if (!realm.getCibaPolicy().isOIDCCIBAGrantEnabled(client)) {
|
||||
event.error(Errors.NOT_ALLOWED);
|
||||
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT,
|
||||
|
@ -301,13 +296,13 @@ public class CibaGrantType extends OAuth2GrantTypeBase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public EventType getEventType() {
|
||||
return EventType.AUTHREQID_TO_TOKEN;
|
||||
public OAuth2GrantType create(KeycloakSession session) {
|
||||
return new CibaGrantType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2GrantType create(KeycloakSession session) {
|
||||
return new CibaGrantType();
|
||||
public boolean isSupported() {
|
||||
return Profile.isFeatureEnabled(Profile.Feature.CIBA);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.keycloak.common.Profile;
|
|||
import org.keycloak.events.Details;
|
||||
import org.keycloak.events.Errors;
|
||||
import org.keycloak.events.EventBuilder;
|
||||
import org.keycloak.events.EventType;
|
||||
import org.keycloak.models.AuthenticatedClientSessionModel;
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ClientSessionContext;
|
||||
|
@ -209,9 +208,7 @@ public class DeviceGrantType extends OAuth2GrantTypeBase implements EnvironmentD
|
|||
}
|
||||
|
||||
@Override
|
||||
public Response process(Context context) {
|
||||
initialize(context);
|
||||
|
||||
public Response process() {
|
||||
if (!realm.getOAuth2DeviceConfig().isOAuth2DeviceAuthorizationGrantEnabled(client)) {
|
||||
event.error(Errors.NOT_ALLOWED);
|
||||
throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT,
|
||||
|
@ -348,11 +345,6 @@ public class DeviceGrantType extends OAuth2GrantTypeBase implements EnvironmentD
|
|||
return OAuth2Constants.DEVICE_CODE_GRANT_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventType getEventType() {
|
||||
return EventType.OAUTH2_DEVICE_CODE_TO_TOKEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2GrantType create(KeycloakSession session) {
|
||||
return new DeviceGrantType();
|
||||
|
|
Loading…
Reference in a new issue