Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
42ffe21f91
97 files changed
+2501
-643
No files matched your search
@@ -0,0 +1,46 @@
|
||||
package org.keycloak.models;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Output of credential validation
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class CredentialValidationOutput {
|
||||
|
||||
private final UserModel authenticatedUser; // authenticated user.
|
||||
private final Status authStatus; // status whether user is authenticated or more steps needed
|
||||
private final Map<String, Object> state; // Additional state related to authentication. It can contain data to be sent back to client or data about used credentials.
|
||||
|
||||
public CredentialValidationOutput(UserModel authenticatedUser, Status authStatus, Map<String, Object> state) {
|
||||
this.authenticatedUser = authenticatedUser;
|
||||
this.authStatus = authStatus;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public static CredentialValidationOutput failed() {
|
||||
return new CredentialValidationOutput(null, CredentialValidationOutput.Status.FAILED, new HashMap<String, Object>());
|
||||
}
|
||||
|
||||
public UserModel getAuthenticatedUser() {
|
||||
return authenticatedUser;
|
||||
}
|
||||
|
||||
public Status getAuthStatus() {
|
||||
return authStatus;
|
||||
}
|
||||
|
||||
public Map<String, Object> getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public CredentialValidationOutput merge(CredentialValidationOutput that) {
|
||||
throw new IllegalStateException("Not supported yet");
|
||||
}
|
||||
|
||||
public static enum Status {
|
||||
AUTHENTICATED, FAILED, CONTINUE
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ public class RequiredCredentialModel {
|
||||
public static final RequiredCredentialModel TOTP;
|
||||
public static final RequiredCredentialModel CLIENT_CERT;
|
||||
public static final RequiredCredentialModel SECRET;
|
||||
public static final RequiredCredentialModel KERBEROS;
|
||||
|
||||
static {
|
||||
Map<String, RequiredCredentialModel> map = new HashMap<String, RequiredCredentialModel>();
|
||||
@@ -81,6 +82,12 @@ public class RequiredCredentialModel {
|
||||
CLIENT_CERT.setSecret(false);
|
||||
CLIENT_CERT.setFormLabel("clientCertificate");
|
||||
map.put(CLIENT_CERT.getType(), CLIENT_CERT);
|
||||
KERBEROS = new RequiredCredentialModel();
|
||||
KERBEROS.setType(UserCredentialModel.KERBEROS);
|
||||
KERBEROS.setInput(false);
|
||||
KERBEROS.setSecret(false);
|
||||
KERBEROS.setFormLabel("kerberos");
|
||||
map.put(KERBEROS.getType(), KERBEROS);
|
||||
BUILT_IN = Collections.unmodifiableMap(map);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ public class UserCredentialModel {
|
||||
public static final String SECRET = "secret";
|
||||
public static final String TOTP = "totp";
|
||||
public static final String CLIENT_CERT = "cert";
|
||||
public static final String KERBEROS = "kerberos";
|
||||
|
||||
protected String type;
|
||||
protected String value;
|
||||
@@ -49,6 +50,13 @@ public class UserCredentialModel {
|
||||
return model;
|
||||
}
|
||||
|
||||
public static UserCredentialModel kerberos(String token) {
|
||||
UserCredentialModel model = new UserCredentialModel();
|
||||
model.setType(KERBEROS);
|
||||
model.setValue(token);
|
||||
return model;
|
||||
}
|
||||
|
||||
public static UserCredentialModel generateSecret() {
|
||||
UserCredentialModel model = new UserCredentialModel();
|
||||
model.setType(SECRET);
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.keycloak.models;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -355,27 +356,40 @@ public class UserFederationManager implements UserProvider {
|
||||
|
||||
@Override
|
||||
public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
|
||||
UserFederationProvider link = getFederationLink(realm, user);
|
||||
if (link != null) {
|
||||
validateUser(realm, user);
|
||||
Set<String> supportedCredentialTypes = link.getSupportedCredentialTypes(user);
|
||||
if (supportedCredentialTypes.size() > 0) {
|
||||
List<UserCredentialModel> fedCreds = new ArrayList<UserCredentialModel>();
|
||||
List<UserCredentialModel> localCreds = new ArrayList<UserCredentialModel>();
|
||||
for (UserCredentialModel cred : input) {
|
||||
if (supportedCredentialTypes.contains(cred.getType())) {
|
||||
fedCreds.add(cred);
|
||||
} else {
|
||||
localCreds.add(cred);
|
||||
}
|
||||
}
|
||||
if (!link.validCredentials(realm, user, fedCreds)) {
|
||||
return false;
|
||||
}
|
||||
return session.userStorage().validCredentials(realm, user, localCreds);
|
||||
}
|
||||
return validCredentials(realm, user, Arrays.asList(input));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
|
||||
List<UserFederationProviderModel> fedProviderModels = realm.getUserFederationProviders();
|
||||
List<UserFederationProvider> fedProviders = new ArrayList<UserFederationProvider>();
|
||||
for (UserFederationProviderModel fedProviderModel : fedProviderModels) {
|
||||
fedProviders.add(getFederationProvider(fedProviderModel));
|
||||
}
|
||||
return session.userStorage().validCredentials(realm, user, input);
|
||||
|
||||
CredentialValidationOutput result = null;
|
||||
for (UserCredentialModel cred : input) {
|
||||
UserFederationProvider providerSupportingCreds = null;
|
||||
|
||||
// Find provider, which supports required credential type
|
||||
for (UserFederationProvider fedProvider : fedProviders) {
|
||||
if (fedProvider.getSupportedCredentialTypes().contains(cred.getType())) {
|
||||
providerSupportingCreds = fedProvider;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (providerSupportingCreds == null) {
|
||||
logger.warn("Don't have provider supporting credentials of type " + cred.getType());
|
||||
return CredentialValidationOutput.failed();
|
||||
}
|
||||
|
||||
CredentialValidationOutput currentResult = providerSupportingCreds.validCredentials(realm, cred);
|
||||
result = (result == null) ? currentResult : result.merge(currentResult);
|
||||
}
|
||||
|
||||
// For now, validCredentials(realm, input) is not supported for local userProviders
|
||||
return (result != null) ? result : CredentialValidationOutput.failed();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -130,6 +130,14 @@ public interface UserFederationProvider extends Provider {
|
||||
*/
|
||||
Set<String> getSupportedCredentialTypes(UserModel user);
|
||||
|
||||
/**
|
||||
* What UserCredentialModel types should be handled by this provider? This is called in scenarios when we don't know user,
|
||||
* who is going to authenticate (For example Kerberos authentication).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Set<String> getSupportedCredentialTypes();
|
||||
|
||||
/**
|
||||
* Validate credentials for this user. This method will only be called with credential parameters supported
|
||||
* by this provider
|
||||
@@ -141,6 +149,15 @@ public interface UserFederationProvider extends Provider {
|
||||
*/
|
||||
boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input);
|
||||
boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input);
|
||||
|
||||
/**
|
||||
* Validate credentials of unknown user. The authenticated user is recognized based on provided credentials and returned back in CredentialValidationOutput
|
||||
* @param realm
|
||||
* @param input
|
||||
* @return
|
||||
*/
|
||||
CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential);
|
||||
|
||||
void close();
|
||||
|
||||
}
|
||||
@@ -43,5 +43,7 @@ public interface UserProvider extends Provider {
|
||||
|
||||
boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input);
|
||||
boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input);
|
||||
CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input);
|
||||
|
||||
void close();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.keycloak.models.utils;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class KerberosConstants {
|
||||
|
||||
/**
|
||||
* Value of HTTP Headers "WWW-Authenticate" or "Authorization" used for SPNEGO/Kerberos
|
||||
**/
|
||||
public static final String NEGOTIATE = "Negotiate";
|
||||
|
||||
/**
|
||||
* OID of SPNEGO mechanism. See http://www.oid-info.com/get/1.3.6.1.5.5.2
|
||||
*/
|
||||
public static final String SPNEGO_OID = "1.3.6.1.5.5.2";
|
||||
|
||||
/**
|
||||
* OID of Kerberos v5 mechanism. See http://www.oid-info.com/get/1.2.840.113554.1.2.2
|
||||
*/
|
||||
public static final String KRB5_OID = "1.2.840.113554.1.2.2";
|
||||
|
||||
/**
|
||||
* Configuration federation provider model attribute. It's always true for KerberosFederationProvider and configurable for LDAPFederationProvider
|
||||
*/
|
||||
public static final String ALLOW_KERBEROS_AUTHENTICATION = "allowKerberosAuthentication";
|
||||
|
||||
/**
|
||||
* Internal attribute used in "state" map . Contains token to be passed in HTTP Response back to browser to continue handshake
|
||||
*/
|
||||
public static final String RESPONSE_TOKEN = "SpnegoResponseToken";
|
||||
|
||||
/**
|
||||
* Internal attribute used in "state" map . Contains credential from SPNEGO/Kerberos successful authentication
|
||||
*/
|
||||
public static final String GSS_DELEGATION_CREDENTIAL = "GssDelegationCredential";
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user