Merge pull request #1146 from patriot1burke/master
phased broker mapper changes
This commit is contained in:
commit
476da4e3e0
53 changed files with 1079 additions and 587 deletions
|
@ -18,8 +18,11 @@
|
||||||
package org.keycloak.broker.provider;
|
package org.keycloak.broker.provider;
|
||||||
|
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
|
import org.keycloak.models.ClientSessionModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
|
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
@ -59,4 +62,19 @@ public abstract class AbstractIdentityProvider<C extends IdentityProviderModel>
|
||||||
public Response keycloakInitiatedBrowserLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
|
public Response keycloakInitiatedBrowserLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attachUserSession(UserSessionModel userSession, ClientSessionModel clientSession, BrokeredIdentityContext context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, BrokeredIdentityContext context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, BrokeredIdentityContext context) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,25 +17,33 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.broker.provider;
|
package org.keycloak.broker.provider;
|
||||||
|
|
||||||
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Represents all identity information obtained from an {@link IdentityProvider} after a
|
* <p>Represents all identity information obtained from an {@link org.keycloak.broker.provider.IdentityProvider} after a
|
||||||
* successful authentication.</p>
|
* successful authentication.</p>
|
||||||
*
|
*
|
||||||
* @author Pedro Igor
|
* @author Pedro Igor
|
||||||
*/
|
*/
|
||||||
public class FederatedIdentity {
|
public class BrokeredIdentityContext {
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private String username;
|
private String username;
|
||||||
|
private String email;
|
||||||
private String firstName;
|
private String firstName;
|
||||||
private String lastName;
|
private String lastName;
|
||||||
private String email;
|
|
||||||
private String token;
|
|
||||||
private String identityProviderId;
|
|
||||||
private String brokerSessionId;
|
private String brokerSessionId;
|
||||||
private String brokerUserId;
|
private String brokerUserId;
|
||||||
|
private String code;
|
||||||
|
private String token;
|
||||||
|
private IdentityProviderModel idpConfig;
|
||||||
|
private IdentityProvider idp;
|
||||||
|
private Map<String, Object> contextData = new HashMap<>();
|
||||||
|
|
||||||
public FederatedIdentity(String id) {
|
public BrokeredIdentityContext(String id) {
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
throw new RuntimeException("No identifier provider for identity.");
|
throw new RuntimeException("No identifier provider for identity.");
|
||||||
}
|
}
|
||||||
|
@ -59,26 +67,6 @@ public class FederatedIdentity {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFirstName() {
|
|
||||||
return firstName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
if (name != null) {
|
|
||||||
int i = name.lastIndexOf(' ');
|
|
||||||
if (i != -1) {
|
|
||||||
firstName = name.substring(0, i);
|
|
||||||
lastName = name.substring(i + 1);
|
|
||||||
} else {
|
|
||||||
firstName = name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLastName() {
|
|
||||||
return lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEmail() {
|
public String getEmail() {
|
||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
|
@ -87,23 +75,6 @@ public class FederatedIdentity {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setToken(String token) {
|
|
||||||
this.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getToken() {
|
|
||||||
return this.token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getIdentityProviderId() {
|
|
||||||
return this.identityProviderId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIdentityProviderId(String identityProviderId) {
|
|
||||||
this.identityProviderId = identityProviderId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getBrokerSessionId() {
|
public String getBrokerSessionId() {
|
||||||
return brokerSessionId;
|
return brokerSessionId;
|
||||||
}
|
}
|
||||||
|
@ -120,16 +91,81 @@ public class FederatedIdentity {
|
||||||
this.brokerUserId = brokerUserId;
|
this.brokerUserId = brokerUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken(String token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdentityProviderModel getIdpConfig() {
|
||||||
|
return idpConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdpConfig(IdentityProviderModel idpConfig) {
|
||||||
|
this.idpConfig = idpConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdentityProvider getIdp() {
|
||||||
|
return idp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdp(IdentityProvider idp) {
|
||||||
|
this.idp = idp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getContextData() {
|
||||||
|
return contextData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContextData(Map<String, Object> contextData) {
|
||||||
|
this.contextData = contextData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
if (name != null) {
|
||||||
|
int i = name.lastIndexOf(' ');
|
||||||
|
if (i != -1) {
|
||||||
|
firstName = name.substring(0, i);
|
||||||
|
lastName = name.substring(i + 1);
|
||||||
|
} else {
|
||||||
|
firstName = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "{" +
|
return "{" +
|
||||||
"id='" + id + '\'' +
|
"id='" + id + '\'' +
|
||||||
", username='" + username + '\'' +
|
", username='" + username + '\'' +
|
||||||
", firstName='" + firstName + '\'' +
|
|
||||||
", lastName='" + lastName + '\'' +
|
|
||||||
", email='" + email + '\'' +
|
", email='" + email + '\'' +
|
||||||
", token='" + token + '\'' +
|
|
||||||
", identityProviderId='" + identityProviderId + '\'' +
|
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,15 +18,17 @@
|
||||||
package org.keycloak.broker.provider;
|
package org.keycloak.broker.provider;
|
||||||
|
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
|
import org.keycloak.models.ClientSessionModel;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
|
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pedro Igor
|
* @author Pedro Igor
|
||||||
|
@ -38,15 +40,16 @@ public interface IdentityProvider<C extends IdentityProviderModel> extends Provi
|
||||||
* This method should be called by provider after the JAXRS callback endpoint has finished authentication
|
* This method should be called by provider after the JAXRS callback endpoint has finished authentication
|
||||||
* with the remote IDP
|
* with the remote IDP
|
||||||
*
|
*
|
||||||
* @param userNotes notes to add to the UserSessionModel
|
* @param context
|
||||||
* @param identityProviderConfig provider config
|
|
||||||
* @param federatedIdentity federated identity
|
|
||||||
* @param code relayState or state parameter used to identity the client session
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Response authenticated(Map<String, String> userNotes, IdentityProviderModel identityProviderConfig, FederatedIdentity federatedIdentity, String code);
|
public Response authenticated(BrokeredIdentityContext context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void attachUserSession(UserSessionModel userSession, ClientSessionModel clientSession, BrokeredIdentityContext context);
|
||||||
|
void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, BrokeredIdentityContext context);
|
||||||
|
void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, BrokeredIdentityContext context);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JAXRS callback endpoint for when the remote IDP wants to callback to keycloak.
|
* JAXRS callback endpoint for when the remote IDP wants to callback to keycloak.
|
||||||
*
|
*
|
||||||
|
@ -58,17 +61,11 @@ public interface IdentityProvider<C extends IdentityProviderModel> extends Provi
|
||||||
* <p>Initiates the authentication process by sending an authentication request to an identity provider. This method is called
|
* <p>Initiates the authentication process by sending an authentication request to an identity provider. This method is called
|
||||||
* only once during the authentication.</p>
|
* only once during the authentication.</p>
|
||||||
*
|
*
|
||||||
* <p>Depending on how the authentication is performed, this method may redirect the user to the identity provider for authentication.
|
|
||||||
* In this case, the response would contain a {@link javax.ws.rs.core.Response} that will be used to redirect the user.</p>
|
|
||||||
*
|
|
||||||
* <p>However, if the authentication flow does not require a redirect to the identity provider (eg.: simple challenge/response mechanism), this method may return a response containing
|
|
||||||
* a {@link FederatedIdentity} representing the identity information for an user. In this case, the authentication flow stops.</p>
|
|
||||||
*
|
|
||||||
* @param request The initial authentication request. Contains all the contextual information in order to build an authentication request to the
|
* @param request The initial authentication request. Contains all the contextual information in order to build an authentication request to the
|
||||||
* identity provider.
|
* identity provider.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Response handleRequest(AuthenticationRequest request);
|
Response performLogin(AuthenticationRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Returns a {@link javax.ws.rs.core.Response} containing the token previously stored during the authentication process for a
|
* <p>Returns a {@link javax.ws.rs.core.Response} containing the token previously stored during the authentication process for a
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.keycloak.broker.provider;
|
||||||
|
|
||||||
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.provider.ConfiguredProvider;
|
||||||
|
import org.keycloak.provider.Provider;
|
||||||
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public interface IdentityProviderMapper extends Provider, ProviderFactory<IdentityProviderMapper>,ConfiguredProvider {
|
||||||
|
String[] getCompatibleProviders();
|
||||||
|
String getDisplayCategory();
|
||||||
|
String getDisplayType();
|
||||||
|
|
||||||
|
void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
|
||||||
|
void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package org.keycloak.broker.provider;
|
||||||
|
|
||||||
|
import org.keycloak.provider.Provider;
|
||||||
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
import org.keycloak.provider.Spi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
*/
|
||||||
|
public class IdentityProviderMapperSpi implements Spi {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "identity-provider-mapper";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends Provider> getProviderClass() {
|
||||||
|
return IdentityProviderMapper.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends ProviderFactory> getProviderFactoryClass() {
|
||||||
|
return IdentityProviderMapper.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1 +1,2 @@
|
||||||
org.keycloak.broker.provider.IdentityProviderSpi
|
org.keycloak.broker.provider.IdentityProviderSpi
|
||||||
|
org.keycloak.broker.provider.IdentityProviderMapperSpi
|
|
@ -25,7 +25,7 @@ import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.broker.oidc.util.SimpleHttp;
|
import org.keycloak.broker.oidc.util.SimpleHttp;
|
||||||
import org.keycloak.broker.provider.AbstractIdentityProvider;
|
import org.keycloak.broker.provider.AbstractIdentityProvider;
|
||||||
import org.keycloak.broker.provider.AuthenticationRequest;
|
import org.keycloak.broker.provider.AuthenticationRequest;
|
||||||
import org.keycloak.broker.provider.FederatedIdentity;
|
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||||
import org.keycloak.events.Errors;
|
import org.keycloak.events.Errors;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
|
@ -33,8 +33,8 @@ import org.keycloak.events.EventType;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.services.messages.Messages;
|
|
||||||
import org.keycloak.services.ErrorPage;
|
import org.keycloak.services.ErrorPage;
|
||||||
|
import org.keycloak.services.messages.Messages;
|
||||||
|
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
|
@ -45,8 +45,6 @@ import javax.ws.rs.core.UriBuilder;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -87,7 +85,7 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response handleRequest(AuthenticationRequest request) {
|
public Response performLogin(AuthenticationRequest request) {
|
||||||
try {
|
try {
|
||||||
URI authorizationUrl = createAuthorizationUrl(request).build();
|
URI authorizationUrl = createAuthorizationUrl(request).build();
|
||||||
|
|
||||||
|
@ -136,7 +134,7 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FederatedIdentity getFederatedIdentity(Map<String, String> notes, String response) {
|
protected BrokeredIdentityContext getFederatedIdentity(String response) {
|
||||||
String accessToken = extractTokenFromResponse(response, OAUTH2_PARAMETER_ACCESS_TOKEN);
|
String accessToken = extractTokenFromResponse(response, OAUTH2_PARAMETER_ACCESS_TOKEN);
|
||||||
|
|
||||||
if (accessToken == null) {
|
if (accessToken == null) {
|
||||||
|
@ -147,7 +145,7 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected FederatedIdentity doGetFederatedIdentity(String accessToken) {
|
protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,14 +223,17 @@ public abstract class AbstractOAuth2IdentityProvider<C extends OAuth2IdentityPro
|
||||||
if (authorizationCode != null) {
|
if (authorizationCode != null) {
|
||||||
String response = generateTokenRequest(authorizationCode).asString();
|
String response = generateTokenRequest(authorizationCode).asString();
|
||||||
|
|
||||||
HashMap<String, String> userNotes = new HashMap<String, String>();
|
BrokeredIdentityContext federatedIdentity = getFederatedIdentity(response);
|
||||||
FederatedIdentity federatedIdentity = getFederatedIdentity(userNotes, response);
|
|
||||||
|
|
||||||
if (getConfig().isStoreToken()) {
|
if (getConfig().isStoreToken()) {
|
||||||
federatedIdentity.setToken(response);
|
federatedIdentity.setToken(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
return callback.authenticated(userNotes, getConfig(), federatedIdentity, state);
|
federatedIdentity.setCode(state);
|
||||||
|
federatedIdentity.setIdpConfig(getConfig());
|
||||||
|
federatedIdentity.setIdp(AbstractOAuth2IdentityProvider.this);
|
||||||
|
|
||||||
|
return callback.authenticated(federatedIdentity);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Failed to make identity provider oauth callback", e);
|
logger.error("Failed to make identity provider oauth callback", e);
|
||||||
|
|
|
@ -95,4 +95,6 @@ public class KeycloakOIDCIdentityProvider extends OIDCIdentityProvider {
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,7 @@ package org.keycloak.broker.oidc;
|
||||||
|
|
||||||
import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
|
import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
|
|
||||||
import org.keycloak.util.JsonSerialization;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
|
@ -21,22 +21,24 @@ import org.codehaus.jackson.JsonNode;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.broker.oidc.util.SimpleHttp;
|
import org.keycloak.broker.oidc.util.SimpleHttp;
|
||||||
import org.keycloak.broker.provider.AuthenticationRequest;
|
import org.keycloak.broker.provider.AuthenticationRequest;
|
||||||
import org.keycloak.broker.provider.FederatedIdentity;
|
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||||
import org.keycloak.events.Errors;
|
import org.keycloak.events.Errors;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
import org.keycloak.events.EventType;
|
import org.keycloak.events.EventType;
|
||||||
import org.keycloak.jose.jws.JWSInput;
|
import org.keycloak.jose.jws.JWSInput;
|
||||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||||
|
import org.keycloak.models.ClientSessionModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.representations.AccessTokenResponse;
|
import org.keycloak.representations.AccessTokenResponse;
|
||||||
import org.keycloak.representations.IDToken;
|
import org.keycloak.representations.IDToken;
|
||||||
|
import org.keycloak.representations.JsonWebToken;
|
||||||
|
import org.keycloak.services.ErrorPage;
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
import org.keycloak.services.messages.Messages;
|
import org.keycloak.services.messages.Messages;
|
||||||
import org.keycloak.services.resources.IdentityBrokerService;
|
import org.keycloak.services.resources.IdentityBrokerService;
|
||||||
import org.keycloak.services.resources.RealmsResource;
|
import org.keycloak.services.resources.RealmsResource;
|
||||||
import org.keycloak.services.ErrorPage;
|
|
||||||
import org.keycloak.util.JsonSerialization;
|
import org.keycloak.util.JsonSerialization;
|
||||||
import org.keycloak.util.PemUtils;
|
import org.keycloak.util.PemUtils;
|
||||||
|
|
||||||
|
@ -49,7 +51,6 @@ import javax.ws.rs.core.UriBuilder;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Pedro Igor
|
* @author Pedro Igor
|
||||||
|
@ -60,6 +61,9 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
|
||||||
public static final String OAUTH2_PARAMETER_PROMPT = "prompt";
|
public static final String OAUTH2_PARAMETER_PROMPT = "prompt";
|
||||||
public static final String SCOPE_OPENID = "openid";
|
public static final String SCOPE_OPENID = "openid";
|
||||||
public static final String FEDERATED_ID_TOKEN = "FEDERATED_ID_TOKEN";
|
public static final String FEDERATED_ID_TOKEN = "FEDERATED_ID_TOKEN";
|
||||||
|
public static final String USER_INFO = "UserInfo";
|
||||||
|
public static final String FEDERATED_ACCESS_TOKEN_RESPONSE = "FEDERATED_ACCESS_TOKEN_RESPONSE";
|
||||||
|
public static final String VALIDATED_ID_TOKEN = "VALIDATED_ID_TOKEN";
|
||||||
|
|
||||||
public OIDCIdentityProvider(OIDCIdentityProviderConfig config) {
|
public OIDCIdentityProvider(OIDCIdentityProviderConfig config) {
|
||||||
super(config);
|
super(config);
|
||||||
|
@ -157,7 +161,7 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FederatedIdentity getFederatedIdentity(Map<String, String> notes, String response) {
|
protected BrokeredIdentityContext getFederatedIdentity(String response) {
|
||||||
AccessTokenResponse tokenResponse = null;
|
AccessTokenResponse tokenResponse = null;
|
||||||
try {
|
try {
|
||||||
tokenResponse = JsonSerialization.readValue(response, AccessTokenResponse.class);
|
tokenResponse = JsonSerialization.readValue(response, AccessTokenResponse.class);
|
||||||
|
@ -169,21 +173,18 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
|
||||||
|
|
||||||
String encodedIdToken = tokenResponse.getIdToken();
|
String encodedIdToken = tokenResponse.getIdToken();
|
||||||
|
|
||||||
notes.put(FEDERATED_ACCESS_TOKEN, accessToken);
|
|
||||||
notes.put(FEDERATED_ID_TOKEN, encodedIdToken);
|
|
||||||
notes.put(FEDERATED_REFRESH_TOKEN, tokenResponse.getRefreshToken());
|
|
||||||
notes.put(FEDERATED_TOKEN_EXPIRATION, Long.toString(tokenResponse.getExpiresIn()));
|
|
||||||
|
|
||||||
|
|
||||||
IDToken idToken = validateIdToken(key, encodedIdToken);
|
JsonWebToken idToken = validateIdToken(key, encodedIdToken);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String id = idToken.getSubject();
|
String id = idToken.getSubject();
|
||||||
String name = idToken.getName();
|
BrokeredIdentityContext identity = new BrokeredIdentityContext(id);
|
||||||
String preferredUsername = idToken.getPreferredUsername();
|
String name = (String)idToken.getOtherClaims().get(IDToken.NAME);
|
||||||
String email = idToken.getEmail();
|
String preferredUsername = (String)idToken.getOtherClaims().get(IDToken.PREFERRED_USERNAME);
|
||||||
|
String email = (String)idToken.getOtherClaims().get(IDToken.EMAIL);
|
||||||
|
|
||||||
if (id == null || name == null || preferredUsername == null || email == null && getConfig().getUserInfoUrl() != null) {
|
if (getConfig().getUserInfoUrl() != null && (id == null || name == null || preferredUsername == null || email == null) ) {
|
||||||
JsonNode userInfo = SimpleHttp.doGet(getConfig().getUserInfoUrl())
|
JsonNode userInfo = SimpleHttp.doGet(getConfig().getUserInfoUrl())
|
||||||
.header("Authorization", "Bearer " + accessToken)
|
.header("Authorization", "Bearer " + accessToken)
|
||||||
.asJson();
|
.asJson();
|
||||||
|
@ -192,9 +193,10 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
|
||||||
name = getJsonProperty(userInfo, "name");
|
name = getJsonProperty(userInfo, "name");
|
||||||
preferredUsername = getJsonProperty(userInfo, "preferred_username");
|
preferredUsername = getJsonProperty(userInfo, "preferred_username");
|
||||||
email = getJsonProperty(userInfo, "email");
|
email = getJsonProperty(userInfo, "email");
|
||||||
|
identity.getContextData().put(USER_INFO, userInfo);
|
||||||
}
|
}
|
||||||
|
identity.getContextData().put(FEDERATED_ACCESS_TOKEN_RESPONSE, tokenResponse);
|
||||||
FederatedIdentity identity = new FederatedIdentity(id);
|
identity.getContextData().put(VALIDATED_ID_TOKEN, idToken);
|
||||||
|
|
||||||
identity.setId(id);
|
identity.setId(id);
|
||||||
identity.setName(name);
|
identity.setName(name);
|
||||||
|
@ -234,7 +236,7 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
|
||||||
return accessToken;
|
return accessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IDToken validateIdToken(PublicKey key, String encodedToken) {
|
private JsonWebToken validateIdToken(PublicKey key, String encodedToken) {
|
||||||
if (encodedToken == null) {
|
if (encodedToken == null) {
|
||||||
throw new IdentityBrokerException("No id_token from server.");
|
throw new IdentityBrokerException("No id_token from server.");
|
||||||
}
|
}
|
||||||
|
@ -244,7 +246,7 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
|
||||||
if (!verify(jws, key)) {
|
if (!verify(jws, key)) {
|
||||||
throw new IdentityBrokerException("IDToken signature validation failed");
|
throw new IdentityBrokerException("IDToken signature validation failed");
|
||||||
}
|
}
|
||||||
IDToken idToken = jws.readJsonContent(IDToken.class);
|
JsonWebToken idToken = jws.readJsonContent(JsonWebToken.class);
|
||||||
|
|
||||||
String aud = idToken.getAudience();
|
String aud = idToken.getAudience();
|
||||||
String iss = idToken.getIssuer();
|
String iss = idToken.getIssuer();
|
||||||
|
@ -272,6 +274,13 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attachUserSession(UserSessionModel userSession, ClientSessionModel clientSession, BrokeredIdentityContext context) {
|
||||||
|
AccessTokenResponse tokenResponse = (AccessTokenResponse)context.getContextData().get(FEDERATED_ACCESS_TOKEN_RESPONSE);
|
||||||
|
userSession.setNote(FEDERATED_ACCESS_TOKEN, tokenResponse.getToken());
|
||||||
|
userSession.setNote(FEDERATED_ID_TOKEN, tokenResponse.getIdToken());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getDefaultScopes() {
|
protected String getDefaultScopes() {
|
||||||
return "openid";
|
return "openid";
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.broker.oidc;
|
package org.keycloak.broker.oidc;
|
||||||
|
|
||||||
import org.codehaus.jackson.annotate.JsonProperty;
|
|
||||||
import org.keycloak.broker.oidc.util.SimpleHttp;
|
import org.keycloak.broker.oidc.util.SimpleHttp;
|
||||||
import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
|
import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
|
||||||
import org.keycloak.jose.jwk.JWK;
|
import org.keycloak.jose.jwk.JWK;
|
||||||
|
@ -27,7 +26,6 @@ import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
import org.keycloak.protocol.oidc.representations.JSONWebKeySet;
|
import org.keycloak.protocol.oidc.representations.JSONWebKeySet;
|
||||||
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
|
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
|
||||||
import org.keycloak.util.JsonSerialization;
|
import org.keycloak.util.JsonSerialization;
|
||||||
import org.keycloak.util.PemUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
33
broker/oidc/src/test/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProviderTest.java
Normal file → Executable file
33
broker/oidc/src/test/java/org/keycloak/broker/oidc/AbstractOAuth2IdentityProviderTest.java
Normal file → Executable file
|
@ -5,17 +5,17 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.broker.oidc;
|
package org.keycloak.broker.oidc;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.codehaus.jackson.JsonNode;
|
import org.codehaus.jackson.JsonNode;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.broker.provider.FederatedIdentity;
|
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit test for {@link AbstractOAuth2IdentityProvider}
|
* Unit test for {@link AbstractOAuth2IdentityProvider}
|
||||||
*
|
*
|
||||||
|
@ -58,45 +58,41 @@ public class AbstractOAuth2IdentityProviderTest {
|
||||||
@Test(expected = IdentityBrokerException.class)
|
@Test(expected = IdentityBrokerException.class)
|
||||||
public void getFederatedIdentity_responseUrlLine_tokenNotFound() {
|
public void getFederatedIdentity_responseUrlLine_tokenNotFound() {
|
||||||
TestProvider tested = getTested();
|
TestProvider tested = getTested();
|
||||||
Map<String, String> notes = new HashMap<>();
|
tested.getFederatedIdentity("cosi=sss");
|
||||||
tested.getFederatedIdentity(notes, "cosi=sss");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IdentityBrokerException.class)
|
@Test(expected = IdentityBrokerException.class)
|
||||||
public void getFederatedIdentity_responseJSON_tokenNotFound() {
|
public void getFederatedIdentity_responseJSON_tokenNotFound() {
|
||||||
TestProvider tested = getTested();
|
TestProvider tested = getTested();
|
||||||
Map<String, String> notes = new HashMap<>();
|
Map<String, String> notes = new HashMap<>();
|
||||||
tested.getFederatedIdentity(notes, "{\"cosi\":\"sss\"}");
|
tested.getFederatedIdentity("{\"cosi\":\"sss\"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IdentityBrokerException.class)
|
@Test(expected = IdentityBrokerException.class)
|
||||||
public void getFederatedIdentity_responseJSON_invalidFormat() {
|
public void getFederatedIdentity_responseJSON_invalidFormat() {
|
||||||
TestProvider tested = getTested();
|
TestProvider tested = getTested();
|
||||||
Map<String, String> notes = new HashMap<>();
|
Map<String, String> notes = new HashMap<>();
|
||||||
tested.getFederatedIdentity(notes, "{\"cosi\":\"sss\"");
|
tested.getFederatedIdentity("{\"cosi\":\"sss\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IdentityBrokerException.class)
|
@Test(expected = IdentityBrokerException.class)
|
||||||
public void getFederatedIdentity_responseJSON_emptyTokenField() {
|
public void getFederatedIdentity_responseJSON_emptyTokenField() {
|
||||||
TestProvider tested = getTested();
|
TestProvider tested = getTested();
|
||||||
Map<String, String> notes = new HashMap<>();
|
tested.getFederatedIdentity("{\""
|
||||||
tested.getFederatedIdentity(notes, "{\""
|
|
||||||
+ AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "\" : \"\"}");
|
+ AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "\" : \"\"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IdentityBrokerException.class)
|
@Test(expected = IdentityBrokerException.class)
|
||||||
public void getFederatedIdentity_responseJSON_nullTokenField() {
|
public void getFederatedIdentity_responseJSON_nullTokenField() {
|
||||||
TestProvider tested = getTested();
|
TestProvider tested = getTested();
|
||||||
Map<String, String> notes = new HashMap<>();
|
tested.getFederatedIdentity("{\""
|
||||||
tested.getFederatedIdentity(notes, "{\""
|
|
||||||
+ AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "\" : null}");
|
+ AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "\" : null}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getFederatedIdentity_responseJSON() {
|
public void getFederatedIdentity_responseJSON() {
|
||||||
TestProvider tested = getTested();
|
TestProvider tested = getTested();
|
||||||
Map<String, String> notes = new HashMap<>();
|
BrokeredIdentityContext fi = tested.getFederatedIdentity("{\""
|
||||||
FederatedIdentity fi = tested.getFederatedIdentity(notes, "{\""
|
|
||||||
+ AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "\" : \"458rt\"}");
|
+ AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "\" : \"458rt\"}");
|
||||||
Assert.assertNotNull(fi);
|
Assert.assertNotNull(fi);
|
||||||
Assert.assertEquals("458rt", fi.getId());
|
Assert.assertEquals("458rt", fi.getId());
|
||||||
|
@ -105,8 +101,7 @@ public class AbstractOAuth2IdentityProviderTest {
|
||||||
@Test
|
@Test
|
||||||
public void getFederatedIdentity_responseUrlLine() {
|
public void getFederatedIdentity_responseUrlLine() {
|
||||||
TestProvider tested = getTested();
|
TestProvider tested = getTested();
|
||||||
Map<String, String> notes = new HashMap<>();
|
BrokeredIdentityContext fi = tested.getFederatedIdentity("cosi=sss&"
|
||||||
FederatedIdentity fi = tested.getFederatedIdentity(notes, "cosi=sss&"
|
|
||||||
+ AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "=458rtf&kdesi=ss}");
|
+ AbstractOAuth2IdentityProvider.OAUTH2_PARAMETER_ACCESS_TOKEN + "=458rtf&kdesi=ss}");
|
||||||
Assert.assertNotNull(fi);
|
Assert.assertNotNull(fi);
|
||||||
Assert.assertEquals("458rtf", fi.getId());
|
Assert.assertEquals("458rtf", fi.getId());
|
||||||
|
@ -129,8 +124,8 @@ public class AbstractOAuth2IdentityProviderTest {
|
||||||
return "default";
|
return "default";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FederatedIdentity doGetFederatedIdentity(String accessToken) {
|
protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
|
||||||
return new FederatedIdentity(accessToken);
|
return new BrokeredIdentityContext(accessToken);
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,9 +3,18 @@ package org.keycloak.broker.saml;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.ClientConnection;
|
import org.keycloak.ClientConnection;
|
||||||
import org.keycloak.VerificationException;
|
import org.keycloak.VerificationException;
|
||||||
import org.keycloak.broker.provider.FederatedIdentity;
|
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||||
import org.keycloak.broker.provider.IdentityProvider;
|
import org.keycloak.broker.provider.IdentityProvider;
|
||||||
|
import org.keycloak.dom.saml.v2.assertion.AssertionType;
|
||||||
|
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
|
||||||
|
import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType;
|
||||||
|
import org.keycloak.dom.saml.v2.assertion.NameIDType;
|
||||||
|
import org.keycloak.dom.saml.v2.assertion.SubjectType;
|
||||||
|
import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
|
||||||
|
import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
|
||||||
|
import org.keycloak.dom.saml.v2.protocol.ResponseType;
|
||||||
|
import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
|
||||||
import org.keycloak.events.Details;
|
import org.keycloak.events.Details;
|
||||||
import org.keycloak.events.Errors;
|
import org.keycloak.events.Errors;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
|
@ -17,9 +26,6 @@ import org.keycloak.protocol.saml.SAML2LogoutResponseBuilder;
|
||||||
import org.keycloak.protocol.saml.SAMLRequestParser;
|
import org.keycloak.protocol.saml.SAMLRequestParser;
|
||||||
import org.keycloak.protocol.saml.SamlProtocol;
|
import org.keycloak.protocol.saml.SamlProtocol;
|
||||||
import org.keycloak.protocol.saml.SamlProtocolUtils;
|
import org.keycloak.protocol.saml.SamlProtocolUtils;
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
|
||||||
import org.keycloak.services.messages.Messages;
|
|
||||||
import org.keycloak.services.ErrorPage;
|
|
||||||
import org.keycloak.saml.common.constants.GeneralConstants;
|
import org.keycloak.saml.common.constants.GeneralConstants;
|
||||||
import org.keycloak.saml.common.constants.JBossSAMLConstants;
|
import org.keycloak.saml.common.constants.JBossSAMLConstants;
|
||||||
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
||||||
|
@ -33,18 +39,15 @@ import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
|
||||||
import org.keycloak.saml.processing.core.util.JAXPValidationUtil;
|
import org.keycloak.saml.processing.core.util.JAXPValidationUtil;
|
||||||
import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
|
import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
|
||||||
import org.keycloak.saml.processing.core.util.XMLSignatureUtil;
|
import org.keycloak.saml.processing.core.util.XMLSignatureUtil;
|
||||||
import org.keycloak.dom.saml.v2.assertion.AssertionType;
|
import org.keycloak.services.ErrorPage;
|
||||||
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType;
|
import org.keycloak.services.messages.Messages;
|
||||||
import org.keycloak.dom.saml.v2.assertion.NameIDType;
|
|
||||||
import org.keycloak.dom.saml.v2.assertion.SubjectType;
|
|
||||||
import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
|
|
||||||
import org.keycloak.dom.saml.v2.protocol.RequestAbstractType;
|
|
||||||
import org.keycloak.dom.saml.v2.protocol.ResponseType;
|
|
||||||
import org.keycloak.dom.saml.v2.protocol.StatusResponseType;
|
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
|
import org.keycloak.services.ErrorPage;
|
||||||
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
|
import org.keycloak.services.messages.Messages;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.FormParam;
|
import javax.ws.rs.FormParam;
|
||||||
|
@ -62,9 +65,7 @@ import java.io.IOException;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -75,10 +76,14 @@ public class SAMLEndpoint {
|
||||||
public static final String SAML_FEDERATED_SESSION_INDEX = "SAML_FEDERATED_SESSION_INDEX";
|
public static final String SAML_FEDERATED_SESSION_INDEX = "SAML_FEDERATED_SESSION_INDEX";
|
||||||
public static final String SAML_FEDERATED_SUBJECT = "SAML_FEDERATED_SUBJECT";
|
public static final String SAML_FEDERATED_SUBJECT = "SAML_FEDERATED_SUBJECT";
|
||||||
public static final String SAML_FEDERATED_SUBJECT_NAMEFORMAT = "SAML_FEDERATED_SUBJECT_NAMEFORMAT";
|
public static final String SAML_FEDERATED_SUBJECT_NAMEFORMAT = "SAML_FEDERATED_SUBJECT_NAMEFORMAT";
|
||||||
|
public static final String SAML_LOGIN_RESPONSE = "SAML_LOGIN_RESPONSE";
|
||||||
|
public static final String SAML_ASSERTION = "SAML_ASSERTION";
|
||||||
|
public static final String SAML_AUTHN_STATEMENT = "SAML_AUTHN_STATEMENT";
|
||||||
protected RealmModel realm;
|
protected RealmModel realm;
|
||||||
protected EventBuilder event;
|
protected EventBuilder event;
|
||||||
protected SAMLIdentityProviderConfig config;
|
protected SAMLIdentityProviderConfig config;
|
||||||
protected IdentityProvider.AuthenticationCallback callback;
|
protected IdentityProvider.AuthenticationCallback callback;
|
||||||
|
protected SAMLIdentityProvider provider;
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
private UriInfo uriInfo;
|
private UriInfo uriInfo;
|
||||||
|
@ -93,10 +98,11 @@ public class SAMLEndpoint {
|
||||||
private HttpHeaders headers;
|
private HttpHeaders headers;
|
||||||
|
|
||||||
|
|
||||||
public SAMLEndpoint(RealmModel realm, SAMLIdentityProviderConfig config, IdentityProvider.AuthenticationCallback callback) {
|
public SAMLEndpoint(RealmModel realm, SAMLIdentityProvider provider, SAMLIdentityProviderConfig config, IdentityProvider.AuthenticationCallback callback) {
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
|
this.provider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
@ -265,10 +271,11 @@ public class SAMLEndpoint {
|
||||||
SubjectType subject = assertion.getSubject();
|
SubjectType subject = assertion.getSubject();
|
||||||
SubjectType.STSubType subType = subject.getSubType();
|
SubjectType.STSubType subType = subject.getSubType();
|
||||||
NameIDType subjectNameID = (NameIDType) subType.getBaseID();
|
NameIDType subjectNameID = (NameIDType) subType.getBaseID();
|
||||||
Map<String, String> notes = new HashMap<>();
|
//Map<String, String> notes = new HashMap<>();
|
||||||
notes.put(SAML_FEDERATED_SUBJECT, subjectNameID.getValue());
|
BrokeredIdentityContext identity = new BrokeredIdentityContext(subjectNameID.getValue());
|
||||||
if (subjectNameID.getFormat() != null) notes.put(SAML_FEDERATED_SUBJECT_NAMEFORMAT, subjectNameID.getFormat().toString());
|
identity.setCode(relayState);
|
||||||
FederatedIdentity identity = new FederatedIdentity(subjectNameID.getValue());
|
identity.getContextData().put(SAML_LOGIN_RESPONSE, responseType);
|
||||||
|
identity.getContextData().put(SAML_ASSERTION, assertion);
|
||||||
|
|
||||||
identity.setUsername(subjectNameID.getValue());
|
identity.setUsername(subjectNameID.getValue());
|
||||||
|
|
||||||
|
@ -284,24 +291,28 @@ public class SAMLEndpoint {
|
||||||
for (Object statement : assertion.getStatements()) {
|
for (Object statement : assertion.getStatements()) {
|
||||||
if (statement instanceof AuthnStatementType) {
|
if (statement instanceof AuthnStatementType) {
|
||||||
authn = (AuthnStatementType)statement;
|
authn = (AuthnStatementType)statement;
|
||||||
|
identity.getContextData().put(SAML_AUTHN_STATEMENT, authn);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String brokerUserId = config.getAlias() + "." + subjectNameID.getValue();
|
String brokerUserId = config.getAlias() + "." + subjectNameID.getValue();
|
||||||
identity.setBrokerUserId(brokerUserId);
|
identity.setBrokerUserId(brokerUserId);
|
||||||
|
identity.setIdpConfig(config);
|
||||||
|
identity.setIdp(provider);
|
||||||
if (authn != null && authn.getSessionIndex() != null) {
|
if (authn != null && authn.getSessionIndex() != null) {
|
||||||
identity.setBrokerSessionId(identity.getBrokerUserId() + "." + authn.getSessionIndex());
|
identity.setBrokerSessionId(identity.getBrokerUserId() + "." + authn.getSessionIndex());
|
||||||
notes.put(SAML_FEDERATED_SESSION_INDEX, authn.getSessionIndex());
|
|
||||||
}
|
}
|
||||||
return callback.authenticated(notes, config, identity, relayState);
|
|
||||||
|
|
||||||
|
return callback.authenticated(identity);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IdentityBrokerException("Could not process response from SAML identity provider.", e);
|
throw new IdentityBrokerException("Could not process response from SAML identity provider.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private AssertionType getAssertion(ResponseType responseType) throws ProcessingException {
|
private AssertionType getAssertion(ResponseType responseType) throws ProcessingException {
|
||||||
List<ResponseType.RTChoiceType> assertions = responseType.getAssertions();
|
List<ResponseType.RTChoiceType> assertions = responseType.getAssertions();
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,15 @@ package org.keycloak.broker.saml;
|
||||||
|
|
||||||
import org.keycloak.broker.provider.AbstractIdentityProvider;
|
import org.keycloak.broker.provider.AbstractIdentityProvider;
|
||||||
import org.keycloak.broker.provider.AuthenticationRequest;
|
import org.keycloak.broker.provider.AuthenticationRequest;
|
||||||
|
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||||
|
import org.keycloak.dom.saml.v2.assertion.AssertionType;
|
||||||
|
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
|
||||||
|
import org.keycloak.dom.saml.v2.assertion.NameIDType;
|
||||||
|
import org.keycloak.dom.saml.v2.assertion.SubjectType;
|
||||||
|
import org.keycloak.dom.saml.v2.protocol.ResponseType;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
|
import org.keycloak.models.ClientSessionModel;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
|
@ -47,11 +54,11 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object callback(RealmModel realm, AuthenticationCallback callback, EventBuilder event) {
|
public Object callback(RealmModel realm, AuthenticationCallback callback, EventBuilder event) {
|
||||||
return new SAMLEndpoint(realm, getConfig(), callback);
|
return new SAMLEndpoint(realm, this, getConfig(), callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response handleRequest(AuthenticationRequest request) {
|
public Response performLogin(AuthenticationRequest request) {
|
||||||
try {
|
try {
|
||||||
UriInfo uriInfo = request.getUriInfo();
|
UriInfo uriInfo = request.getUriInfo();
|
||||||
RealmModel realm = request.getRealm();
|
RealmModel realm = request.getRealm();
|
||||||
|
@ -112,6 +119,22 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
|
||||||
return UriBuilder.fromUri(uriInfo.getBaseUri()).path("realms").path(realm.getName()).build().toString();
|
return UriBuilder.fromUri(uriInfo.getBaseUri()).path("realms").path(realm.getName()).build().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attachUserSession(UserSessionModel userSession, ClientSessionModel clientSession, BrokeredIdentityContext context) {
|
||||||
|
ResponseType responseType = (ResponseType)context.getContextData().get(SAMLEndpoint.SAML_LOGIN_RESPONSE);
|
||||||
|
AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
|
||||||
|
SubjectType subject = assertion.getSubject();
|
||||||
|
SubjectType.STSubType subType = subject.getSubType();
|
||||||
|
NameIDType subjectNameID = (NameIDType) subType.getBaseID();
|
||||||
|
userSession.setNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT, subjectNameID.getValue());
|
||||||
|
if (subjectNameID.getFormat() != null) userSession.setNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT_NAMEFORMAT, subjectNameID.getFormat().toString());
|
||||||
|
AuthnStatementType authn = (AuthnStatementType)context.getContextData().get(SAMLEndpoint.SAML_AUTHN_STATEMENT);
|
||||||
|
if (authn != null && authn.getSessionIndex() != null) {
|
||||||
|
userSession.setNote(SAMLEndpoint.SAML_FEDERATED_SESSION_INDEX, authn.getSessionIndex());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response retrieveToken(FederatedIdentityModel identity) {
|
public Response retrieveToken(FederatedIdentityModel identity) {
|
||||||
return Response.ok(identity.getToken()).build();
|
return Response.ok(identity.getToken()).build();
|
||||||
|
|
|
@ -18,17 +18,17 @@
|
||||||
package org.keycloak.broker.saml;
|
package org.keycloak.broker.saml;
|
||||||
|
|
||||||
import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
|
import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
|
||||||
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
|
||||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
|
||||||
import org.keycloak.saml.common.util.DocumentUtil;
|
|
||||||
import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
|
|
||||||
import org.keycloak.dom.saml.v2.metadata.EndpointType;
|
import org.keycloak.dom.saml.v2.metadata.EndpointType;
|
||||||
import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType;
|
import org.keycloak.dom.saml.v2.metadata.EntitiesDescriptorType;
|
||||||
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
|
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
|
||||||
import org.keycloak.dom.saml.v2.metadata.IDPSSODescriptorType;
|
import org.keycloak.dom.saml.v2.metadata.IDPSSODescriptorType;
|
||||||
import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
|
import org.keycloak.dom.saml.v2.metadata.KeyDescriptorType;
|
||||||
import org.keycloak.dom.saml.v2.metadata.KeyTypes;
|
import org.keycloak.dom.saml.v2.metadata.KeyTypes;
|
||||||
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
||||||
|
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||||
|
import org.keycloak.saml.common.util.DocumentUtil;
|
||||||
|
import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
|
|
|
@ -7,22 +7,29 @@ import org.codehaus.jackson.annotate.JsonProperty;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class AddressClaimSet {
|
public class AddressClaimSet {
|
||||||
@JsonProperty("formatted")
|
public static final String FORMATTED = "formatted";
|
||||||
|
public static final String STREET_ADDRESS = "street_address";
|
||||||
|
public static final String LOCALITY = "locality";
|
||||||
|
public static final String REGION = "region";
|
||||||
|
public static final String POSTAL_CODE = "postal_code";
|
||||||
|
public static final String COUNTRY = "country";
|
||||||
|
|
||||||
|
@JsonProperty(FORMATTED)
|
||||||
protected String formattedAddress;
|
protected String formattedAddress;
|
||||||
|
|
||||||
@JsonProperty("street_address")
|
@JsonProperty(STREET_ADDRESS)
|
||||||
protected String streetAddress;
|
protected String streetAddress;
|
||||||
|
|
||||||
@JsonProperty("locality")
|
@JsonProperty(LOCALITY)
|
||||||
protected String locality;
|
protected String locality;
|
||||||
|
|
||||||
@JsonProperty("region")
|
@JsonProperty(REGION)
|
||||||
protected String region;
|
protected String region;
|
||||||
|
|
||||||
@JsonProperty("postal_code")
|
@JsonProperty(POSTAL_CODE)
|
||||||
protected String postalCode;
|
protected String postalCode;
|
||||||
|
|
||||||
@JsonProperty("country")
|
@JsonProperty(COUNTRY)
|
||||||
protected String country;
|
protected String country;
|
||||||
|
|
||||||
public String getFormattedAddress() {
|
public String getFormattedAddress() {
|
||||||
|
|
|
@ -13,76 +13,96 @@ import java.util.Map;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class IDToken extends JsonWebToken {
|
public class IDToken extends JsonWebToken {
|
||||||
|
public static final String NONCE = "nonce";
|
||||||
|
public static final String SESSION_STATE = "session_state";
|
||||||
|
public static final String NAME = "name";
|
||||||
|
public static final String GIVEN_NAME = "given_name";
|
||||||
|
public static final String FAMILY_NAME = "family_name";
|
||||||
|
public static final String MIDDLE_NAME = "middle_name";
|
||||||
|
public static final String NICKNAME = "nickname";
|
||||||
|
public static final String PREFERRED_USERNAME = "preferred_username";
|
||||||
|
public static final String PROFILE = "profile";
|
||||||
|
public static final String PICTURE = "picture";
|
||||||
|
public static final String WEBSITE = "website";
|
||||||
|
public static final String EMAIL = "email";
|
||||||
|
public static final String EMAIL_VERIFIED = "email_verified";
|
||||||
|
public static final String GENDER = "gender";
|
||||||
|
public static final String BIRTHDATE = "birthdate";
|
||||||
|
public static final String ZONEINFO = "zoneinfo";
|
||||||
|
public static final String LOCALE = "locale";
|
||||||
|
public static final String PHONE_NUMBER = "phone_number";
|
||||||
|
public static final String PHONE_NUMBER_VERIFIED = "phone_number_verified";
|
||||||
|
public static final String ADDRESS = "address";
|
||||||
|
public static final String UPDATED_AT = "updated_at";
|
||||||
|
public static final String CLAIMS_LOCALES = "claims_locales";
|
||||||
// NOTE!!! WE used to use @JsonUnwrapped on a UserClaimSet object. This screws up otherClaims and the won't work
|
// NOTE!!! WE used to use @JsonUnwrapped on a UserClaimSet object. This screws up otherClaims and the won't work
|
||||||
// anymore. So don't have any @JsonUnwrapped!
|
// anymore. So don't have any @JsonUnwrapped!
|
||||||
@JsonProperty("nonce")
|
@JsonProperty(NONCE)
|
||||||
protected String nonce;
|
protected String nonce;
|
||||||
|
|
||||||
@JsonProperty("session_state")
|
@JsonProperty(SESSION_STATE)
|
||||||
protected String sessionState;
|
protected String sessionState;
|
||||||
|
|
||||||
@JsonProperty("name")
|
@JsonProperty(NAME)
|
||||||
protected String name;
|
protected String name;
|
||||||
|
|
||||||
@JsonProperty("given_name")
|
@JsonProperty(GIVEN_NAME)
|
||||||
protected String givenName;
|
protected String givenName;
|
||||||
|
|
||||||
@JsonProperty("family_name")
|
@JsonProperty(FAMILY_NAME)
|
||||||
protected String familyName;
|
protected String familyName;
|
||||||
|
|
||||||
@JsonProperty("middle_name")
|
@JsonProperty(MIDDLE_NAME)
|
||||||
protected String middleName;
|
protected String middleName;
|
||||||
|
|
||||||
@JsonProperty("nickname")
|
@JsonProperty(NICKNAME)
|
||||||
protected String nickName;
|
protected String nickName;
|
||||||
|
|
||||||
@JsonProperty("preferred_username")
|
@JsonProperty(PREFERRED_USERNAME)
|
||||||
protected String preferredUsername;
|
protected String preferredUsername;
|
||||||
|
|
||||||
@JsonProperty("profile")
|
@JsonProperty(PROFILE)
|
||||||
protected String profile;
|
protected String profile;
|
||||||
|
|
||||||
@JsonProperty("picture")
|
@JsonProperty(PICTURE)
|
||||||
protected String picture;
|
protected String picture;
|
||||||
|
|
||||||
@JsonProperty("website")
|
@JsonProperty(WEBSITE)
|
||||||
protected String website;
|
protected String website;
|
||||||
|
|
||||||
@JsonProperty("email")
|
@JsonProperty(EMAIL)
|
||||||
protected String email;
|
protected String email;
|
||||||
|
|
||||||
@JsonProperty("email_verified")
|
@JsonProperty(EMAIL_VERIFIED)
|
||||||
protected Boolean emailVerified;
|
protected Boolean emailVerified;
|
||||||
|
|
||||||
@JsonProperty("gender")
|
@JsonProperty(GENDER)
|
||||||
protected String gender;
|
protected String gender;
|
||||||
|
|
||||||
@JsonProperty("birthdate")
|
@JsonProperty(BIRTHDATE)
|
||||||
protected String birthdate;
|
protected String birthdate;
|
||||||
|
|
||||||
@JsonProperty("zoneinfo")
|
@JsonProperty(ZONEINFO)
|
||||||
protected String zoneinfo;
|
protected String zoneinfo;
|
||||||
|
|
||||||
@JsonProperty("locale")
|
@JsonProperty(LOCALE)
|
||||||
protected String locale;
|
protected String locale;
|
||||||
|
|
||||||
@JsonProperty("phone_number")
|
@JsonProperty(PHONE_NUMBER)
|
||||||
protected String phoneNumber;
|
protected String phoneNumber;
|
||||||
|
|
||||||
@JsonProperty("phone_number_verified")
|
@JsonProperty(PHONE_NUMBER_VERIFIED)
|
||||||
protected Boolean phoneNumberVerified;
|
protected Boolean phoneNumberVerified;
|
||||||
|
|
||||||
@JsonProperty("address")
|
@JsonProperty(ADDRESS)
|
||||||
protected AddressClaimSet address;
|
protected AddressClaimSet address;
|
||||||
|
|
||||||
@JsonProperty("updated_at")
|
@JsonProperty(UPDATED_AT)
|
||||||
protected Long updatedAt;
|
protected Long updatedAt;
|
||||||
|
|
||||||
@JsonProperty("claims_locales")
|
@JsonProperty(CLAIMS_LOCALES)
|
||||||
protected String claimsLocales;
|
protected String claimsLocales;
|
||||||
|
|
||||||
protected Map<String, Object> otherClaims = new HashMap<String, Object>();
|
|
||||||
|
|
||||||
public String getNonce() {
|
public String getNonce() {
|
||||||
return nonce;
|
return nonce;
|
||||||
}
|
}
|
||||||
|
@ -259,18 +279,4 @@ public class IDToken extends JsonWebToken {
|
||||||
this.claimsLocales = claimsLocales;
|
this.claimsLocales = claimsLocales;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a map of any other claims and data that might be in the IDToken. Could be custom claims set up by the auth server
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@JsonAnyGetter
|
|
||||||
public Map<String, Object> getOtherClaims() {
|
|
||||||
return otherClaims;
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonAnySetter
|
|
||||||
public void setOtherClaims(String name, Object value) {
|
|
||||||
otherClaims.put(name, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package org.keycloak.representations;
|
package org.keycloak.representations;
|
||||||
|
|
||||||
|
import org.codehaus.jackson.annotate.JsonAnyGetter;
|
||||||
|
import org.codehaus.jackson.annotate.JsonAnySetter;
|
||||||
import org.codehaus.jackson.annotate.JsonIgnore;
|
import org.codehaus.jackson.annotate.JsonIgnore;
|
||||||
import org.codehaus.jackson.annotate.JsonProperty;
|
import org.codehaus.jackson.annotate.JsonProperty;
|
||||||
import org.keycloak.util.Time;
|
import org.keycloak.util.Time;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -29,6 +33,7 @@ public class JsonWebToken implements Serializable {
|
||||||
protected String type;
|
protected String type;
|
||||||
@JsonProperty("azp")
|
@JsonProperty("azp")
|
||||||
public String issuedFor;
|
public String issuedFor;
|
||||||
|
protected Map<String, Object> otherClaims = new HashMap<String, Object>();
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
|
@ -153,4 +158,19 @@ public class JsonWebToken implements Serializable {
|
||||||
this.issuedFor = issuedFor;
|
this.issuedFor = issuedFor;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a map of any other claims and data that might be in the IDToken. Could be custom claims set up by the auth server
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@JsonAnyGetter
|
||||||
|
public Map<String, Object> getOtherClaims() {
|
||||||
|
return otherClaims;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonAnySetter
|
||||||
|
public void setOtherClaims(String name, Object value) {
|
||||||
|
otherClaims.put(name, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ConfigPropertyRepresentation {
|
||||||
|
protected String name;
|
||||||
|
protected String label;
|
||||||
|
protected String helpText;
|
||||||
|
protected String type;
|
||||||
|
protected Object defaultValue;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLabel() {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLabel(String label) {
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getDefaultValue() {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultValue(Object defaultValue) {
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHelpText() {
|
||||||
|
return helpText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHelpText(String helpText) {
|
||||||
|
this.helpText = helpText;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class IdentityProviderMapperRepresentation {
|
||||||
|
protected String id;
|
||||||
|
protected String name;
|
||||||
|
protected String identityProviderAlias;
|
||||||
|
protected String identityProviderMapper;
|
||||||
|
protected Map<String, String> config = new HashMap<String, String>();
|
||||||
|
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdentityProviderAlias() {
|
||||||
|
return identityProviderAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdentityProviderAlias(String identityProviderAlias) {
|
||||||
|
this.identityProviderAlias = identityProviderAlias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdentityProviderMapper() {
|
||||||
|
return identityProviderMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdentityProviderMapper(String identityProviderMapper) {
|
||||||
|
this.identityProviderMapper = identityProviderMapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfig(Map<String, String> config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package org.keycloak.representations.idm;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class IdentityProviderMapperTypeRepresentation {
|
||||||
|
protected String id;
|
||||||
|
protected String name;
|
||||||
|
protected String category;
|
||||||
|
protected String helpText;
|
||||||
|
|
||||||
|
protected List<ConfigPropertyRepresentation> properties;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCategory() {
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCategory(String category) {
|
||||||
|
this.category = category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHelpText() {
|
||||||
|
return helpText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHelpText(String helpText) {
|
||||||
|
this.helpText = helpText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ConfigPropertyRepresentation> getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProperties(List<ConfigPropertyRepresentation> properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,55 +12,7 @@ public class ProtocolMapperTypeRepresentation {
|
||||||
protected String category;
|
protected String category;
|
||||||
protected String helpText;
|
protected String helpText;
|
||||||
|
|
||||||
public static class ConfigProperty {
|
protected List<ConfigPropertyRepresentation> properties;
|
||||||
protected String name;
|
|
||||||
protected String label;
|
|
||||||
protected String helpText;
|
|
||||||
protected String type;
|
|
||||||
protected Object defaultValue;
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLabel() {
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLabel(String label) {
|
|
||||||
this.label = label;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setType(String type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getDefaultValue() {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefaultValue(Object defaultValue) {
|
|
||||||
this.defaultValue = defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHelpText() {
|
|
||||||
return helpText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHelpText(String helpText) {
|
|
||||||
this.helpText = helpText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected List<ConfigProperty> properties;
|
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
|
@ -94,11 +46,11 @@ public class ProtocolMapperTypeRepresentation {
|
||||||
this.helpText = helpText;
|
this.helpText = helpText;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ConfigProperty> getProperties() {
|
public List<ConfigPropertyRepresentation> getProperties() {
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProperties(List<ConfigProperty> properties) {
|
public void setProperties(List<ConfigPropertyRepresentation> properties) {
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
||||||
import org.keycloak.models.ClientSessionModel;
|
import org.keycloak.models.ClientSessionModel;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
@ -18,6 +19,7 @@ import org.keycloak.representations.idm.ClientIdentityProviderMappingRepresentat
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
|
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
|
||||||
|
import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
|
||||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||||
import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
|
import org.keycloak.representations.idm.RealmEventsConfigRepresentation;
|
||||||
|
@ -327,4 +329,16 @@ public class ModelToRepresentation {
|
||||||
return rep;
|
return rep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IdentityProviderMapperRepresentation toRepresentation(IdentityProviderMapperModel model) {
|
||||||
|
IdentityProviderMapperRepresentation rep = new IdentityProviderMapperRepresentation();
|
||||||
|
rep.setId(model.getId());
|
||||||
|
rep.setIdentityProviderMapper(model.getIdentityProviderMapper());
|
||||||
|
rep.setIdentityProviderAlias(model.getIdentityProviderAlias());
|
||||||
|
Map<String, String> config = new HashMap<String, String>();
|
||||||
|
config.putAll(model.getConfig());
|
||||||
|
rep.setConfig(config);
|
||||||
|
rep.setName(model.getName());
|
||||||
|
return rep;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.keycloak.models.ClaimMask;
|
||||||
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.PasswordPolicy;
|
import org.keycloak.models.PasswordPolicy;
|
||||||
|
@ -25,6 +26,7 @@ import org.keycloak.representations.idm.ClientIdentityProviderMappingRepresentat
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
|
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
|
||||||
|
import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
|
||||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||||
import org.keycloak.representations.idm.OAuthClientRepresentation;
|
import org.keycloak.representations.idm.OAuthClientRepresentation;
|
||||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||||
|
@ -870,6 +872,16 @@ public class RepresentationToModel {
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IdentityProviderMapperModel toModel(IdentityProviderMapperRepresentation rep) {
|
||||||
|
IdentityProviderMapperModel model = new IdentityProviderMapperModel();
|
||||||
|
model.setId(rep.getId());
|
||||||
|
model.setName(rep.getName());
|
||||||
|
model.setIdentityProviderAlias(rep.getIdentityProviderAlias());
|
||||||
|
model.setIdentityProviderMapper(rep.getIdentityProviderMapper());
|
||||||
|
model.setConfig(rep.getConfig());
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
private static List<ClientIdentityProviderMappingModel> toModel(List<ClientIdentityProviderMappingRepresentation> repIdentityProviders, RealmModel realm) {
|
private static List<ClientIdentityProviderMappingModel> toModel(List<ClientIdentityProviderMappingRepresentation> repIdentityProviders, RealmModel realm) {
|
||||||
List<ClientIdentityProviderMappingModel> result = new ArrayList<ClientIdentityProviderMappingModel>();
|
List<ClientIdentityProviderMappingModel> result = new ArrayList<ClientIdentityProviderMappingModel>();
|
||||||
|
|
||||||
|
|
15
model/api/src/main/java/org/keycloak/provider/ConfiguredProvider.java
Executable file
15
model/api/src/main/java/org/keycloak/provider/ConfiguredProvider.java
Executable file
|
@ -0,0 +1,15 @@
|
||||||
|
package org.keycloak.provider;
|
||||||
|
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public interface ConfiguredProvider {
|
||||||
|
String getHelpText();
|
||||||
|
|
||||||
|
List<ProviderConfigProperty> getConfigProperties();
|
||||||
|
}
|
57
model/api/src/main/java/org/keycloak/provider/ProviderConfigProperty.java
Executable file
57
model/api/src/main/java/org/keycloak/provider/ProviderConfigProperty.java
Executable file
|
@ -0,0 +1,57 @@
|
||||||
|
package org.keycloak.provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ProviderConfigProperty {
|
||||||
|
public static final String BOOLEAN_TYPE="boolean";
|
||||||
|
public static final String STRING_TYPE="String";
|
||||||
|
public static final String LIST_TYPE="List";
|
||||||
|
|
||||||
|
protected String name;
|
||||||
|
protected String label;
|
||||||
|
protected String helpText;
|
||||||
|
protected String type;
|
||||||
|
protected Object defaultValue;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLabel() {
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLabel(String label) {
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getDefaultValue() {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultValue(Object defaultValue) {
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHelpText() {
|
||||||
|
return helpText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHelpText(String helpText) {
|
||||||
|
this.helpText = helpText;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
package org.keycloak.protocol.saml.mappers;
|
package org.keycloak.protocol.saml.mappers;
|
||||||
|
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.protocol.ProtocolMapper;
|
|
||||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.protocol.saml.SamlProtocol;
|
import org.keycloak.protocol.saml.SamlProtocol;
|
||||||
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
||||||
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
||||||
|
@ -48,18 +48,18 @@ public class AttributeStatementHelper {
|
||||||
return attribute;
|
return attribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setConfigProperties(List<ProtocolMapper.ConfigProperty> configProperties) {
|
public static void setConfigProperties(List<ProviderConfigProperty> configProperties) {
|
||||||
ProtocolMapper.ConfigProperty property = new ProtocolMapper.ConfigProperty();
|
ProviderConfigProperty property = new ProviderConfigProperty();
|
||||||
property.setName(AttributeStatementHelper.FRIENDLY_NAME);
|
property.setName(AttributeStatementHelper.FRIENDLY_NAME);
|
||||||
property.setLabel(AttributeStatementHelper.FRIENDLY_NAME_LABEL);
|
property.setLabel(AttributeStatementHelper.FRIENDLY_NAME_LABEL);
|
||||||
property.setHelpText(AttributeStatementHelper.FRIENDLY_NAME_HELP_TEXT);
|
property.setHelpText(AttributeStatementHelper.FRIENDLY_NAME_HELP_TEXT);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ProtocolMapper.ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAME);
|
property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAME);
|
||||||
property.setLabel("SAML Attribute Name");
|
property.setLabel("SAML Attribute Name");
|
||||||
property.setHelpText("SAML Attribute Name");
|
property.setHelpText("SAML Attribute Name");
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ProtocolMapper.ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT);
|
property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT);
|
||||||
property.setLabel("SAML Attribute NameFormat");
|
property.setLabel("SAML Attribute NameFormat");
|
||||||
property.setHelpText("SAML Attribute NameFormat. Can be basic, URI reference, or unspecified.");
|
property.setHelpText("SAML Attribute NameFormat. Can be basic, URI reference, or unspecified.");
|
||||||
|
@ -67,7 +67,7 @@ public class AttributeStatementHelper {
|
||||||
types.add(AttributeStatementHelper.BASIC);
|
types.add(AttributeStatementHelper.BASIC);
|
||||||
types.add(AttributeStatementHelper.URI_REFERENCE);
|
types.add(AttributeStatementHelper.URI_REFERENCE);
|
||||||
types.add(AttributeStatementHelper.UNSPECIFIED);
|
types.add(AttributeStatementHelper.UNSPECIFIED);
|
||||||
property.setType(ProtocolMapper.ConfigProperty.LIST_TYPE);
|
property.setType(ProviderConfigProperty.LIST_TYPE);
|
||||||
property.setDefaultValue(types);
|
property.setDefaultValue(types);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -18,15 +19,15 @@ import java.util.List;
|
||||||
public class HardcodedAttributeMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
|
public class HardcodedAttributeMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
|
||||||
public static final String PROVIDER_ID = "saml-hardcode-attribute-mapper";
|
public static final String PROVIDER_ID = "saml-hardcode-attribute-mapper";
|
||||||
public static final String ATTRIBUTE_VALUE = "attribute.value";
|
public static final String ATTRIBUTE_VALUE = "attribute.value";
|
||||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
AttributeStatementHelper.setConfigProperties(configProperties);
|
AttributeStatementHelper.setConfigProperties(configProperties);
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(ATTRIBUTE_VALUE);
|
property.setName(ATTRIBUTE_VALUE);
|
||||||
property.setLabel("Attribute value");
|
property.setLabel("Attribute value");
|
||||||
property.setType(ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
property.setHelpText("Value of the attribute you want to hard code.");
|
property.setHelpText("Value of the attribute you want to hard code.");
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ public class HardcodedAttributeMapper extends AbstractSAMLProtocolMapper impleme
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public List<ConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.keycloak.protocol.saml.mappers;
|
package org.keycloak.protocol.saml.mappers;
|
||||||
|
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.protocol.saml.SamlProtocol;
|
import org.keycloak.protocol.saml.SamlProtocol;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -17,21 +18,21 @@ import java.util.Map;
|
||||||
public class HardcodedRole extends AbstractSAMLProtocolMapper {
|
public class HardcodedRole extends AbstractSAMLProtocolMapper {
|
||||||
public static final String PROVIDER_ID = "saml-hardcode-role-mapper";
|
public static final String PROVIDER_ID = "saml-hardcode-role-mapper";
|
||||||
public static final String ATTRIBUTE_VALUE = "attribute.value";
|
public static final String ATTRIBUTE_VALUE = "attribute.value";
|
||||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName("role");
|
property.setName("role");
|
||||||
property.setLabel("Role");
|
property.setLabel("Role");
|
||||||
property.setHelpText("Role name you want to hardcode.");
|
property.setHelpText("Role name you want to hardcode.");
|
||||||
property.setType(ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public List<ConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.protocol.ProtocolMapper;
|
import org.keycloak.protocol.ProtocolMapper;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.protocol.saml.SamlProtocol;
|
import org.keycloak.protocol.saml.SamlProtocol;
|
||||||
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
||||||
import org.keycloak.dom.saml.v2.assertion.AttributeType;
|
import org.keycloak.dom.saml.v2.assertion.AttributeType;
|
||||||
|
@ -25,22 +26,22 @@ public class RoleListMapper extends AbstractSAMLProtocolMapper implements SAMLRo
|
||||||
public static final String PROVIDER_ID = "saml-role-list-mapper";
|
public static final String PROVIDER_ID = "saml-role-list-mapper";
|
||||||
public static final String SINGLE_ROLE_ATTRIBUTE = "single";
|
public static final String SINGLE_ROLE_ATTRIBUTE = "single";
|
||||||
|
|
||||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAME);
|
property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAME);
|
||||||
property.setLabel("Role attribute name");
|
property.setLabel("Role attribute name");
|
||||||
property.setDefaultValue("Role");
|
property.setDefaultValue("Role");
|
||||||
property.setHelpText("Name of the SAML attribute you want to put your roles into. i.e. 'Role', 'memberOf'.");
|
property.setHelpText("Name of the SAML attribute you want to put your roles into. i.e. 'Role', 'memberOf'.");
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ProtocolMapper.ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(AttributeStatementHelper.FRIENDLY_NAME);
|
property.setName(AttributeStatementHelper.FRIENDLY_NAME);
|
||||||
property.setLabel(AttributeStatementHelper.FRIENDLY_NAME_LABEL);
|
property.setLabel(AttributeStatementHelper.FRIENDLY_NAME_LABEL);
|
||||||
property.setHelpText(AttributeStatementHelper.FRIENDLY_NAME_HELP_TEXT);
|
property.setHelpText(AttributeStatementHelper.FRIENDLY_NAME_HELP_TEXT);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ProtocolMapper.ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT);
|
property.setName(AttributeStatementHelper.SAML_ATTRIBUTE_NAMEFORMAT);
|
||||||
property.setLabel("SAML Attribute NameFormat");
|
property.setLabel("SAML Attribute NameFormat");
|
||||||
property.setHelpText("SAML Attribute NameFormat. Can be basic, URI reference, or unspecified.");
|
property.setHelpText("SAML Attribute NameFormat. Can be basic, URI reference, or unspecified.");
|
||||||
|
@ -48,13 +49,13 @@ public class RoleListMapper extends AbstractSAMLProtocolMapper implements SAMLRo
|
||||||
types.add(AttributeStatementHelper.BASIC);
|
types.add(AttributeStatementHelper.BASIC);
|
||||||
types.add(AttributeStatementHelper.URI_REFERENCE);
|
types.add(AttributeStatementHelper.URI_REFERENCE);
|
||||||
types.add(AttributeStatementHelper.UNSPECIFIED);
|
types.add(AttributeStatementHelper.UNSPECIFIED);
|
||||||
property.setType(ProtocolMapper.ConfigProperty.LIST_TYPE);
|
property.setType(ProviderConfigProperty.LIST_TYPE);
|
||||||
property.setDefaultValue(types);
|
property.setDefaultValue(types);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(SINGLE_ROLE_ATTRIBUTE);
|
property.setName(SINGLE_ROLE_ATTRIBUTE);
|
||||||
property.setLabel("Single Role Attribute");
|
property.setLabel("Single Role Attribute");
|
||||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
|
||||||
property.setDefaultValue("true");
|
property.setDefaultValue("true");
|
||||||
property.setHelpText("If true, all roles will be stored under one attribute with multiple attribute values.");
|
property.setHelpText("If true, all roles will be stored under one attribute with multiple attribute values.");
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
|
@ -78,7 +79,7 @@ public class RoleListMapper extends AbstractSAMLProtocolMapper implements SAMLRo
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.RoleContainerModel;
|
import org.keycloak.models.RoleContainerModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper;
|
import org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper;
|
||||||
import org.keycloak.protocol.saml.SamlProtocol;
|
import org.keycloak.protocol.saml.SamlProtocol;
|
||||||
|
|
||||||
|
@ -20,31 +21,31 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class RoleNameMapper extends AbstractOIDCProtocolMapper implements SAMLRoleNameMapper {
|
public class RoleNameMapper extends AbstractOIDCProtocolMapper implements SAMLRoleNameMapper {
|
||||||
|
|
||||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
public static final String ROLE_CONFIG = "role";
|
public static final String ROLE_CONFIG = "role";
|
||||||
public static String NEW_ROLE_NAME = "new.role.name";
|
public static String NEW_ROLE_NAME = "new.role.name";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(ROLE_CONFIG);
|
property.setName(ROLE_CONFIG);
|
||||||
property.setLabel("Role");
|
property.setLabel("Role");
|
||||||
property.setHelpText("Role name you want changed. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
|
property.setHelpText("Role name you want changed. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
|
||||||
property.setType(ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(NEW_ROLE_NAME);
|
property.setName(NEW_ROLE_NAME);
|
||||||
property.setLabel("New Role Name");
|
property.setLabel("New Role Name");
|
||||||
property.setHelpText("The new role name.");
|
property.setHelpText("The new role name.");
|
||||||
property.setType(ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String PROVIDER_ID = "saml-role-name-mapper";
|
public static final String PROVIDER_ID = "saml-role-name-mapper";
|
||||||
|
|
||||||
|
|
||||||
public List<ConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||||
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -18,11 +19,11 @@ import java.util.List;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class UserAttributeStatementMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
|
public class UserAttributeStatementMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
|
||||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
|
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
|
||||||
property.setLabel(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_LABEL);
|
property.setLabel(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_LABEL);
|
||||||
property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
|
property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
|
||||||
|
@ -34,7 +35,7 @@ public class UserAttributeStatementMapper extends AbstractSAMLProtocolMapper imp
|
||||||
public static final String PROVIDER_ID = "saml-user-attribute-mapper";
|
public static final String PROVIDER_ID = "saml-user-attribute-mapper";
|
||||||
|
|
||||||
|
|
||||||
public List<ConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||||
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -18,11 +19,11 @@ import java.util.List;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class UserPropertyAttributeStatementMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
|
public class UserPropertyAttributeStatementMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
|
||||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
|
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
|
||||||
property.setLabel(ProtocolMapperUtils.USER_MODEL_PROPERTY_LABEL);
|
property.setLabel(ProtocolMapperUtils.USER_MODEL_PROPERTY_LABEL);
|
||||||
property.setHelpText(ProtocolMapperUtils.USER_MODEL_PROPERTY_HELP_TEXT);
|
property.setHelpText(ProtocolMapperUtils.USER_MODEL_PROPERTY_HELP_TEXT);
|
||||||
|
@ -34,7 +35,7 @@ public class UserPropertyAttributeStatementMapper extends AbstractSAMLProtocolMa
|
||||||
public static final String PROVIDER_ID = "saml-user-property-mapper";
|
public static final String PROVIDER_ID = "saml-user-property-mapper";
|
||||||
|
|
||||||
|
|
||||||
public List<ConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,71 +1,16 @@
|
||||||
package org.keycloak.protocol;
|
package org.keycloak.protocol;
|
||||||
|
|
||||||
|
import org.keycloak.provider.ConfiguredProvider;
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public interface ProtocolMapper extends Provider, ProviderFactory<ProtocolMapper> {
|
public interface ProtocolMapper extends Provider, ProviderFactory<ProtocolMapper>,ConfiguredProvider {
|
||||||
String getProtocol();
|
String getProtocol();
|
||||||
String getDisplayCategory();
|
String getDisplayCategory();
|
||||||
String getDisplayType();
|
String getDisplayType();
|
||||||
String getHelpText();
|
|
||||||
|
|
||||||
public static class ConfigProperty {
|
|
||||||
public static final String BOOLEAN_TYPE="boolean";
|
|
||||||
public static final String STRING_TYPE="String";
|
|
||||||
public static final String LIST_TYPE="List";
|
|
||||||
|
|
||||||
protected String name;
|
|
||||||
protected String label;
|
|
||||||
protected String helpText;
|
|
||||||
protected String type;
|
|
||||||
protected Object defaultValue;
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLabel() {
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLabel(String label) {
|
|
||||||
this.label = label;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setType(String type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getDefaultValue() {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDefaultValue(Object defaultValue) {
|
|
||||||
this.defaultValue = defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHelpText() {
|
|
||||||
return helpText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHelpText(String helpText) {
|
|
||||||
this.helpText = helpText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ConfigProperty> getConfigProperties();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
import org.keycloak.representations.AddressClaimSet;
|
import org.keycloak.representations.AddressClaimSet;
|
||||||
import org.keycloak.representations.IDToken;
|
import org.keycloak.representations.IDToken;
|
||||||
|
@ -23,21 +24,21 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
||||||
|
|
||||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
|
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
|
||||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
|
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
|
||||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
|
||||||
property.setDefaultValue("true");
|
property.setDefaultValue("true");
|
||||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
|
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
|
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
|
||||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
|
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
|
||||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
|
||||||
property.setDefaultValue("true");
|
property.setDefaultValue("true");
|
||||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
|
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
|
@ -75,7 +76,7 @@ public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAcc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<ConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
import org.keycloak.representations.IDToken;
|
import org.keycloak.representations.IDToken;
|
||||||
|
|
||||||
|
@ -23,21 +24,21 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class FullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
public class FullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
||||||
|
|
||||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
|
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
|
||||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
|
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
|
||||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
|
||||||
property.setDefaultValue("true");
|
property.setDefaultValue("true");
|
||||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
|
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
|
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
|
||||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
|
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
|
||||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
|
||||||
property.setDefaultValue("true");
|
property.setDefaultValue("true");
|
||||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
|
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
|
@ -47,7 +48,7 @@ public class FullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAc
|
||||||
public static final String PROVIDER_ID = "oidc-full-name-mapper";
|
public static final String PROVIDER_ID = "oidc-full-name-mapper";
|
||||||
|
|
||||||
|
|
||||||
public List<ConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.protocol.ProtocolMapper;
|
import org.keycloak.protocol.ProtocolMapper;
|
||||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
import org.keycloak.representations.IDToken;
|
import org.keycloak.representations.IDToken;
|
||||||
|
|
||||||
|
@ -24,25 +25,25 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class HardcodedClaim extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
public class HardcodedClaim extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
||||||
|
|
||||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
public static final String CLAIM_VALUE = "claim.value";
|
public static final String CLAIM_VALUE = "claim.value";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
|
property.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
|
||||||
property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_LABEL);
|
property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_LABEL);
|
||||||
property.setType(ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
property.setHelpText("Claim name you want to hard code into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
|
property.setHelpText("Claim name you want to hard code into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(CLAIM_VALUE);
|
property.setName(CLAIM_VALUE);
|
||||||
property.setLabel("Claim value");
|
property.setLabel("Claim value");
|
||||||
property.setType(ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
property.setHelpText("Value of the claim you want to hard code. 'true' and 'false can be used for boolean values.");
|
property.setHelpText("Value of the claim you want to hard code. 'true' and 'false can be used for boolean values.");
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
|
property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
|
||||||
property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
|
property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
|
||||||
List<String> types = new ArrayList(3);
|
List<String> types = new ArrayList(3);
|
||||||
|
@ -50,21 +51,21 @@ public class HardcodedClaim extends AbstractOIDCProtocolMapper implements OIDCAc
|
||||||
types.add("long");
|
types.add("long");
|
||||||
types.add("int");
|
types.add("int");
|
||||||
types.add("boolean");
|
types.add("boolean");
|
||||||
property.setType(ProtocolMapper.ConfigProperty.LIST_TYPE);
|
property.setType(ProviderConfigProperty.LIST_TYPE);
|
||||||
property.setDefaultValue(types);
|
property.setDefaultValue(types);
|
||||||
property.setHelpText("JSON type that should be used for the value of the claim. long, int, boolean, and String are valid values.");
|
property.setHelpText("JSON type that should be used for the value of the claim. long, int, boolean, and String are valid values.");
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
|
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
|
||||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
|
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
|
||||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
|
||||||
property.setDefaultValue("true");
|
property.setDefaultValue("true");
|
||||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
|
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
|
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
|
||||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
|
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
|
||||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
|
||||||
property.setDefaultValue("true");
|
property.setDefaultValue("true");
|
||||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
|
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
|
@ -74,7 +75,7 @@ public class HardcodedClaim extends AbstractOIDCProtocolMapper implements OIDCAc
|
||||||
public static final String PROVIDER_ID = "oidc-hardcoded-claim-mapper";
|
public static final String PROVIDER_ID = "oidc-hardcoded-claim-mapper";
|
||||||
|
|
||||||
|
|
||||||
public List<ConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -21,24 +22,24 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class HardcodedRole extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
|
public class HardcodedRole extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
|
||||||
|
|
||||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
public static final String ROLE_CONFIG = "role";
|
public static final String ROLE_CONFIG = "role";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(ROLE_CONFIG);
|
property.setName(ROLE_CONFIG);
|
||||||
property.setLabel("Role");
|
property.setLabel("Role");
|
||||||
property.setHelpText("Role you want added to the token. To specify a client role the syntax is clientId.clientRole, i.e. myapp.myrole");
|
property.setHelpText("Role you want added to the token. To specify an application role the syntax is appname.approle, i.e. myapp.myrole");
|
||||||
property.setType(ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String PROVIDER_ID = "oidc-hardcoded-role-mapper";
|
public static final String PROVIDER_ID = "oidc-hardcoded-role-mapper";
|
||||||
|
|
||||||
|
|
||||||
public List<ConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.protocol.ProtocolMapper;
|
import org.keycloak.protocol.ProtocolMapper;
|
||||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
import org.keycloak.representations.IDToken;
|
import org.keycloak.representations.IDToken;
|
||||||
|
|
||||||
|
@ -101,15 +102,15 @@ public class OIDCAttributeMapperHelper {
|
||||||
return "true".equals(mappingModel.getConfig().get(INCLUDE_IN_ACCESS_TOKEN));
|
return "true".equals(mappingModel.getConfig().get(INCLUDE_IN_ACCESS_TOKEN));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void addAttributeConfig(List<ProtocolMapper.ConfigProperty> configProperties) {
|
public static void addAttributeConfig(List<ProviderConfigProperty> configProperties) {
|
||||||
ProtocolMapper.ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
property = new ProtocolMapper.ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(TOKEN_CLAIM_NAME);
|
property.setName(TOKEN_CLAIM_NAME);
|
||||||
property.setLabel(TOKEN_CLAIM_NAME_LABEL);
|
property.setLabel(TOKEN_CLAIM_NAME_LABEL);
|
||||||
property.setType(ProtocolMapper.ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
property.setHelpText("Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
|
property.setHelpText("Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ProtocolMapper.ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(JSON_TYPE);
|
property.setName(JSON_TYPE);
|
||||||
property.setLabel(JSON_TYPE);
|
property.setLabel(JSON_TYPE);
|
||||||
List<String> types = new ArrayList(3);
|
List<String> types = new ArrayList(3);
|
||||||
|
@ -117,21 +118,21 @@ public class OIDCAttributeMapperHelper {
|
||||||
types.add("long");
|
types.add("long");
|
||||||
types.add("int");
|
types.add("int");
|
||||||
types.add("boolean");
|
types.add("boolean");
|
||||||
property.setType(ProtocolMapper.ConfigProperty.LIST_TYPE);
|
property.setType(ProviderConfigProperty.LIST_TYPE);
|
||||||
property.setDefaultValue(types);
|
property.setDefaultValue(types);
|
||||||
property.setHelpText("JSON type that should be used to populate the json claim in the token. long, int, boolean, and String are valid values.");
|
property.setHelpText("JSON type that should be used to populate the json claim in the token. long, int, boolean, and String are valid values.");
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ProtocolMapper.ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(INCLUDE_IN_ID_TOKEN);
|
property.setName(INCLUDE_IN_ID_TOKEN);
|
||||||
property.setLabel(INCLUDE_IN_ID_TOKEN_LABEL);
|
property.setLabel(INCLUDE_IN_ID_TOKEN_LABEL);
|
||||||
property.setType(ProtocolMapper.ConfigProperty.BOOLEAN_TYPE);
|
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
|
||||||
property.setDefaultValue("true");
|
property.setDefaultValue("true");
|
||||||
property.setHelpText(INCLUDE_IN_ID_TOKEN_HELP_TEXT);
|
property.setHelpText(INCLUDE_IN_ID_TOKEN_HELP_TEXT);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ProtocolMapper.ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(INCLUDE_IN_ACCESS_TOKEN);
|
property.setName(INCLUDE_IN_ACCESS_TOKEN);
|
||||||
property.setLabel(INCLUDE_IN_ACCESS_TOKEN_LABEL);
|
property.setLabel(INCLUDE_IN_ACCESS_TOKEN_LABEL);
|
||||||
property.setType(ProtocolMapper.ConfigProperty.BOOLEAN_TYPE);
|
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
|
||||||
property.setDefaultValue("true");
|
property.setDefaultValue("true");
|
||||||
property.setHelpText(INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
|
property.setHelpText(INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
import org.keycloak.representations.IDToken;
|
import org.keycloak.representations.IDToken;
|
||||||
|
|
||||||
|
@ -23,31 +24,31 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
public class RoleNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
|
public class RoleNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper {
|
||||||
|
|
||||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
public static final String ROLE_CONFIG = "role";
|
public static final String ROLE_CONFIG = "role";
|
||||||
public static String NEW_ROLE_NAME = "new.role.name";
|
public static String NEW_ROLE_NAME = "new.role.name";
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(ROLE_CONFIG);
|
property.setName(ROLE_CONFIG);
|
||||||
property.setLabel("Role");
|
property.setLabel("Role");
|
||||||
property.setHelpText("Role name you want changed. To reference an client role the syntax is clientId.clientRole, i.e. myapp.myrole");
|
property.setHelpText("Role name you want changed. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
|
||||||
property.setType(ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(NEW_ROLE_NAME);
|
property.setName(NEW_ROLE_NAME);
|
||||||
property.setLabel("New Role Name");
|
property.setLabel("New Role Name");
|
||||||
property.setHelpText("The new role name. The new name format corresponds to where in the access token the role will be mapped to. So, a new name of 'myapp.newname' will map the role to that position in the access token. A new name of 'newname' will map the role to the realm roles in the token.");
|
property.setHelpText("The new role name. The new name format corresponds to where in the access token the role will be mapped to. So, a new name of 'myapp.newname' will map the role to that position in the access token. A new name of 'newname' will map the role to the realm roles in the token.");
|
||||||
property.setType(ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String PROVIDER_ID = "oidc-role-name-mapper";
|
public static final String PROVIDER_ID = "oidc-role-name-mapper";
|
||||||
|
|
||||||
|
|
||||||
public List<ConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
import org.keycloak.representations.IDToken;
|
import org.keycloak.representations.IDToken;
|
||||||
|
|
||||||
|
@ -23,15 +24,15 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class UserAttributeMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
public class UserAttributeMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
||||||
|
|
||||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
|
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
|
||||||
property.setLabel(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_LABEL);
|
property.setLabel(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_LABEL);
|
||||||
property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
|
property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
|
||||||
property.setType(ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
|
OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ public class UserAttributeMapper extends AbstractOIDCProtocolMapper implements O
|
||||||
public static final String PROVIDER_ID = "oidc-usermodel-attribute-mapper";
|
public static final String PROVIDER_ID = "oidc-usermodel-attribute-mapper";
|
||||||
|
|
||||||
|
|
||||||
public List<ConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
import org.keycloak.representations.IDToken;
|
import org.keycloak.representations.IDToken;
|
||||||
|
|
||||||
|
@ -21,14 +22,14 @@ import java.util.List;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class UserPropertyMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
public class UserPropertyMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
||||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
|
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
|
||||||
property.setLabel(ProtocolMapperUtils.USER_MODEL_PROPERTY_LABEL);
|
property.setLabel(ProtocolMapperUtils.USER_MODEL_PROPERTY_LABEL);
|
||||||
property.setType(ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
property.setHelpText(ProtocolMapperUtils.USER_MODEL_PROPERTY_HELP_TEXT);
|
property.setHelpText(ProtocolMapperUtils.USER_MODEL_PROPERTY_HELP_TEXT);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
|
OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
|
||||||
|
@ -37,7 +38,7 @@ public class UserPropertyMapper extends AbstractOIDCProtocolMapper implements OI
|
||||||
public static final String PROVIDER_ID = "oidc-usermodel-property-mapper";
|
public static final String PROVIDER_ID = "oidc-usermodel-property-mapper";
|
||||||
|
|
||||||
|
|
||||||
public List<ConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||||
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
import org.keycloak.representations.IDToken;
|
import org.keycloak.representations.IDToken;
|
||||||
|
|
||||||
|
@ -21,40 +22,40 @@ import org.keycloak.representations.IDToken;
|
||||||
*/
|
*/
|
||||||
public class UserSessionNoteMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
public class UserSessionNoteMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper {
|
||||||
|
|
||||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ConfigProperty property;
|
ProviderConfigProperty property;
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(ProtocolMapperUtils.USER_SESSION_NOTE);
|
property.setName(ProtocolMapperUtils.USER_SESSION_NOTE);
|
||||||
property.setLabel(ProtocolMapperUtils.USER_SESSION_MODEL_NOTE_LABEL);
|
property.setLabel(ProtocolMapperUtils.USER_SESSION_MODEL_NOTE_LABEL);
|
||||||
property.setHelpText(ProtocolMapperUtils.USER_SESSION_MODEL_NOTE_HELP_TEXT);
|
property.setHelpText(ProtocolMapperUtils.USER_SESSION_MODEL_NOTE_HELP_TEXT);
|
||||||
property.setType(ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
|
property.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
|
||||||
property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_LABEL);
|
property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_LABEL);
|
||||||
property.setType(ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
property.setHelpText("Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
|
property.setHelpText("Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
|
property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
|
||||||
property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
|
property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
|
||||||
property.setType(ConfigProperty.STRING_TYPE);
|
property.setType(ProviderConfigProperty.STRING_TYPE);
|
||||||
property.setDefaultValue(ConfigProperty.STRING_TYPE);
|
property.setDefaultValue(ProviderConfigProperty.STRING_TYPE);
|
||||||
property.setHelpText("JSON type that should be used to populate the json claim in the token. long, int, boolean, and String are valid values.");
|
property.setHelpText("JSON type that should be used to populate the json claim in the token. long, int, boolean, and String are valid values.");
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
|
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
|
||||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
|
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
|
||||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
|
||||||
property.setDefaultValue("true");
|
property.setDefaultValue("true");
|
||||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
|
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
property = new ConfigProperty();
|
property = new ProviderConfigProperty();
|
||||||
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
|
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
|
||||||
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
|
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
|
||||||
property.setType(ConfigProperty.BOOLEAN_TYPE);
|
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
|
||||||
property.setDefaultValue("true");
|
property.setDefaultValue("true");
|
||||||
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
|
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
|
||||||
configProperties.add(property);
|
configProperties.add(property);
|
||||||
|
@ -64,7 +65,7 @@ public class UserSessionNoteMapper extends AbstractOIDCProtocolMapper implements
|
||||||
public static final String PROVIDER_ID = "oidc-usersessionmodel-note-mapper";
|
public static final String PROVIDER_ID = "oidc-usersessionmodel-note-mapper";
|
||||||
|
|
||||||
|
|
||||||
public List<ConfigProperty> getConfigProperties() {
|
public List<ProviderConfigProperty> getConfigProperties() {
|
||||||
return configProperties;
|
return configProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,11 @@ import org.jboss.resteasy.spi.HttpRequest;
|
||||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||||
import org.keycloak.ClientConnection;
|
import org.keycloak.ClientConnection;
|
||||||
import org.keycloak.broker.provider.AuthenticationRequest;
|
import org.keycloak.broker.provider.AuthenticationRequest;
|
||||||
import org.keycloak.broker.provider.FederatedIdentity;
|
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||||
import org.keycloak.broker.provider.IdentityProvider;
|
import org.keycloak.broker.provider.IdentityProvider;
|
||||||
import org.keycloak.broker.provider.IdentityProviderFactory;
|
import org.keycloak.broker.provider.IdentityProviderFactory;
|
||||||
|
import org.keycloak.broker.provider.IdentityProviderMapper;
|
||||||
import org.keycloak.events.Details;
|
import org.keycloak.events.Details;
|
||||||
import org.keycloak.events.Errors;
|
import org.keycloak.events.Errors;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
|
@ -34,11 +35,14 @@ import org.keycloak.login.LoginFormsProvider;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.ClientSessionModel;
|
import org.keycloak.models.ClientSessionModel;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.UserSessionModel;
|
import org.keycloak.models.UserSessionModel;
|
||||||
|
import org.keycloak.protocol.ProtocolMapper;
|
||||||
import org.keycloak.protocol.oidc.TokenManager;
|
import org.keycloak.protocol.oidc.TokenManager;
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
import org.keycloak.services.managers.AppAuthManager;
|
import org.keycloak.services.managers.AppAuthManager;
|
||||||
|
@ -72,6 +76,7 @@ import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT;
|
import static org.keycloak.models.AccountRoles.MANAGE_ACCOUNT;
|
||||||
import static org.keycloak.models.ClientSessionModel.Action.AUTHENTICATE;
|
import static org.keycloak.models.ClientSessionModel.Action.AUTHENTICATE;
|
||||||
|
@ -131,7 +136,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
try {
|
try {
|
||||||
ClientSessionCode clientSessionCode = parseClientSessionCode(code);
|
ClientSessionCode clientSessionCode = parseClientSessionCode(code);
|
||||||
IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
|
IdentityProvider identityProvider = getIdentityProvider(session, realmModel, providerId);
|
||||||
Response response = identityProvider.handleRequest(createAuthenticationRequest(providerId, clientSessionCode));
|
Response response = identityProvider.performLogin(createAuthenticationRequest(providerId, clientSessionCode));
|
||||||
|
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
this.event.success();
|
this.event.success();
|
||||||
|
@ -239,10 +244,11 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
return getToken(providerId, true);
|
return getToken(providerId, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Response authenticated(Map<String, String> userNotes, IdentityProviderModel identityProviderConfig, FederatedIdentity federatedIdentity, String code) {
|
public Response authenticated(BrokeredIdentityContext context) {
|
||||||
ClientSessionCode clientCode = null;
|
ClientSessionCode clientCode = null;
|
||||||
|
IdentityProviderModel identityProviderConfig = context.getIdpConfig();
|
||||||
try {
|
try {
|
||||||
clientCode = parseClientSessionCode(code);
|
clientCode = parseClientSessionCode(context.getCode());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return redirectToErrorPage(Messages.IDENTITY_PROVIDER_AUTHENTICATION_FAILED, e, identityProviderConfig.getProviderId());
|
return redirectToErrorPage(Messages.IDENTITY_PROVIDER_AUTHENTICATION_FAILED, e, identityProviderConfig.getProviderId());
|
||||||
|
|
||||||
|
@ -252,32 +258,27 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
if (isDebugEnabled()) {
|
if (isDebugEnabled()) {
|
||||||
LOGGER.debugf("Token will not be stored for identity provider [%s].", providerId);
|
LOGGER.debugf("Token will not be stored for identity provider [%s].", providerId);
|
||||||
}
|
}
|
||||||
federatedIdentity.setToken(null);
|
context.setToken(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
federatedIdentity.setIdentityProviderId(providerId);
|
|
||||||
ClientSessionModel clientSession = clientCode.getClientSession();
|
ClientSessionModel clientSession = clientCode.getClientSession();
|
||||||
FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(providerId, federatedIdentity.getId(),
|
FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(providerId, context.getId(),
|
||||||
federatedIdentity.getUsername(), federatedIdentity.getToken());
|
context.getUsername(), context.getToken());
|
||||||
|
|
||||||
this.event.event(EventType.IDENTITY_PROVIDER_LOGIN)
|
this.event.event(EventType.IDENTITY_PROVIDER_LOGIN)
|
||||||
.detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
|
.detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
|
||||||
.detail(Details.IDENTITY_PROVIDER_USERNAME, federatedIdentity.getUsername());
|
.detail(Details.IDENTITY_PROVIDER_USERNAME, context.getUsername());
|
||||||
|
|
||||||
UserModel federatedUser = this.session.users().getUserByFederatedIdentity(federatedIdentityModel, this.realmModel);
|
UserModel federatedUser = this.session.users().getUserByFederatedIdentity(federatedIdentityModel, this.realmModel);
|
||||||
|
|
||||||
// Check if federatedUser is already authenticated (this means linking social into existing federatedUser account)
|
// Check if federatedUser is already authenticated (this means linking social into existing federatedUser account)
|
||||||
if (clientSession.getUserSession() != null) {
|
if (clientSession.getUserSession() != null) {
|
||||||
UserSessionModel userSession = clientSession.getUserSession();
|
return performAccountLinking(clientSession, context, federatedIdentityModel, federatedUser);
|
||||||
for (Map.Entry<String, String> entry : userNotes.entrySet()) {
|
|
||||||
userSession.setNote(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
return performAccountLinking(clientSession, providerId, federatedIdentityModel, federatedUser);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (federatedUser == null) {
|
if (federatedUser == null) {
|
||||||
try {
|
try {
|
||||||
federatedUser = createUser(federatedIdentity);
|
federatedUser = createUser(context);
|
||||||
|
|
||||||
if (identityProviderConfig.isUpdateProfileFirstLogin()) {
|
if (identityProviderConfig.isUpdateProfileFirstLogin()) {
|
||||||
if (isDebugEnabled()) {
|
if (isDebugEnabled()) {
|
||||||
|
@ -290,18 +291,16 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFederatedIdentity(federatedIdentity, federatedUser);
|
updateFederatedIdentity(context, federatedUser);
|
||||||
|
|
||||||
UserSessionModel userSession = this.session.sessions()
|
UserSessionModel userSession = this.session.sessions()
|
||||||
.createUserSession(this.realmModel, federatedUser, federatedUser.getUsername(), this.clientConnection.getRemoteAddr(), "broker", false, federatedIdentity.getBrokerSessionId(), federatedIdentity.getBrokerUserId());
|
.createUserSession(this.realmModel, federatedUser, federatedUser.getUsername(), this.clientConnection.getRemoteAddr(), "broker", false, context.getBrokerSessionId(), context.getBrokerUserId());
|
||||||
|
|
||||||
this.event.user(federatedUser);
|
this.event.user(federatedUser);
|
||||||
this.event.session(userSession);
|
this.event.session(userSession);
|
||||||
|
|
||||||
TokenManager.attachClientSession(userSession, clientSession);
|
TokenManager.attachClientSession(userSession, clientSession);
|
||||||
for (Map.Entry<String, String> entry : userNotes.entrySet()) {
|
context.getIdp().attachUserSession(userSession, clientSession, context);
|
||||||
userSession.setNote(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
userSession.setNote(BROKER_PROVIDER_ID, providerId);
|
userSession.setNote(BROKER_PROVIDER_ID, providerId);
|
||||||
|
|
||||||
if (isDebugEnabled()) {
|
if (isDebugEnabled()) {
|
||||||
|
@ -312,17 +311,17 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
this.uriInfo, event);
|
this.uriInfo, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response performAccountLinking(ClientSessionModel clientSession, String providerId, FederatedIdentityModel federatedIdentityModel, UserModel federatedUser) {
|
private Response performAccountLinking(ClientSessionModel clientSession, BrokeredIdentityContext context, FederatedIdentityModel federatedIdentityModel, UserModel federatedUser) {
|
||||||
this.event.event(EventType.IDENTITY_PROVIDER_ACCCOUNT_LINKING);
|
this.event.event(EventType.IDENTITY_PROVIDER_ACCCOUNT_LINKING);
|
||||||
|
|
||||||
if (federatedUser != null) {
|
if (federatedUser != null) {
|
||||||
return redirectToErrorPage(Messages.IDENTITY_PROVIDER_ALREADY_LINKED, providerId);
|
return redirectToErrorPage(Messages.IDENTITY_PROVIDER_ALREADY_LINKED, context.getIdpConfig().getAlias());
|
||||||
}
|
}
|
||||||
|
|
||||||
UserModel authenticatedUser = clientSession.getUserSession().getUser();
|
UserModel authenticatedUser = clientSession.getUserSession().getUser();
|
||||||
|
|
||||||
if (isDebugEnabled()) {
|
if (isDebugEnabled()) {
|
||||||
LOGGER.debugf("Linking account [%s] from identity provider [%s] to user [%s].", federatedIdentityModel, providerId, authenticatedUser);
|
LOGGER.debugf("Linking account [%s] from identity provider [%s] to user [%s].", federatedIdentityModel, context.getIdpConfig().getAlias(), authenticatedUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!authenticatedUser.isEnabled()) {
|
if (!authenticatedUser.isEnabled()) {
|
||||||
|
@ -336,14 +335,14 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
}
|
}
|
||||||
|
|
||||||
this.session.users().addFederatedIdentity(this.realmModel, authenticatedUser, federatedIdentityModel);
|
this.session.users().addFederatedIdentity(this.realmModel, authenticatedUser, federatedIdentityModel);
|
||||||
|
context.getIdp().attachUserSession(clientSession.getUserSession(), clientSession, context);
|
||||||
|
|
||||||
this.event.success();
|
this.event.success();
|
||||||
|
|
||||||
return Response.status(302).location(UriBuilder.fromUri(clientSession.getRedirectUri()).build()).build();
|
return Response.status(302).location(UriBuilder.fromUri(clientSession.getRedirectUri()).build()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateFederatedIdentity(FederatedIdentity updatedIdentity, UserModel federatedUser) {
|
private void updateFederatedIdentity(BrokeredIdentityContext updatedIdentity, UserModel federatedUser) {
|
||||||
FederatedIdentityModel federatedIdentityModel = this.session.users().getFederatedIdentity(federatedUser, updatedIdentity.getIdentityProviderId(), this.realmModel);
|
FederatedIdentityModel federatedIdentityModel = this.session.users().getFederatedIdentity(federatedUser, updatedIdentity.getIdpConfig().getAlias(), this.realmModel);
|
||||||
|
|
||||||
// Skip DB write if tokens are null or equal
|
// Skip DB write if tokens are null or equal
|
||||||
if (!ObjectUtil.isEqualOrNull(updatedIdentity.getToken(), federatedIdentityModel.getToken())) {
|
if (!ObjectUtil.isEqualOrNull(updatedIdentity.getToken(), federatedIdentityModel.getToken())) {
|
||||||
|
@ -352,9 +351,19 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
this.session.users().updateFederatedIdentity(this.realmModel, federatedUser, federatedIdentityModel);
|
this.session.users().updateFederatedIdentity(this.realmModel, federatedUser, federatedIdentityModel);
|
||||||
|
|
||||||
if (isDebugEnabled()) {
|
if (isDebugEnabled()) {
|
||||||
LOGGER.debugf("Identity [%s] update with response from identity provider [%s].", federatedUser, updatedIdentity.getIdentityProviderId());
|
LOGGER.debugf("Identity [%s] update with response from identity provider [%s].", federatedUser, updatedIdentity.getIdpConfig().getAlias());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
updatedIdentity.getIdp().updateBrokeredUser(session, realmModel, federatedUser, updatedIdentity);
|
||||||
|
Set<IdentityProviderMapperModel> mappers = realmModel.getIdentityProviderMappersByAlias(updatedIdentity.getIdpConfig().getAlias());
|
||||||
|
if (mappers != null) {
|
||||||
|
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
|
||||||
|
for (IdentityProviderMapperModel mapper : mappers) {
|
||||||
|
IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
|
||||||
|
target.updateBrokeredUser(session, realmModel, federatedUser, mapper, updatedIdentity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClientSessionCode parseClientSessionCode(String code) {
|
private ClientSessionCode parseClientSessionCode(String code) {
|
||||||
|
@ -476,8 +485,8 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
throw new IdentityBrokerException("Configuration for identity provider [" + providerId + "] not found.");
|
throw new IdentityBrokerException("Configuration for identity provider [" + providerId + "] not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private UserModel createUser(FederatedIdentity updatedIdentity) {
|
private UserModel createUser(BrokeredIdentityContext updatedIdentity) {
|
||||||
FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(updatedIdentity.getIdentityProviderId(), updatedIdentity.getId(),
|
FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(updatedIdentity.getIdpConfig().getAlias(), updatedIdentity.getId(),
|
||||||
updatedIdentity.getUsername(), updatedIdentity.getToken());
|
updatedIdentity.getUsername(), updatedIdentity.getToken());
|
||||||
// Check if no user already exists with this username or email
|
// Check if no user already exists with this username or email
|
||||||
UserModel existingUser = null;
|
UserModel existingUser = null;
|
||||||
|
@ -495,9 +504,9 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
if (this.realmModel.isRegistrationEmailAsUsername() && !Validation.isEmpty(updatedIdentity.getEmail())) {
|
if (this.realmModel.isRegistrationEmailAsUsername() && !Validation.isEmpty(updatedIdentity.getEmail())) {
|
||||||
username = updatedIdentity.getEmail();
|
username = updatedIdentity.getEmail();
|
||||||
} else if (username == null) {
|
} else if (username == null) {
|
||||||
username = updatedIdentity.getIdentityProviderId() + "." + updatedIdentity.getId();
|
username = updatedIdentity.getIdpConfig().getAlias() + "." + updatedIdentity.getId();
|
||||||
} else {
|
} else {
|
||||||
username = updatedIdentity.getIdentityProviderId() + "." + updatedIdentity.getUsername();
|
username = updatedIdentity.getIdpConfig().getAlias() + "." + updatedIdentity.getUsername();
|
||||||
}
|
}
|
||||||
if (username != null) {
|
if (username != null) {
|
||||||
username = username.trim();
|
username = username.trim();
|
||||||
|
@ -521,12 +530,23 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
}
|
}
|
||||||
|
|
||||||
federatedUser.setEnabled(true);
|
federatedUser.setEnabled(true);
|
||||||
|
federatedUser.setEmail(updatedIdentity.getEmail());
|
||||||
federatedUser.setFirstName(updatedIdentity.getFirstName());
|
federatedUser.setFirstName(updatedIdentity.getFirstName());
|
||||||
federatedUser.setLastName(updatedIdentity.getLastName());
|
federatedUser.setLastName(updatedIdentity.getLastName());
|
||||||
federatedUser.setEmail(updatedIdentity.getEmail());
|
|
||||||
|
|
||||||
this.session.users().addFederatedIdentity(this.realmModel, federatedUser, federatedIdentityModel);
|
this.session.users().addFederatedIdentity(this.realmModel, federatedUser, federatedIdentityModel);
|
||||||
|
|
||||||
|
updatedIdentity.getIdp().importNewUser(session, realmModel, federatedUser, updatedIdentity);
|
||||||
|
Set<IdentityProviderMapperModel> mappers = realmModel.getIdentityProviderMappersByAlias(updatedIdentity.getIdpConfig().getAlias());
|
||||||
|
if (mappers != null) {
|
||||||
|
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
|
||||||
|
for (IdentityProviderMapperModel mapper : mappers) {
|
||||||
|
IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
|
||||||
|
target.importNewUser(session, realmModel, federatedUser, mapper, updatedIdentity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
this.event.clone().user(federatedUser).event(EventType.REGISTER)
|
this.event.clone().user(federatedUser).event(EventType.REGISTER)
|
||||||
.detail(Details.IDENTITY_PROVIDER, federatedIdentityModel.getIdentityProvider())
|
.detail(Details.IDENTITY_PROVIDER, federatedIdentityModel.getIdentityProvider())
|
||||||
.detail(Details.IDENTITY_PROVIDER_USERNAME, updatedIdentity.getUsername())
|
.detail(Details.IDENTITY_PROVIDER_USERNAME, updatedIdentity.getUsername())
|
||||||
|
|
|
@ -2,28 +2,40 @@ package org.keycloak.services.resources.admin;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
|
import org.jboss.resteasy.spi.NotFoundException;
|
||||||
import org.keycloak.broker.provider.IdentityProvider;
|
import org.keycloak.broker.provider.IdentityProvider;
|
||||||
import org.keycloak.broker.provider.IdentityProviderFactory;
|
import org.keycloak.broker.provider.IdentityProviderFactory;
|
||||||
|
import org.keycloak.broker.provider.IdentityProviderMapper;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
import org.keycloak.models.ClientIdentityProviderMappingModel;
|
||||||
import org.keycloak.models.FederatedIdentityModel;
|
import org.keycloak.models.FederatedIdentityModel;
|
||||||
|
import org.keycloak.models.IdentityProviderMapperModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.models.ModelDuplicateException;
|
import org.keycloak.models.ModelDuplicateException;
|
||||||
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.utils.ModelToRepresentation;
|
import org.keycloak.models.utils.ModelToRepresentation;
|
||||||
import org.keycloak.models.utils.RepresentationToModel;
|
import org.keycloak.models.utils.RepresentationToModel;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
import org.keycloak.representations.idm.ConfigPropertyRepresentation;
|
||||||
|
import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
|
||||||
|
import org.keycloak.representations.idm.IdentityProviderMapperTypeRepresentation;
|
||||||
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||||
import org.keycloak.services.ErrorResponse;
|
import org.keycloak.services.ErrorResponse;
|
||||||
|
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||||
import org.keycloak.social.SocialIdentityProvider;
|
import org.keycloak.social.SocialIdentityProvider;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.PUT;
|
import javax.ws.rs.PUT;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
|
@ -31,6 +43,7 @@ import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,6 +58,8 @@ public class IdentityProviderResource {
|
||||||
private final KeycloakSession session;
|
private final KeycloakSession session;
|
||||||
private final IdentityProviderModel identityProviderModel;
|
private final IdentityProviderModel identityProviderModel;
|
||||||
|
|
||||||
|
@Context private UriInfo uriInfo;
|
||||||
|
|
||||||
public IdentityProviderResource(RealmAuth auth, RealmModel realm, KeycloakSession session, IdentityProviderModel identityProviderModel) {
|
public IdentityProviderResource(RealmAuth auth, RealmModel realm, KeycloakSession session, IdentityProviderModel identityProviderModel) {
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
this.session = session;
|
this.session = session;
|
||||||
|
@ -56,6 +71,7 @@ public class IdentityProviderResource {
|
||||||
@NoCache
|
@NoCache
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public IdentityProviderRepresentation getIdentityProvider() {
|
public IdentityProviderRepresentation getIdentityProvider() {
|
||||||
|
this.auth.requireView();
|
||||||
IdentityProviderRepresentation rep = ModelToRepresentation.toRepresentation(this.identityProviderModel);
|
IdentityProviderRepresentation rep = ModelToRepresentation.toRepresentation(this.identityProviderModel);
|
||||||
|
|
||||||
return rep;
|
return rep;
|
||||||
|
@ -75,6 +91,7 @@ public class IdentityProviderResource {
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
@NoCache
|
||||||
public Response update(IdentityProviderRepresentation providerRep) {
|
public Response update(IdentityProviderRepresentation providerRep) {
|
||||||
try {
|
try {
|
||||||
this.auth.requireManage();
|
this.auth.requireManage();
|
||||||
|
@ -163,6 +180,7 @@ public class IdentityProviderResource {
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("export")
|
@Path("export")
|
||||||
|
@NoCache
|
||||||
public Response export(@Context UriInfo uriInfo, @QueryParam("format") String format) {
|
public Response export(@Context UriInfo uriInfo, @QueryParam("format") String format) {
|
||||||
try {
|
try {
|
||||||
this.auth.requireView();
|
this.auth.requireView();
|
||||||
|
@ -173,6 +191,97 @@ public class IdentityProviderResource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("mapper-types")
|
||||||
|
@NoCache
|
||||||
|
public List<IdentityProviderMapperTypeRepresentation> getMapperTypes() {
|
||||||
|
this.auth.requireView();
|
||||||
|
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
|
||||||
|
List<IdentityProviderMapperTypeRepresentation> types = new LinkedList<>();
|
||||||
|
List<ProviderFactory> factories = sessionFactory.getProviderFactories(IdentityProviderMapper.class);
|
||||||
|
for (ProviderFactory factory : factories) {
|
||||||
|
IdentityProviderMapper mapper = (IdentityProviderMapper)factory;
|
||||||
|
for (String type : mapper.getCompatibleProviders()) {
|
||||||
|
if (type.equals(identityProviderModel.getProviderId())) {
|
||||||
|
IdentityProviderMapperTypeRepresentation rep = new IdentityProviderMapperTypeRepresentation();
|
||||||
|
rep.setId(mapper.getId());
|
||||||
|
rep.setCategory(mapper.getDisplayCategory());
|
||||||
|
rep.setName(mapper.getDisplayType());
|
||||||
|
rep.setHelpText(mapper.getHelpText());
|
||||||
|
List<ProviderConfigProperty> configProperties = mapper.getConfigProperties();
|
||||||
|
for (ProviderConfigProperty prop : configProperties) {
|
||||||
|
ConfigPropertyRepresentation propRep = new ConfigPropertyRepresentation();
|
||||||
|
propRep.setName(prop.getName());
|
||||||
|
propRep.setLabel(prop.getLabel());
|
||||||
|
propRep.setType(prop.getType());
|
||||||
|
propRep.setDefaultValue(prop.getDefaultValue());
|
||||||
|
propRep.setHelpText(prop.getHelpText());
|
||||||
|
rep.getProperties().add(propRep);
|
||||||
|
}
|
||||||
|
types.add(rep);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("mappers")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@NoCache
|
||||||
|
public List<IdentityProviderMapperRepresentation> getMappers() {
|
||||||
|
this.auth.requireView();
|
||||||
|
List<IdentityProviderMapperRepresentation> mappers = new LinkedList<>();
|
||||||
|
for (IdentityProviderMapperModel model : realm.getIdentityProviderMappersByAlias(identityProviderModel.getAlias())) {
|
||||||
|
mappers.add(ModelToRepresentation.toRepresentation(model));
|
||||||
|
}
|
||||||
|
return mappers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("mappers")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public Response addMapper(IdentityProviderMapperRepresentation mapper) {
|
||||||
|
auth.requireManage();
|
||||||
|
IdentityProviderMapperModel model = RepresentationToModel.toModel(mapper);
|
||||||
|
model = realm.addIdentityProviderMapper(model);
|
||||||
|
return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@NoCache
|
||||||
|
@Path("mappers/{id}")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public IdentityProviderMapperRepresentation getMapperById(@PathParam("id") String id) {
|
||||||
|
auth.requireView();
|
||||||
|
IdentityProviderMapperModel model = realm.getIdentityProviderMapperById(id);
|
||||||
|
if (model == null) throw new NotFoundException("Model not found");
|
||||||
|
return ModelToRepresentation.toRepresentation(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@NoCache
|
||||||
|
@Path("mappers/{id}")
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public void update(@PathParam("id") String id, IdentityProviderMapperRepresentation rep) {
|
||||||
|
auth.requireManage();
|
||||||
|
IdentityProviderMapperModel model = realm.getIdentityProviderMapperById(id);
|
||||||
|
if (model == null) throw new NotFoundException("Model not found");
|
||||||
|
model = RepresentationToModel.toModel(rep);
|
||||||
|
realm.updateIdentityProviderMapper(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DELETE
|
||||||
|
@NoCache
|
||||||
|
@Path("mappers/{id}")
|
||||||
|
public void delete(@PathParam("id") String id) {
|
||||||
|
auth.requireManage();
|
||||||
|
IdentityProviderMapperModel model = realm.getIdentityProviderMapperById(id);
|
||||||
|
if (model == null) throw new NotFoundException("Model not found");
|
||||||
|
realm.removeIdentityProviderMapper(model);
|
||||||
|
}
|
||||||
|
|
||||||
private void removeClientIdentityProviders(List<ClientModel> clients, IdentityProviderModel identityProvider) {
|
private void removeClientIdentityProviders(List<ClientModel> clients, IdentityProviderModel identityProvider) {
|
||||||
for (ClientModel clientModel : clients) {
|
for (ClientModel clientModel : clients) {
|
||||||
|
|
|
@ -15,8 +15,10 @@ import org.keycloak.models.utils.ModelToRepresentation;
|
||||||
import org.keycloak.protocol.LoginProtocol;
|
import org.keycloak.protocol.LoginProtocol;
|
||||||
import org.keycloak.protocol.LoginProtocolFactory;
|
import org.keycloak.protocol.LoginProtocolFactory;
|
||||||
import org.keycloak.protocol.ProtocolMapper;
|
import org.keycloak.protocol.ProtocolMapper;
|
||||||
|
import org.keycloak.provider.ProviderConfigProperty;
|
||||||
import org.keycloak.provider.ProviderFactory;
|
import org.keycloak.provider.ProviderFactory;
|
||||||
import org.keycloak.provider.Spi;
|
import org.keycloak.provider.Spi;
|
||||||
|
import org.keycloak.representations.idm.ConfigPropertyRepresentation;
|
||||||
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
|
||||||
import org.keycloak.representations.idm.ProtocolMapperTypeRepresentation;
|
import org.keycloak.representations.idm.ProtocolMapperTypeRepresentation;
|
||||||
import org.keycloak.social.SocialIdentityProvider;
|
import org.keycloak.social.SocialIdentityProvider;
|
||||||
|
@ -141,9 +143,10 @@ public class ServerInfoAdminResource {
|
||||||
rep.setName(mapper.getDisplayType());
|
rep.setName(mapper.getDisplayType());
|
||||||
rep.setHelpText(mapper.getHelpText());
|
rep.setHelpText(mapper.getHelpText());
|
||||||
rep.setCategory(mapper.getDisplayCategory());
|
rep.setCategory(mapper.getDisplayCategory());
|
||||||
rep.setProperties(new LinkedList<ProtocolMapperTypeRepresentation.ConfigProperty>());
|
rep.setProperties(new LinkedList<ConfigPropertyRepresentation>());
|
||||||
for (ProtocolMapper.ConfigProperty prop : mapper.getConfigProperties()) {
|
List<ProviderConfigProperty> configProperties = mapper.getConfigProperties();
|
||||||
ProtocolMapperTypeRepresentation.ConfigProperty propRep = new ProtocolMapperTypeRepresentation.ConfigProperty();
|
for (ProviderConfigProperty prop : configProperties) {
|
||||||
|
ConfigPropertyRepresentation propRep = new ConfigPropertyRepresentation();
|
||||||
propRep.setName(prop.getName());
|
propRep.setName(prop.getName());
|
||||||
propRep.setLabel(prop.getLabel());
|
propRep.setLabel(prop.getLabel());
|
||||||
propRep.setType(prop.getType());
|
propRep.setType(prop.getType());
|
||||||
|
|
|
@ -4,7 +4,7 @@ import org.codehaus.jackson.JsonNode;
|
||||||
import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
|
import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
|
||||||
import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
|
import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
|
||||||
import org.keycloak.broker.oidc.util.SimpleHttp;
|
import org.keycloak.broker.oidc.util.SimpleHttp;
|
||||||
import org.keycloak.broker.provider.FederatedIdentity;
|
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||||
import org.keycloak.social.SocialIdentityProvider;
|
import org.keycloak.social.SocialIdentityProvider;
|
||||||
|
|
||||||
|
@ -25,13 +25,13 @@ public class FacebookIdentityProvider extends AbstractOAuth2IdentityProvider imp
|
||||||
config.setUserInfoUrl(PROFILE_URL);
|
config.setUserInfoUrl(PROFILE_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected FederatedIdentity doGetFederatedIdentity(String accessToken) {
|
protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
|
||||||
try {
|
try {
|
||||||
JsonNode profile = SimpleHttp.doGet(PROFILE_URL).header("Authorization", "Bearer " + accessToken).asJson();
|
JsonNode profile = SimpleHttp.doGet(PROFILE_URL).header("Authorization", "Bearer " + accessToken).asJson();
|
||||||
|
|
||||||
String id = getJsonProperty(profile, "id");
|
String id = getJsonProperty(profile, "id");
|
||||||
|
|
||||||
FederatedIdentity user = new FederatedIdentity(id);
|
BrokeredIdentityContext user = new BrokeredIdentityContext(id);
|
||||||
|
|
||||||
String email = getJsonProperty(profile, "email");
|
String email = getJsonProperty(profile, "email");
|
||||||
|
|
||||||
|
@ -59,6 +59,8 @@ public class FacebookIdentityProvider extends AbstractOAuth2IdentityProvider imp
|
||||||
}
|
}
|
||||||
|
|
||||||
user.setName(firstName + lastName);
|
user.setName(firstName + lastName);
|
||||||
|
user.setIdpConfig(getConfig());
|
||||||
|
user.setIdp(this);
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import org.codehaus.jackson.JsonNode;
|
||||||
import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
|
import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
|
||||||
import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
|
import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
|
||||||
import org.keycloak.broker.oidc.util.SimpleHttp;
|
import org.keycloak.broker.oidc.util.SimpleHttp;
|
||||||
import org.keycloak.broker.provider.FederatedIdentity;
|
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||||
import org.keycloak.social.SocialIdentityProvider;
|
import org.keycloak.social.SocialIdentityProvider;
|
||||||
|
|
||||||
|
@ -26,15 +26,17 @@ public class GitHubIdentityProvider extends AbstractOAuth2IdentityProvider imple
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FederatedIdentity doGetFederatedIdentity(String accessToken) {
|
protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
|
||||||
try {
|
try {
|
||||||
JsonNode profile = SimpleHttp.doGet(PROFILE_URL).header("Authorization", "Bearer " + accessToken).asJson();
|
JsonNode profile = SimpleHttp.doGet(PROFILE_URL).header("Authorization", "Bearer " + accessToken).asJson();
|
||||||
|
|
||||||
FederatedIdentity user = new FederatedIdentity(getJsonProperty(profile, "id"));
|
BrokeredIdentityContext user = new BrokeredIdentityContext(getJsonProperty(profile, "id"));
|
||||||
|
|
||||||
user.setUsername(getJsonProperty(profile, "login"));
|
user.setUsername(getJsonProperty(profile, "login"));
|
||||||
user.setName(getJsonProperty(profile, "name"));
|
user.setName(getJsonProperty(profile, "name"));
|
||||||
user.setEmail(getJsonProperty(profile, "email"));
|
user.setEmail(getJsonProperty(profile, "email"));
|
||||||
|
user.setIdpConfig(getConfig());
|
||||||
|
user.setIdp(this);
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -26,7 +26,7 @@ import org.jboss.logging.Logger;
|
||||||
import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
|
import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
|
||||||
import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
|
import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
|
||||||
import org.keycloak.broker.oidc.util.SimpleHttp;
|
import org.keycloak.broker.oidc.util.SimpleHttp;
|
||||||
import org.keycloak.broker.provider.FederatedIdentity;
|
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||||
import org.keycloak.social.SocialIdentityProvider;
|
import org.keycloak.social.SocialIdentityProvider;
|
||||||
|
|
||||||
|
@ -52,16 +52,18 @@ public class LinkedInIdentityProvider extends AbstractOAuth2IdentityProvider imp
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FederatedIdentity doGetFederatedIdentity(String accessToken) {
|
protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
|
||||||
log.debug("doGetFederatedIdentity()");
|
log.debug("doGetFederatedIdentity()");
|
||||||
try {
|
try {
|
||||||
JsonNode profile = SimpleHttp.doGet(PROFILE_URL).header("Authorization", "Bearer " + accessToken).asJson();
|
JsonNode profile = SimpleHttp.doGet(PROFILE_URL).header("Authorization", "Bearer " + accessToken).asJson();
|
||||||
|
|
||||||
FederatedIdentity user = new FederatedIdentity(getJsonProperty(profile, "id"));
|
BrokeredIdentityContext user = new BrokeredIdentityContext(getJsonProperty(profile, "id"));
|
||||||
|
|
||||||
user.setUsername(extractUsernameFromProfileURL(getJsonProperty(profile, "publicProfileUrl")));
|
user.setUsername(extractUsernameFromProfileURL(getJsonProperty(profile, "publicProfileUrl")));
|
||||||
user.setName(getJsonProperty(profile, "formattedName"));
|
user.setName(getJsonProperty(profile, "formattedName"));
|
||||||
user.setEmail(getJsonProperty(profile, "emailAddress"));
|
user.setEmail(getJsonProperty(profile, "emailAddress"));
|
||||||
|
user.setIdpConfig(getConfig());
|
||||||
|
user.setIdp(this);
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ import org.codehaus.jackson.JsonNode;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
|
import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
|
||||||
import org.keycloak.broker.oidc.util.SimpleHttp;
|
import org.keycloak.broker.oidc.util.SimpleHttp;
|
||||||
import org.keycloak.broker.provider.FederatedIdentity;
|
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||||
import org.keycloak.social.SocialIdentityProvider;
|
import org.keycloak.social.SocialIdentityProvider;
|
||||||
|
|
||||||
|
@ -53,8 +53,10 @@ public class StackoverflowIdentityProvider extends AbstractOAuth2IdentityProvide
|
||||||
config.setUserInfoUrl(PROFILE_URL);
|
config.setUserInfoUrl(PROFILE_URL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected FederatedIdentity doGetFederatedIdentity(String accessToken) {
|
protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
|
||||||
log.debug("doGetFederatedIdentity()");
|
log.debug("doGetFederatedIdentity()");
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -64,12 +66,15 @@ public class StackoverflowIdentityProvider extends AbstractOAuth2IdentityProvide
|
||||||
}
|
}
|
||||||
JsonNode profile = SimpleHttp.doGet(URL).asJson().get("items").get(0);
|
JsonNode profile = SimpleHttp.doGet(URL).asJson().get("items").get(0);
|
||||||
|
|
||||||
FederatedIdentity user = new FederatedIdentity(getJsonProperty(profile, "user_id"));
|
BrokeredIdentityContext user = new BrokeredIdentityContext(getJsonProperty(profile, "user_id"));
|
||||||
|
|
||||||
user.setUsername(extractUsernameFromProfileURL(getJsonProperty(profile, "link")));
|
user.setUsername(extractUsernameFromProfileURL(getJsonProperty(profile, "link")));
|
||||||
user.setName(unescapeHtml3(getJsonProperty(profile, "display_name")));
|
user.setName(unescapeHtml3(getJsonProperty(profile, "display_name")));
|
||||||
// email is not provided
|
// email is not provided
|
||||||
// user.setEmail(getJsonProperty(profile, "email"));
|
// user.setEmail(getJsonProperty(profile, "email"));
|
||||||
|
user.setIdpConfig(getConfig());
|
||||||
|
user.setIdp(this);
|
||||||
|
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -26,7 +26,7 @@ import org.keycloak.ClientConnection;
|
||||||
import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
|
import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
|
||||||
import org.keycloak.broker.provider.AbstractIdentityProvider;
|
import org.keycloak.broker.provider.AbstractIdentityProvider;
|
||||||
import org.keycloak.broker.provider.AuthenticationRequest;
|
import org.keycloak.broker.provider.AuthenticationRequest;
|
||||||
import org.keycloak.broker.provider.FederatedIdentity;
|
import org.keycloak.broker.provider.BrokeredIdentityContext;
|
||||||
import org.keycloak.broker.provider.IdentityBrokerException;
|
import org.keycloak.broker.provider.IdentityBrokerException;
|
||||||
import org.keycloak.events.EventBuilder;
|
import org.keycloak.events.EventBuilder;
|
||||||
import org.keycloak.events.EventType;
|
import org.keycloak.events.EventType;
|
||||||
|
@ -52,7 +52,6 @@ import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import static org.keycloak.models.ClientSessionModel.Action.AUTHENTICATE;
|
import static org.keycloak.models.ClientSessionModel.Action.AUTHENTICATE;
|
||||||
|
|
||||||
|
@ -73,7 +72,7 @@ public class TwitterIdentityProvider extends AbstractIdentityProvider<OAuth2Iden
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response handleRequest(AuthenticationRequest request) {
|
public Response performLogin(AuthenticationRequest request) {
|
||||||
try {
|
try {
|
||||||
Twitter twitter = new TwitterFactory().getInstance();
|
Twitter twitter = new TwitterFactory().getInstance();
|
||||||
twitter.setOAuthConsumer(getConfig().getClientId(), getConfig().getClientSecret());
|
twitter.setOAuthConsumer(getConfig().getClientId(), getConfig().getClientSecret());
|
||||||
|
@ -135,7 +134,7 @@ public class TwitterIdentityProvider extends AbstractIdentityProvider<OAuth2Iden
|
||||||
AccessToken oAuthAccessToken = twitter.getOAuthAccessToken(requestToken, verifier);
|
AccessToken oAuthAccessToken = twitter.getOAuthAccessToken(requestToken, verifier);
|
||||||
twitter4j.User twitterUser = twitter.verifyCredentials();
|
twitter4j.User twitterUser = twitter.verifyCredentials();
|
||||||
|
|
||||||
FederatedIdentity identity = new FederatedIdentity(Long.toString(twitterUser.getId()));
|
BrokeredIdentityContext identity = new BrokeredIdentityContext(Long.toString(twitterUser.getId()));
|
||||||
|
|
||||||
identity.setUsername(twitterUser.getScreenName());
|
identity.setUsername(twitterUser.getScreenName());
|
||||||
identity.setName(twitterUser.getName());
|
identity.setName(twitterUser.getName());
|
||||||
|
@ -150,8 +149,10 @@ public class TwitterIdentityProvider extends AbstractIdentityProvider<OAuth2Iden
|
||||||
tokenBuilder.append("}");
|
tokenBuilder.append("}");
|
||||||
|
|
||||||
identity.setToken(tokenBuilder.toString());
|
identity.setToken(tokenBuilder.toString());
|
||||||
|
identity.setCode(state);
|
||||||
|
identity.setIdpConfig(getConfig());
|
||||||
|
|
||||||
return callback.authenticated(new HashMap<String, String>(), getConfig(), identity, state);
|
return callback.authenticated(identity);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Could get user profile from twitter.", e);
|
logger.error("Could get user profile from twitter.", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class CustomIdentityProvider extends AbstractIdentityProvider<IdentityPro
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response handleRequest(AuthenticationRequest request) {
|
public Response performLogin(AuthenticationRequest request) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class CustomSocialProvider extends AbstractIdentityProvider<IdentityProvi
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Response handleRequest(AuthenticationRequest request) {
|
public Response performLogin(AuthenticationRequest request) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue