keycloak
公開メンバ関数 | 静的公開変数類 | 限定公開メンバ関数 | 全メンバ一覧
org.keycloak.authentication.authenticators.client.JWTClientAuthenticator クラス
org.keycloak.authentication.authenticators.client.JWTClientAuthenticator の継承関係図
Inheritance graph
org.keycloak.authentication.authenticators.client.JWTClientAuthenticator 連携図
Collaboration graph

公開メンバ関数

void authenticateClient (ClientAuthenticationFlowContext context)
 
String getDisplayType ()
 
boolean isConfigurable ()
 
AuthenticationExecutionModel.Requirement [] getRequirementChoices ()
 
String getHelpText ()
 
List< ProviderConfigPropertygetConfigProperties ()
 
List< ProviderConfigPropertygetConfigPropertiesPerClient ()
 
Map< String, Object > getAdapterConfiguration (ClientModel client)
 
String getId ()
 
Set< String > getProtocolAuthenticatorMethods (String loginProtocol)
 
ClientAuthenticator create ()
 
ClientAuthenticator create (KeycloakSession session)
 
void close ()
 
void init (Config.Scope config)
 
void postInit (KeycloakSessionFactory factory)
 
boolean isUserSetupAllowed ()
 
String getReferenceCategory ()
 
default int order ()
 

静的公開変数類

static final String PROVIDER_ID = "client-jwt"
 
static final String ATTR_PREFIX = "jwt.credential"
 
static final String CERTIFICATE_ATTR = "jwt.credential.certificate"
 
static final AuthenticationExecutionModel.Requirement [] REQUIREMENT_CHOICES
 

限定公開メンバ関数

PublicKey getSignatureValidationKey (ClientModel client, ClientAuthenticationFlowContext context, JWSInput jws)
 

詳解

Client authentication based on JWT signed by client private key . See specs for more details.

This is server side, which verifies JWT from client_assertion parameter, where the assertion was created on adapter side by org.keycloak.adapters.authentication.JWTClientCredentialsProvider

著者
Marek Posolda

関数詳解

◆ authenticateClient()

void org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.authenticateClient ( ClientAuthenticationFlowContext  context)
inline

org.keycloak.authentication.ClientAuthenticatorを実装しています。

72  {
73  MultivaluedMap<String, String> params = context.getHttpRequest().getDecodedFormParameters();
74 
75  String clientAssertionType = params.getFirst(OAuth2Constants.CLIENT_ASSERTION_TYPE);
76  String clientAssertion = params.getFirst(OAuth2Constants.CLIENT_ASSERTION);
77 
78  if (clientAssertionType == null) {
79  Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "invalid_client", "Parameter client_assertion_type is missing");
80  context.challenge(challengeResponse);
81  return;
82  }
83 
84  if (!clientAssertionType.equals(OAuth2Constants.CLIENT_ASSERTION_TYPE_JWT)) {
85  Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "invalid_client", "Parameter client_assertion_type has value '"
86  + clientAssertionType + "' but expected is '" + OAuth2Constants.CLIENT_ASSERTION_TYPE_JWT + "'");
87  context.challenge(challengeResponse);
88  return;
89  }
90 
91  if (clientAssertion == null) {
92  Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "invalid_client", "client_assertion parameter missing");
93  context.failure(AuthenticationFlowError.INVALID_CLIENT_CREDENTIALS, challengeResponse);
94  return;
95  }
96 
97  try {
98  JWSInput jws = new JWSInput(clientAssertion);
99  JsonWebToken token = jws.readJsonContent(JsonWebToken.class);
100 
101  RealmModel realm = context.getRealm();
102  String clientId = token.getSubject();
103  if (clientId == null) {
104  throw new RuntimeException("Can't identify client. Issuer missing on JWT token");
105  }
106 
107  context.getEvent().client(clientId);
108  ClientModel client = realm.getClientByClientId(clientId);
109  if (client == null) {
110  context.failure(AuthenticationFlowError.CLIENT_NOT_FOUND, null);
111  return;
112  } else {
113  context.setClient(client);
114  }
115 
116  if (!client.isEnabled()) {
117  context.failure(AuthenticationFlowError.CLIENT_DISABLED, null);
118  return;
119  }
120 
121  // Get client key and validate signature
122  PublicKey clientPublicKey = getSignatureValidationKey(client, context, jws);
123  if (clientPublicKey == null) {
124  // Error response already set to context
125  return;
126  }
127 
128  boolean signatureValid;
129  try {
130  signatureValid = RSAProvider.verify(jws, clientPublicKey);
131  } catch (RuntimeException e) {
132  Throwable cause = e.getCause() != null ? e.getCause() : e;
133  throw new RuntimeException("Signature on JWT token failed validation", cause);
134  }
135  if (!signatureValid) {
136  throw new RuntimeException("Signature on JWT token failed validation");
137  }
138 
139  // Allow both "issuer" or "token-endpoint" as audience
140  String issuerUrl = Urls.realmIssuer(context.getUriInfo().getBaseUri(), realm.getName());
141  String tokenUrl = OIDCLoginProtocolService.tokenUrl(context.getUriInfo().getBaseUriBuilder()).build(realm.getName()).toString();
142  if (!token.hasAudience(issuerUrl) && !token.hasAudience(tokenUrl)) {
143  throw new RuntimeException("Token audience doesn't match domain. Realm issuer is '" + issuerUrl + "' but audience from token is '" + Arrays.asList(token.getAudience()).toString() + "'");
144  }
145 
146  if (!token.isActive()) {
147  throw new RuntimeException("Token is not active");
148  }
149 
150  // KEYCLOAK-2986
151  if (token.getExpiration() == 0 && token.getIssuedAt() + 10 < Time.currentTime()) {
152  throw new RuntimeException("Token is not active");
153  }
154 
155  context.success();
156  } catch (Exception e) {
157  ServicesLogger.LOGGER.errorValidatingAssertion(e);
158  Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Client authentication with signed JWT failed: " + e.getMessage());
159  context.failure(AuthenticationFlowError.INVALID_CLIENT_CREDENTIALS, challengeResponse);
160  }
161  }
PublicKey getSignatureValidationKey(ClientModel client, ClientAuthenticationFlowContext context, JWSInput jws)
Definition: JWTClientAuthenticator.java:163

