Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Bill Burke committed 2015-02-20 09:23:18 -05:00
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";
}