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

公開メンバ関数

boolean requiresUser ()
 
void action (AuthenticationFlowContext context)
 
void authenticate (AuthenticationFlowContext context)
 
boolean configuredFor (KeycloakSession session, RealmModel realm, UserModel user)
 
void setRequiredActions (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 KERBEROS_DISABLED = "kerberos_disabled"
 
static boolean bypassChallengeJavascript = false
 
static final String REGISTRATION_FORM_ACTION = "registration_form"
 
static final String ATTEMPTED_USERNAME = "ATTEMPTED_USERNAME"
 

限定公開メンバ関数

Response optionalChallengeRedirect (AuthenticationFlowContext context, String negotiateHeader)
 
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)
 

非公開メンバ関数

Response challengeNegotiation (AuthenticationFlowContext context, final String negotiateToken)
 

静的非公開変数類

static final Logger logger = Logger.getLogger(SpnegoAuthenticator.class)
 

詳解

著者
Bill Burke
バージョン
Revision
1

関数詳解

◆ action()

void org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator.action ( AuthenticationFlowContext  context)
inline
55  {
56  context.attempted();
57  return;
58  }

◆ authenticate()

void org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator.authenticate ( AuthenticationFlowContext  context)
inline
61  {
62  HttpRequest request = context.getHttpRequest();
63  String authHeader = request.getHttpHeaders().getRequestHeaders().getFirst(HttpHeaders.AUTHORIZATION);
64  if (authHeader == null) {
65  Response challenge = challengeNegotiation(context, null);
66  context.forceChallenge(challenge);
67  return;
68  }
69 
70  String[] tokens = authHeader.split(" ");
71  if (tokens.length == 0) { // assume not supported
72  logger.debug("Invalid length of tokens: " + tokens.length);
73  context.attempted();
74  return;
75  }
76  if (!KerberosConstants.NEGOTIATE.equalsIgnoreCase(tokens[0])) {
77  logger.debug("Unknown scheme " + tokens[0]);
78  context.attempted();
79  return;
80  }
81  if (tokens.length != 2) {
82  context.failure(AuthenticationFlowError.INVALID_CREDENTIALS);
83  return;
84  }
85 
86  String spnegoToken = tokens[1];
87  UserCredentialModel spnegoCredential = UserCredentialModel.kerberos(spnegoToken);
88 
89  CredentialValidationOutput output = context.getSession().userCredentialManager().authenticate(context.getSession(), context.getRealm(), spnegoCredential);
90 
91  if (output == null) {
92  logger.warn("Received kerberos token, but there is no user storage provider that handles kerberos credentials.");
93  context.attempted();
94  return;
95  }
96  if (output.getAuthStatus() == CredentialValidationOutput.Status.AUTHENTICATED) {
97  context.setUser(output.getAuthenticatedUser());
98  if (output.getState() != null && !output.getState().isEmpty()) {
99  for (Map.Entry<String, String> entry : output.getState().entrySet()) {
100  context.getAuthenticationSession().setUserSessionNote(entry.getKey(), entry.getValue());
101  }
102  }
103  context.success();
104  } else if (output.getAuthStatus() == CredentialValidationOutput.Status.CONTINUE) {
105  String spnegoResponseToken = (String) output.getState().get(KerberosConstants.RESPONSE_TOKEN);
106  Response challenge = challengeNegotiation(context, spnegoResponseToken);
107  context.challenge(challenge);
108  } else {
109  context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
110  context.failure(AuthenticationFlowError.INVALID_CREDENTIALS);
111  }
112  }
static final Logger logger
Definition: SpnegoAuthenticator.java:47
Response challengeNegotiation(AuthenticationFlowContext context, final String negotiateToken)
Definition: SpnegoAuthenticator.java:114

◆ challengeNegotiation()

Response org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator.challengeNegotiation ( AuthenticationFlowContext  context,
final String  negotiateToken 
)
inlineprivate
114  {
115  String negotiateHeader = negotiateToken == null ? KerberosConstants.NEGOTIATE : KerberosConstants.NEGOTIATE + " " + negotiateToken;
116 
117  if (logger.isTraceEnabled()) {
118  logger.trace("Sending back " + HttpHeaders.WWW_AUTHENTICATE + ": " + negotiateHeader);
119  }
120  if (context.getExecution().isRequired()) {
121  return context.getSession().getProvider(LoginFormsProvider.class)
122  .setAuthenticationSession(context.getAuthenticationSession())
123  .setResponseHeader(HttpHeaders.WWW_AUTHENTICATE, negotiateHeader)
124  .setError(Messages.KERBEROS_NOT_ENABLED).createErrorPage(Response.Status.UNAUTHORIZED);
125  } else {
126  return optionalChallengeRedirect(context, negotiateHeader);
127  }
128  }
static final Logger logger
Definition: SpnegoAuthenticator.java:47
Response optionalChallengeRedirect(AuthenticationFlowContext context, String negotiateHeader)
Definition: SpnegoAuthenticator.java:140

◆ close()

void org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator.close ( )
inline
181  {
182 
183  }

◆ configuredFor()

boolean org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator.configuredFor ( KeycloakSession  session,
RealmModel  realm,
UserModel  user 
)
inline
172  {
173  return true;
174  }

◆ 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

◆ optionalChallengeRedirect()

Response org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator.optionalChallengeRedirect ( AuthenticationFlowContext  context,
String  negotiateHeader 
)
inlineprotected

401 challenge sent back that bypasses

引数
context
negotiateHeader
戻り値
140  {
141  String accessCode = context.generateAccessCode();
142  URI action = context.getActionUrl(accessCode);
143 
144  StringBuilder builder = new StringBuilder();
145 
146  builder.append("<HTML>");
147  builder.append("<HEAD>");
148 
149  builder.append("<TITLE>Kerberos Unsupported</TITLE>");
150  builder.append("</HEAD>");
152  builder.append("<BODY>");
153 
154  } else {
155  builder.append("<BODY Onload=\"document.forms[0].submit()\">");
156  }
157  builder.append("<FORM METHOD=\"POST\" ACTION=\"" + action.toString() + "\">");
158  builder.append("<NOSCRIPT>");
159  builder.append("<P>JavaScript is disabled. We strongly recommend to enable it. You were unable to login via Kerberos. Click the button below to login via an alternative method .</P>");
160  builder.append("<INPUT name=\"continue\" TYPE=\"SUBMIT\" VALUE=\"CONTINUE\" />");
161  builder.append("</NOSCRIPT>");
162 
163  builder.append("</FORM></BODY></HTML>");
164  return Response.status(Response.Status.UNAUTHORIZED)
165  .header(HttpHeaders.WWW_AUTHENTICATE, negotiateHeader)
166  .type(MediaType.TEXT_HTML_TYPE)
167  .entity(builder.toString()).build();
168  }
void action(AuthenticationFlowContext context)
Definition: SpnegoAuthenticator.java:55
static boolean bypassChallengeJavascript
Definition: SpnegoAuthenticator.java:132

◆ requiresUser()

boolean org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator.requiresUser ( )
inline
50  {
51  return false;
52  }

◆ 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.SpnegoAuthenticator.setRequiredActions ( KeycloakSession  session,
RealmModel  realm,
UserModel  user 
)
inline
177  {
178  }

◆ temporarilyDisabledUser()

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

◆ 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

メンバ詳解

◆ ATTEMPTED_USERNAME

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

◆ bypassChallengeJavascript

boolean org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator.bypassChallengeJavascript = false
static

◆ KERBEROS_DISABLED

final String org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator.KERBEROS_DISABLED = "kerberos_disabled"
static

◆ logger

final Logger org.keycloak.authentication.authenticators.browser.SpnegoAuthenticator.logger = Logger.getLogger(SpnegoAuthenticator.class)
staticprivate

◆ REGISTRATION_FORM_ACTION

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

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