◆ close()

void org.keycloak.authentication.authenticators.client.AbstractClientAuthenticator.close ( )
inlineinherited

org.keycloak.provider.Providerを実装しています。

37  {
38 
39  }

◆ create() [1/2]

ClientAuthenticator org.keycloak.authentication.authenticators.client.AbstractClientAuthenticator.create ( )
inlineinherited

org.keycloak.authentication.ClientAuthenticatorFactoryを実装しています。

32  {
33  return this;
34  }

◆ create() [2/2]

ClientAuthenticator org.keycloak.authentication.authenticators.client.AbstractClientAuthenticator.create ( KeycloakSession  session)
inlineinherited

org.keycloak.provider.ProviderFactory< T extends Provider >を実装しています。

42  {
43  return this;
44  }

◆ getAdapterConfiguration()

Map<String, Object> org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.getAdapterConfiguration ( ClientModel  client)
inline

org.keycloak.authentication.ClientAuthenticatorFactoryを実装しています。

206  {
207  Map<String, Object> props = new HashMap<>();
208  props.put("client-keystore-file", "REPLACE WITH THE LOCATION OF YOUR KEYSTORE FILE");
209  props.put("client-keystore-type", "jks");
210  props.put("client-keystore-password", "REPLACE WITH THE KEYSTORE PASSWORD");
211  props.put("client-key-password", "REPLACE WITH THE KEY PASSWORD IN KEYSTORE");
212  props.put("client-key-alias", client.getClientId());
213  props.put("token-timeout", 10);
214 
215  Map<String, Object> config = new HashMap<>();
216  config.put("jwt", props);
217  return config;
218  }

◆ getConfigProperties()

List<ProviderConfigProperty> org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.getConfigProperties ( )
inline

org.keycloak.provider.ConfiguredProviderを実装しています。

195  {
196  return new LinkedList<>();
197  }

◆ getConfigPropertiesPerClient()

List<ProviderConfigProperty> org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.getConfigPropertiesPerClient ( )
inline

org.keycloak.authentication.ClientAuthenticatorFactoryを実装しています。

200  {
201  // This impl doesn't use generic screen in admin console, but has its own screen. So no need to return anything here
202  return Collections.emptyList();
203  }

◆ getDisplayType()

String org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.getDisplayType ( )
inline

org.keycloak.authentication.ConfigurableAuthenticatorFactoryを実装しています。

