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

クラス

enum  OtpDecision
 

公開メンバ関数

void authenticate (AuthenticationFlowContext context)
 
void setRequiredActions (KeycloakSession session, RealmModel realm, UserModel user)
 
void action (AuthenticationFlowContext context)
 
void validateOTP (AuthenticationFlowContext context)
 
boolean requiresUser ()
 
boolean configuredFor (KeycloakSession session, RealmModel realm, UserModel user)
 
void close ()
 
boolean invalidUser (AuthenticationFlowContext context, UserModel user)
 
boolean enabledUser (AuthenticationFlowContext context, UserModel user)
 
boolean validateUserAndPassword (AuthenticationFlowContext context, MultivaluedMap< String, String > inputData)
 
boolean validatePassword (AuthenticationFlowContext context, UserModel user, MultivaluedMap< String, String > inputData)
 

静的公開変数類

static final String SKIP = "skip"
 
static final String FORCE = "force"
 
static final String OTP_CONTROL_USER_ATTRIBUTE = "otpControlAttribute"
 
static final String SKIP_OTP_ROLE = "skipOtpRole"
 
static final String FORCE_OTP_ROLE = "forceOtpRole"
 
static final String SKIP_OTP_FOR_HTTP_HEADER = "noOtpRequiredForHeaderPattern"
 
static final String FORCE_OTP_FOR_HTTP_HEADER = "forceOtpForHeaderPattern"
 
static final String DEFAULT_OTP_OUTCOME = "defaultOtpOutcome"
 
static final String REGISTRATION_FORM_ACTION = "registration_form"
 
static final String ATTEMPTED_USERNAME = "ATTEMPTED_USERNAME"
 

限定公開メンバ関数

Response challenge (AuthenticationFlowContext context, String error)
 
Response invalidUser (AuthenticationFlowContext context)
 
Response disabledUser (AuthenticationFlowContext context)
 
Response temporarilyDisabledUser (AuthenticationFlowContext context)
 
Response invalidCredentials (AuthenticationFlowContext context)
 
Response setDuplicateUserChallenge (AuthenticationFlowContext context, String eventError, String loginFormError, AuthenticationFlowError authenticatorError)
 
void runDefaultDummyHash (AuthenticationFlowContext context)
 
void dummyHash (AuthenticationFlowContext context)
 

非公開メンバ関数

OtpDecision voteForDefaultFallback (Map< String, String > config)
 
boolean tryConcludeBasedOn (OtpDecision state, AuthenticationFlowContext context)
 
boolean tryConcludeBasedOn (OtpDecision state)
 
void showOtpForm (AuthenticationFlowContext context)
 
OtpDecision voteForUserOtpControlAttribute (UserModel user, Map< String, String > config)
 
OtpDecision voteForHttpHeaderMatchesPattern (MultivaluedMap< String, String > requestHeaders, Map< String, String > config)
 
boolean containsMatchingRequestHeader (MultivaluedMap< String, String > requestHeaders, String headerPattern)
 
OtpDecision voteForUserRole (RealmModel realm, UserModel user, Map< String, String > config)
 
boolean userHasRole (RealmModel realm, UserModel user, String roleName)
 
boolean isOTPRequired (KeycloakSession session, RealmModel realm, UserModel user)
 
boolean containsConditionalOtpConfig (Map config)
 

詳解

An OTPFormAuthenticator that can conditionally require OTP authentication.

The decision for whether or not to require OTP authentication can be made based on multiple conditions which are evaluated in the following order. The first matching condition determines the outcome.

  1. User Attribute
  2. Role
  3. Request Header
  4. Configured Default

If no condition matches, the ConditionalOtpFormAuthenticator fallback is to require OTP authentication.

User Attribute

A User Attribute like otp_auth can be used to control OTP authentication on individual user level. The supported values are skip and force. If the value is set to skip then the OTP auth is skipped for the user, otherwise if the value is force then the OTP auth is enforced. The setting is ignored for any other value.

Role

A role can be used to control the OTP authentication. If the user has the specified skip OTP role then OTP authentication is skipped for the user. If the user has the specified force OTP role, then the OTP authentication is required for the user. If not configured, e.g. if no role is selected, then this setting is ignored.

Request Header

Request Headers are matched via regex Patterns and can be specified as a whitelist and blacklist. No OTP for Header specifies the pattern for which OTP authentication is not required. This can be used to specify trusted networks, e.g. via: X-Forwarded-Host: (1.2.3.4|1.2.3.5) where The IPs 1.2.3.4, 1.2.3.5 denote trusted machines. Force OTP for Header specifies the pattern for which OTP authentication is required. Whitelist entries take precedence before blacklist entries.

Configured Default

A default fall-though behaviour can be specified to handle cases where all previous conditions did not lead to a conclusion. An OTP authentication is required in case no default is configured.

著者
Thomas Darimont

クラス詳解

◆ org::keycloak::authentication::authenticators::browser::ConditionalOtpFormAuthenticator::OtpDecision

enum org::keycloak::authentication::authenticators::browser::ConditionalOtpFormAuthenticator::OtpDecision
org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.OtpDecision 連携図
Collaboration graph
列挙値
ABSTAIN
SHOW_OTP
SKIP_OTP

関数詳解

◆ action()

void org.keycloak.authentication.authenticators.browser.OTPFormAuthenticator.action ( AuthenticationFlowContext  context)
inlineinherited
41  {
42  validateOTP(context);
43  }
void validateOTP(AuthenticationFlowContext context)
Definition: OTPFormAuthenticator.java:51

◆ authenticate()

void org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.authenticate ( AuthenticationFlowContext  context)
inline
108  {
109 
110  Map<String, String> config = context.getAuthenticatorConfig().getConfig();
111 
112  if (tryConcludeBasedOn(voteForUserOtpControlAttribute(context.getUser(), config), context)) {
113  return;
114  }
115 
116  if (tryConcludeBasedOn(voteForUserRole(context.getRealm(), context.getUser(), config), context)) {
117  return;
118  }
119 
120  if (tryConcludeBasedOn(voteForHttpHeaderMatchesPattern(context.getHttpRequest().getHttpHeaders().getRequestHeaders(), config), context)) {
121  return;
122  }
123 
124  if (tryConcludeBasedOn(voteForDefaultFallback(config), context)) {
125  return;
126  }
127 
128  showOtpForm(context);
129  }
void showOtpForm(AuthenticationFlowContext context)
Definition: ConditionalOtpFormAuthenticator.java:179
OtpDecision voteForHttpHeaderMatchesPattern(MultivaluedMap< String, String > requestHeaders, Map< String, String > config)
Definition: ConditionalOtpFormAuthenticator.java:212
OtpDecision voteForUserOtpControlAttribute(UserModel user, Map< String, String > config)
Definition: ConditionalOtpFormAuthenticator.java:183
OtpDecision voteForDefaultFallback(Map< String, String > config)
Definition: ConditionalOtpFormAuthenticator.java:131
boolean tryConcludeBasedOn(OtpDecision state, AuthenticationFlowContext context)
Definition: ConditionalOtpFormAuthenticator.java:147
OtpDecision voteForUserRole(RealmModel realm, UserModel user, Map< String, String > config)
Definition: ConditionalOtpFormAuthenticator.java:257

◆ challenge()

Response org.keycloak.authentication.authenticators.browser.OTPFormAuthenticator.challenge ( AuthenticationFlowContext  context,
String  error 
)
inlineprotectedinherited
80  {
81  LoginFormsProvider forms = context.form();
82  if (error != null) forms.setError(error);
83 
84  return forms.createLoginTotp();
85  }

◆ close()

void org.keycloak.authentication.authenticators.browser.OTPFormAuthenticator.close ( )
inlineinherited
101  {
102 
103  }

◆ configuredFor()

boolean org.keycloak.authentication.authenticators.browser.OTPFormAuthenticator.configuredFor ( KeycloakSession  session,
RealmModel  realm,
UserModel  user 
)
inlineinherited
88  {
89  return session.userCredentialManager().isConfiguredFor(realm, user, realm.getOTPPolicy().getType());
90  }

◆ containsConditionalOtpConfig()

boolean org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.containsConditionalOtpConfig ( Map  config)
inlineprivate
315  {
316  return config.containsKey(OTP_CONTROL_USER_ATTRIBUTE)
317  || config.containsKey(SKIP_OTP_ROLE)
318  || config.containsKey(FORCE_OTP_ROLE)
319  || config.containsKey(SKIP_OTP_FOR_HTTP_HEADER)
320  || config.containsKey(FORCE_OTP_FOR_HTTP_HEADER)
321  || config.containsKey(DEFAULT_OTP_OUTCOME);
322  }
static final String FORCE_OTP_FOR_HTTP_HEADER
Definition: ConditionalOtpFormAuthenticator.java:99
static final String DEFAULT_OTP_OUTCOME
Definition: ConditionalOtpFormAuthenticator.java:101
static final String OTP_CONTROL_USER_ATTRIBUTE
Definition: ConditionalOtpFormAuthenticator.java:91
static final String SKIP_OTP_FOR_HTTP_HEADER
Definition: ConditionalOtpFormAuthenticator.java:97
static final String FORCE_OTP_ROLE
Definition: ConditionalOtpFormAuthenticator.java:95
static final String SKIP_OTP_ROLE
Definition: ConditionalOtpFormAuthenticator.java:93

◆ containsMatchingRequestHeader()

boolean org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.containsMatchingRequestHeader ( MultivaluedMap< String, String >  requestHeaders,
String  headerPattern 
)
inlineprivate
230  {
231 
232  if (headerPattern == null) {
233  return false;
234  }
235 
236  //TODO cache RequestHeader Patterns
237  //TODO how to deal with pattern syntax exceptions?
238  Pattern pattern = Pattern.compile(headerPattern, Pattern.DOTALL);
239 
240  for (Map.Entry<String, List<String>> entry : requestHeaders.entrySet()) {
241 
242  String key = entry.getKey();
243 
244  for (String value : entry.getValue()) {
245 
246  String headerEntry = key.trim() + ": " + value.trim();
247 
248  if (pattern.matcher(headerEntry).matches()) {
249  return true;
250  }
251  }
252  }
253 
254  return false;
255  }

◆ disabledUser()

Response org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.disabledUser ( AuthenticationFlowContext  context)
inlineprotectedinherited
65  {
66  return context.form()
67  .setError(Messages.ACCOUNT_DISABLED).createLogin();
68  }

◆ dummyHash()

void org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.dummyHash ( AuthenticationFlowContext  context)
inlineprotectedinherited
93  {
94  PasswordPolicy policy = context.getRealm().getPasswordPolicy();
95  if (policy == null) {
96  runDefaultDummyHash(context);
97  return;
98  } else {
99  PasswordHashProvider hash = context.getSession().getProvider(PasswordHashProvider.class, policy.getHashAlgorithm());
100  if (hash == null) {
101  runDefaultDummyHash(context);
102  return;
103 
104  } else {
105  hash.encode("dummypassword", policy.getHashIterations());
106  }
107  }
108 
109  }
void runDefaultDummyHash(AuthenticationFlowContext context)
Definition: AbstractUsernameFormAuthenticator.java:88

◆ enabledUser()

boolean org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.enabledUser ( AuthenticationFlowContext  context,
UserModel  user 
)
inlineinherited
122  {
123  if (!user.isEnabled()) {
124  context.getEvent().user(user);
125  context.getEvent().error(Errors.USER_DISABLED);
126  Response challengeResponse = disabledUser(context);
127  // this is not a failure so don't call failureChallenge.
128  //context.failureChallenge(AuthenticationFlowError.USER_DISABLED, challengeResponse);
129  context.forceChallenge(challengeResponse);
130  return false;
131  }
132  if (isTemporarilyDisabledByBruteForce(context, user)) return false;
133  return true;
134  }
Response disabledUser(AuthenticationFlowContext context)
Definition: AbstractUsernameFormAuthenticator.java:65
boolean isTemporarilyDisabledByBruteForce(AuthenticationFlowContext context, UserModel user)
Definition: AbstractUsernameFormAuthenticator.java:210

◆ invalidCredentials()

Response org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.invalidCredentials ( AuthenticationFlowContext  context)
inlineprotectedinherited
75  {
76  return context.form()
77  .setError(Messages.INVALID_USER).createLogin();
78  }

◆ invalidUser() [1/2]

Response org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.invalidUser ( AuthenticationFlowContext  context)
inlineprotectedinherited
59  {
60  return context.form()
61  .setError(Messages.INVALID_USER)
62  .createLogin();
63  }

◆ invalidUser() [2/2]

boolean org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.invalidUser ( AuthenticationFlowContext  context,
UserModel  user 
)
inlineinherited
111  {
112  if (user == null) {
113  dummyHash(context);
114  context.getEvent().error(Errors.USER_NOT_FOUND);
115  Response challengeResponse = invalidUser(context);
116  context.failureChallenge(AuthenticationFlowError.INVALID_USER, challengeResponse);
117  return true;
118  }
119  return false;
120  }
Response invalidUser(AuthenticationFlowContext context)
Definition: AbstractUsernameFormAuthenticator.java:59
void dummyHash(AuthenticationFlowContext context)
Definition: AbstractUsernameFormAuthenticator.java:93

◆ isOTPRequired()

boolean org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.isOTPRequired ( KeycloakSession  session,
RealmModel  realm,
UserModel  user 
)
inlineprivate
285  {
286  MultivaluedMap<String, String> requestHeaders = session.getContext().getRequestHeaders().getRequestHeaders();
287  for (AuthenticatorConfigModel configModel : realm.getAuthenticatorConfigs()) {
288 
289  if (tryConcludeBasedOn(voteForUserOtpControlAttribute(user, configModel.getConfig()))) {
290  return true;
291  }
292  if (tryConcludeBasedOn(voteForUserRole(realm, user, configModel.getConfig()))) {
293  return true;
294  }
295  if (tryConcludeBasedOn(voteForHttpHeaderMatchesPattern(requestHeaders, configModel.getConfig()))) {
296  return true;
297  }
298  if (configModel.getConfig().get(DEFAULT_OTP_OUTCOME) != null
299  && configModel.getConfig().get(DEFAULT_OTP_OUTCOME).equals(FORCE)
300  && configModel.getConfig().size() <= 1) {
301  return true;
302  }
303  if (containsConditionalOtpConfig(configModel.getConfig())
304  && voteForUserOtpControlAttribute(user, configModel.getConfig()) == ABSTAIN
305  && voteForUserRole(realm, user, configModel.getConfig()) == ABSTAIN
306  && voteForHttpHeaderMatchesPattern(requestHeaders, configModel.getConfig()) == ABSTAIN
307  && (voteForDefaultFallback(configModel.getConfig()) == SHOW_OTP
308  || voteForDefaultFallback(configModel.getConfig()) == ABSTAIN)) {
309  return true;
310  }
311  }
312  return false;
313  }
OtpDecision voteForHttpHeaderMatchesPattern(MultivaluedMap< String, String > requestHeaders, Map< String, String > config)
Definition: ConditionalOtpFormAuthenticator.java:212
OtpDecision voteForUserOtpControlAttribute(UserModel user, Map< String, String > config)
Definition: ConditionalOtpFormAuthenticator.java:183
boolean containsConditionalOtpConfig(Map config)
Definition: ConditionalOtpFormAuthenticator.java:315
static final String DEFAULT_OTP_OUTCOME
Definition: ConditionalOtpFormAuthenticator.java:101
OtpDecision voteForDefaultFallback(Map< String, String > config)
Definition: ConditionalOtpFormAuthenticator.java:131
boolean tryConcludeBasedOn(OtpDecision state, AuthenticationFlowContext context)
Definition: ConditionalOtpFormAuthenticator.java:147
static final String FORCE
Definition: ConditionalOtpFormAuthenticator.java:89
OtpDecision voteForUserRole(RealmModel realm, UserModel user, Map< String, String > config)
Definition: ConditionalOtpFormAuthenticator.java:257

◆ requiresUser()

boolean org.keycloak.authentication.authenticators.browser.OTPFormAuthenticator.requiresUser ( )
inlineinherited
76  {
77  return true;
78  }

◆ runDefaultDummyHash()

void org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.runDefaultDummyHash ( AuthenticationFlowContext  context)
inlineprotectedinherited
88  {
89  PasswordHashProvider hash = context.getSession().getProvider(PasswordHashProvider.class, PasswordPolicy.HASH_ALGORITHM_DEFAULT);
90  hash.encode("dummypassword", PasswordPolicy.HASH_ITERATIONS_DEFAULT);
91  }

◆ setDuplicateUserChallenge()

Response org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.setDuplicateUserChallenge ( AuthenticationFlowContext  context,
String  eventError,
String  loginFormError,
AuthenticationFlowError  authenticatorError 
)
inlineprotectedinherited
80  {
81  context.getEvent().error(eventError);
82  Response challengeResponse = context.form()
83  .setError(loginFormError).createLogin();
84  context.failureChallenge(authenticatorError, challengeResponse);
85  return challengeResponse;
86  }

◆ setRequiredActions()

void org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.setRequiredActions ( KeycloakSession  session,
RealmModel  realm,
UserModel  user 
)
inline
325  {
326  if (!isOTPRequired(session, realm, user)) {
327  user.removeRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP);
328  } else if (!user.getRequiredActions().contains(UserModel.RequiredAction.CONFIGURE_TOTP.name())) {
329  user.addRequiredAction(UserModel.RequiredAction.CONFIGURE_TOTP.name());
330  }
331  }
boolean isOTPRequired(KeycloakSession session, RealmModel realm, UserModel user)
Definition: ConditionalOtpFormAuthenticator.java:285

◆ showOtpForm()

void org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.showOtpForm ( AuthenticationFlowContext  context)
inlineprivate
179  {
180  super.authenticate(context);
181  }

◆ temporarilyDisabledUser()

Response org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.temporarilyDisabledUser ( AuthenticationFlowContext  context)
inlineprotectedinherited
70  {
71  return context.form()
72  .setError(Messages.INVALID_USER).createLogin();
73  }

◆ tryConcludeBasedOn() [1/2]

boolean org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.tryConcludeBasedOn ( OtpDecision  state,
AuthenticationFlowContext  context 
)
inlineprivate
147  {
148 
149  switch (state) {
150 
151  case SHOW_OTP:
152  showOtpForm(context);
153  return true;
154 
155  case SKIP_OTP:
156  context.success();
157  return true;
158 
159  default:
160  return false;
161  }
162  }
void showOtpForm(AuthenticationFlowContext context)
Definition: ConditionalOtpFormAuthenticator.java:179

◆ tryConcludeBasedOn() [2/2]

boolean org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.tryConcludeBasedOn ( OtpDecision  state)
inlineprivate
164  {
165 
166  switch (state) {
167 
168  case SHOW_OTP:
169  return true;
170 
171  case SKIP_OTP:
172  return false;
173 
174  default:
175  return false;
176  }
177  }

◆ userHasRole()

boolean org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.userHasRole ( RealmModel  realm,
UserModel  user,
String  roleName 
)
inlineprivate
274  {
275 
276  if (roleName == null) {
277  return false;
278  }
279 
280  RoleModel role = getRoleFromString(realm, roleName);
281 
282  return RoleUtils.hasRole(user.getRoleMappings(), role);
283  }

◆ validateOTP()

void org.keycloak.authentication.authenticators.browser.OTPFormAuthenticator.validateOTP ( AuthenticationFlowContext  context)
inlineinherited
51  {
52  MultivaluedMap<String, String> inputData = context.getHttpRequest().getDecodedFormParameters();
53  if (inputData.containsKey("cancel")) {
54  context.resetFlow();
55  return;
56  }
57  String password = inputData.getFirst(CredentialRepresentation.TOTP);
58  if (password == null) {
59  Response challengeResponse = challenge(context, null);
60  context.challenge(challengeResponse);
61  return;
62  }
63  boolean valid = context.getSession().userCredentialManager().isValid(context.getRealm(), context.getUser(),
64  UserCredentialModel.otp(context.getRealm().getOTPPolicy().getType(), password));
65  if (!valid) {
66  context.getEvent().user(context.getUser())
67  .error(Errors.INVALID_USER_CREDENTIALS);
68  Response challengeResponse = challenge(context, Messages.INVALID_TOTP);
69  context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS, challengeResponse);
70  return;
71  }
72  context.success();
73  }
Response challenge(AuthenticationFlowContext context, String error)
Definition: OTPFormAuthenticator.java:80

◆ validatePassword()

boolean org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.validatePassword ( AuthenticationFlowContext  context,
UserModel  user,
MultivaluedMap< String, String >  inputData 
)
inlineinherited
191  {
192  List<CredentialInput> credentials = new LinkedList<>();
193  String password = inputData.getFirst(CredentialRepresentation.PASSWORD);
194  credentials.add(UserCredentialModel.password(password));
195 
196  if (isTemporarilyDisabledByBruteForce(context, user)) return false;
197 
198  if (password != null && !password.isEmpty() && context.getSession().userCredentialManager().isValid(context.getRealm(), user, credentials)) {
199  return true;
200  } else {
201  context.getEvent().user(user);
202  context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
203  Response challengeResponse = invalidCredentials(context);
204  context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS, challengeResponse);
205  context.clearUser();
206  return false;
207  }
208  }
Response invalidCredentials(AuthenticationFlowContext context)
Definition: AbstractUsernameFormAuthenticator.java:75
boolean isTemporarilyDisabledByBruteForce(AuthenticationFlowContext context, UserModel user)
Definition: AbstractUsernameFormAuthenticator.java:210

◆ validateUserAndPassword()

boolean org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.validateUserAndPassword ( AuthenticationFlowContext  context,
MultivaluedMap< String, String >  inputData 
)
inlineinherited
136  {
137  String username = inputData.getFirst(AuthenticationManager.FORM_USERNAME);
138  if (username == null) {
139  context.getEvent().error(Errors.USER_NOT_FOUND);
140  Response challengeResponse = invalidUser(context);
141  context.failureChallenge(AuthenticationFlowError.INVALID_USER, challengeResponse);
142  return false;
143  }
144 
145  // remove leading and trailing whitespace
146  username = username.trim();
147 
148  context.getEvent().detail(Details.USERNAME, username);
149  context.getAuthenticationSession().setAuthNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME, username);
150 
151  UserModel user = null;
152  try {
153  user = KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(), username);
154  } catch (ModelDuplicateException mde) {
155  ServicesLogger.LOGGER.modelDuplicateException(mde);
156 
157  // Could happen during federation import
158  if (mde.getDuplicateFieldName() != null && mde.getDuplicateFieldName().equals(UserModel.EMAIL)) {
159  setDuplicateUserChallenge(context, Errors.EMAIL_IN_USE, Messages.EMAIL_EXISTS, AuthenticationFlowError.INVALID_USER);
160  } else {
161  setDuplicateUserChallenge(context, Errors.USERNAME_IN_USE, Messages.USERNAME_EXISTS, AuthenticationFlowError.INVALID_USER);
162  }
163 
164  return false;
165  }
166 
167  if (invalidUser(context, user)) {
168  return false;
169  }
170 
171  if (!validatePassword(context, user, inputData)) {
172  return false;
173  }
174 
175  if (!enabledUser(context, user)) {
176  return false;
177  }
178 
179  String rememberMe = inputData.getFirst("rememberMe");
180  boolean remember = rememberMe != null && rememberMe.equalsIgnoreCase("on");
181  if (remember) {
182  context.getAuthenticationSession().setAuthNote(Details.REMEMBER_ME, "true");
183  context.getEvent().detail(Details.REMEMBER_ME, "true");
184  } else {
185  context.getAuthenticationSession().removeAuthNote(Details.REMEMBER_ME);
186  }
187  context.setUser(user);
188  return true;
189  }
Response invalidUser(AuthenticationFlowContext context)
Definition: AbstractUsernameFormAuthenticator.java:59
Response setDuplicateUserChallenge(AuthenticationFlowContext context, String eventError, String loginFormError, AuthenticationFlowError authenticatorError)
Definition: AbstractUsernameFormAuthenticator.java:80
boolean enabledUser(AuthenticationFlowContext context, UserModel user)
Definition: AbstractUsernameFormAuthenticator.java:122
boolean validatePassword(AuthenticationFlowContext context, UserModel user, MultivaluedMap< String, String > inputData)
Definition: AbstractUsernameFormAuthenticator.java:191

◆ voteForDefaultFallback()

OtpDecision org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.voteForDefaultFallback ( Map< String, String >  config)
inlineprivate
131  {
132 
133  if (!config.containsKey(DEFAULT_OTP_OUTCOME)) {
134  return ABSTAIN;
135  }
136 
137  switch (config.get(DEFAULT_OTP_OUTCOME)) {
138  case SKIP:
139  return SKIP_OTP;
140  case FORCE:
141  return SHOW_OTP;
142  default:
143  return ABSTAIN;
144  }
145  }
static final String DEFAULT_OTP_OUTCOME
Definition: ConditionalOtpFormAuthenticator.java:101
static final String FORCE
Definition: ConditionalOtpFormAuthenticator.java:89
static final String SKIP
Definition: ConditionalOtpFormAuthenticator.java:87

◆ voteForHttpHeaderMatchesPattern()

OtpDecision org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.voteForHttpHeaderMatchesPattern ( MultivaluedMap< String, String >  requestHeaders,
Map< String, String >  config 
)
inlineprivate
212  {
213 
214  if (!config.containsKey(FORCE_OTP_FOR_HTTP_HEADER) && !config.containsKey(SKIP_OTP_FOR_HTTP_HEADER)) {
215  return ABSTAIN;
216  }
217 
218  //Inverted to allow white-lists, e.g. for specifying trusted remote hosts: X-Forwarded-Host: (1.2.3.4|1.2.3.5)
219  if (containsMatchingRequestHeader(requestHeaders, config.get(SKIP_OTP_FOR_HTTP_HEADER))) {
220  return SKIP_OTP;
221  }
222 
223  if (containsMatchingRequestHeader(requestHeaders, config.get(FORCE_OTP_FOR_HTTP_HEADER))) {
224  return SHOW_OTP;
225  }
226 
227  return ABSTAIN;
228  }
static final String FORCE_OTP_FOR_HTTP_HEADER
Definition: ConditionalOtpFormAuthenticator.java:99
static final String SKIP_OTP_FOR_HTTP_HEADER
Definition: ConditionalOtpFormAuthenticator.java:97
boolean containsMatchingRequestHeader(MultivaluedMap< String, String > requestHeaders, String headerPattern)
Definition: ConditionalOtpFormAuthenticator.java:230

◆ voteForUserOtpControlAttribute()

OtpDecision org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.voteForUserOtpControlAttribute ( UserModel  user,
Map< String, String >  config 
)
inlineprivate
183  {
184 
185  if (!config.containsKey(OTP_CONTROL_USER_ATTRIBUTE)) {
186  return ABSTAIN;
187  }
188 
189  String attributeName = config.get(OTP_CONTROL_USER_ATTRIBUTE);
190  if (attributeName == null) {
191  return ABSTAIN;
192  }
193 
194  List<String> values = user.getAttribute(attributeName);
195 
196  if (values.isEmpty()) {
197  return ABSTAIN;
198  }
199 
200  String value = values.get(0).trim();
201 
202  switch (value) {
203  case SKIP:
204  return SKIP_OTP;
205  case FORCE:
206  return SHOW_OTP;
207  default:
208  return ABSTAIN;
209  }
210  }
static final String OTP_CONTROL_USER_ATTRIBUTE
Definition: ConditionalOtpFormAuthenticator.java:91
static final String FORCE
Definition: ConditionalOtpFormAuthenticator.java:89
static final String SKIP
Definition: ConditionalOtpFormAuthenticator.java:87

◆ voteForUserRole()

OtpDecision org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.voteForUserRole ( RealmModel  realm,
UserModel  user,
Map< String, String >  config 
)
inlineprivate
257  {
258 
259  if (!config.containsKey(SKIP_OTP_ROLE) && !config.containsKey(FORCE_OTP_ROLE)) {
260  return ABSTAIN;
261  }
262 
263  if (userHasRole(realm, user, config.get(SKIP_OTP_ROLE))) {
264  return SKIP_OTP;
265  }
266 
267  if (userHasRole(realm, user, config.get(FORCE_OTP_ROLE))) {
268  return SHOW_OTP;
269  }
270 
271  return ABSTAIN;
272  }
boolean userHasRole(RealmModel realm, UserModel user, String roleName)
Definition: ConditionalOtpFormAuthenticator.java:274
static final String FORCE_OTP_ROLE
Definition: ConditionalOtpFormAuthenticator.java:95
static final String SKIP_OTP_ROLE
Definition: ConditionalOtpFormAuthenticator.java:93

メンバ詳解

◆ ATTEMPTED_USERNAME

final String org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME = "ATTEMPTED_USERNAME"
staticinherited

◆ DEFAULT_OTP_OUTCOME

final String org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.DEFAULT_OTP_OUTCOME = "defaultOtpOutcome"
static

◆ FORCE

final String org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.FORCE = "force"
static

◆ FORCE_OTP_FOR_HTTP_HEADER

final String org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.FORCE_OTP_FOR_HTTP_HEADER = "forceOtpForHeaderPattern"
static

◆ FORCE_OTP_ROLE

final String org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.FORCE_OTP_ROLE = "forceOtpRole"
static

◆ OTP_CONTROL_USER_ATTRIBUTE

final String org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.OTP_CONTROL_USER_ATTRIBUTE = "otpControlAttribute"
static

◆ REGISTRATION_FORM_ACTION

final String org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator.REGISTRATION_FORM_ACTION = "registration_form"
staticinherited

◆ SKIP

final String org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.SKIP = "skip"
static

◆ SKIP_OTP_FOR_HTTP_HEADER

final String org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.SKIP_OTP_FOR_HTTP_HEADER = "noOtpRequiredForHeaderPattern"
static

◆ SKIP_OTP_ROLE

final String org.keycloak.authentication.authenticators.browser.ConditionalOtpFormAuthenticator.SKIP_OTP_ROLE = "skipOtpRole"
static

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