175  {
176  return "Signed Jwt";
177  }

◆ getHelpText()

String org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.getHelpText ( )
inline

org.keycloak.provider.ConfiguredProviderを実装しています。

190  {
191  return "Validates client based on signed JWT issued by client and signed with the Client private key";
192  }

◆ getId()

String org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.getId ( )
inline

org.keycloak.provider.ProviderFactory< T extends Provider >を実装しています。

221  {
222  return PROVIDER_ID;
223  }
static final String PROVIDER_ID
Definition: JWTClientAuthenticator.java:62

◆ getProtocolAuthenticatorMethods()

Set<String> org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.getProtocolAuthenticatorMethods ( String  loginProtocol)
inline

org.keycloak.authentication.ClientAuthenticatorFactoryを実装しています。

226  {
227  if (loginProtocol.equals(OIDCLoginProtocol.LOGIN_PROTOCOL)) {
228  Set<String> results = new HashSet<>();
229  results.add(OIDCLoginProtocol.PRIVATE_KEY_JWT);
230  return results;
231  } else {
232  return Collections.emptySet();
233  }
234  }

◆ getReferenceCategory()

String org.keycloak.authentication.authenticators.client.AbstractClientAuthenticator.getReferenceCategory ( )
inlineinherited

org.keycloak.authentication.ConfigurableAuthenticatorFactoryを実装しています。

62  {
63  return null;
64  }

◆ getRequirementChoices()

AuthenticationExecutionModel.Requirement [] org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.getRequirementChoices ( )
inline

org.keycloak.authentication.ConfigurableAuthenticatorFactoryを実装しています。

185  {
186  return REQUIREMENT_CHOICES;
187  }
static final AuthenticationExecutionModel.Requirement [] REQUIREMENT_CHOICES
Definition: JWTClientAuthenticator.java:66

◆ getSignatureValidationKey()

PublicKey org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.getSignatureValidationKey ( ClientModel  client,
ClientAuthenticationFlowContext  context,
JWSInput  jws 
)
inlineprotected
163  {
164  PublicKey publicKey = PublicKeyStorageManager.getClientPublicKey(context.getSession(), client, jws);
165  if (publicKey == null) {
166  Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Unable to load public key");
167  context.failure(AuthenticationFlowError.CLIENT_CREDENTIALS_SETUP_REQUIRED, challengeResponse);
168  return null;
169  } else {
170  return publicKey;
171  }
172  }

◆ init()

void org.keycloak.authentication.authenticators.client.AbstractClientAuthenticator.init ( Config.Scope  config)
inlineinherited

org.keycloak.provider.ProviderFactory< T extends Provider >を実装しています。

47  {
48 
49  }

◆ isConfigurable()

boolean org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.isConfigurable ( )
inline

org.keycloak.authentication.ClientAuthenticatorFactoryを実装しています。

180  {
181  return false;
182  }

◆ isUserSetupAllowed()

boolean org.keycloak.authentication.authenticators.client.AbstractClientAuthenticator.isUserSetupAllowed ( )
inlineinherited

org.keycloak.authentication.ConfigurableAuthenticatorFactoryを実装しています。

57  {
58  return false;
59  }

◆ order()

default int org.keycloak.provider.ProviderFactory< T extends Provider >.order ( )
inlineinherited

◆ postInit()

void org.keycloak.authentication.authenticators.client.AbstractClientAuthenticator.postInit ( KeycloakSessionFactory  factory)
inlineinherited

org.keycloak.provider.ProviderFactory< T extends Provider >を実装しています。

52  {
53 
54  }

メンバ詳解

◆ ATTR_PREFIX

final String org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.ATTR_PREFIX = "jwt.credential"
static

◆ CERTIFICATE_ATTR

final String org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.CERTIFICATE_ATTR = "jwt.credential.certificate"
static

◆ PROVIDER_ID

final String org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.PROVIDER_ID = "client-jwt"
static

◆ REQUIREMENT_CHOICES

final AuthenticationExecutionModel.Requirement [] org.keycloak.authentication.authenticators.client.JWTClientAuthenticator.REQUIREMENT_CHOICES
static
初期値:
= {
AuthenticationExecutionModel.Requirement.ALTERNATIVE,
AuthenticationExecutionModel.Requirement.DISABLED
}

このクラス詳解は次のファイルから抽出されました: