-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[BACK-3125] Add SMART identity provider
- Loading branch information
1 parent
78de033
commit a3b2998
Showing
4 changed files
with
204 additions
and
0 deletions.
There are no files selected for viewing
74 changes: 74 additions & 0 deletions
74
admin/src/main/java/org/tidepool/keycloak/extensions/broker/SMARTIdentityProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package org.tidepool.keycloak.extensions.broker; | ||
|
||
import org.keycloak.broker.oidc.OIDCIdentityProvider; | ||
import org.keycloak.broker.oidc.OIDCIdentityProviderConfig; | ||
import org.keycloak.broker.oidc.OIDCIdentityProviderFactory; | ||
import org.keycloak.broker.provider.IdentityBrokerException; | ||
import org.keycloak.broker.provider.util.SimpleHttp; | ||
import org.keycloak.models.KeycloakSession; | ||
|
||
import java.io.IOException; | ||
import java.util.Arrays; | ||
import java.util.HashSet; | ||
|
||
public class SMARTIdentityProvider extends OIDCIdentityProvider { | ||
|
||
private static final String[] defaultForwardParameters = {"launch", "aud", "iss"}; | ||
|
||
private final String fhirVersion; | ||
|
||
public SMARTIdentityProvider(KeycloakSession session, SMARTIdentityProviderConfig config) { | ||
super(session, discoverConfig(session, config.getIssuer())); | ||
getConfig().setIssuer(config.getIssuer()); | ||
getConfig().setClientId(config.getClientId()); | ||
getConfig().setClientSecret(config.getClientSecret()); | ||
getConfig().setDefaultScope(config.getScopes()); | ||
getConfig().setAlias(config.getAlias()); | ||
getConfig().setForwardParameters(withDefaultForwardParameters(config.getForwardParameters())); | ||
|
||
fhirVersion = config.getFHIRVersion(); | ||
} | ||
|
||
private static String withDefaultForwardParameters(String params){ | ||
if (params == null) { | ||
params = ""; | ||
} | ||
|
||
HashSet<String> set = new HashSet<>(Arrays.asList(params.split(","))); | ||
set.addAll(Arrays.asList(defaultForwardParameters)); | ||
return String.join(",", set.stream().map(String::trim).toArray(String[]::new)); | ||
} | ||
|
||
private static OIDCIdentityProviderConfig discoverConfig(KeycloakSession session, String issuer) { | ||
OIDCIdentityProviderFactory factory = new OIDCIdentityProviderFactory(); | ||
OIDCIdentityProviderConfig identityProviderConfig = factory.createConfig(); | ||
|
||
if (issuer == null || issuer.isEmpty()) { | ||
return identityProviderConfig; | ||
} | ||
|
||
if (!issuer.endsWith("/")) { | ||
issuer = issuer + "/"; | ||
} | ||
|
||
String smartConfigurationUrl = issuer + ".well-known/smart-configuration"; | ||
SimpleHttp request = SimpleHttp.doGet(smartConfigurationUrl, session).header("Accept", "application/fhir+json"); | ||
|
||
try { | ||
SimpleHttp.Response response = request.asResponse(); | ||
if (response.getStatus() != 200) { | ||
String msg = "failed to invoke url [" + smartConfigurationUrl + "]"; | ||
String tmp = response.asString(); | ||
if (tmp != null) msg = tmp; | ||
|
||
throw new IdentityBrokerException("Failed to invoke url [" + smartConfigurationUrl + "]: " + msg); | ||
} | ||
|
||
identityProviderConfig.setConfig(factory.parseConfig(session, response.asString())); | ||
} catch (IOException e) { | ||
throw new IdentityBrokerException("Unable to retrieve smart configuration"); | ||
} | ||
|
||
return identityProviderConfig; | ||
} | ||
} |
62 changes: 62 additions & 0 deletions
62
admin/src/main/java/org/tidepool/keycloak/extensions/broker/SMARTIdentityProviderConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package org.tidepool.keycloak.extensions.broker; | ||
|
||
import org.keycloak.models.IdentityProviderModel; | ||
|
||
public class SMARTIdentityProviderConfig extends IdentityProviderModel { | ||
|
||
public SMARTIdentityProviderConfig(IdentityProviderModel identityProviderModel) { | ||
super(identityProviderModel); | ||
} | ||
|
||
public SMARTIdentityProviderConfig() { | ||
super(); | ||
} | ||
|
||
public String getIssuer() { | ||
return getConfig().get("issuer"); | ||
} | ||
|
||
public void setIssuer(String issuer) { | ||
getConfig().put("issuer", issuer); | ||
} | ||
|
||
public String getClientId() { | ||
return getConfig().get("clientId"); | ||
} | ||
|
||
public void setClientId(String clientId) { | ||
getConfig().put("clientId", clientId); | ||
} | ||
|
||
public String getClientSecret() { | ||
return getConfig().get("clientSecret"); | ||
} | ||
|
||
public void setClientSecret(String clientSecret) { | ||
getConfig().put("clientSecret", clientSecret); | ||
} | ||
|
||
public String getScopes() { | ||
return getConfig().get("scopes"); | ||
} | ||
|
||
public void setScopes(String scopes) { | ||
getConfig().put("scopes", scopes); | ||
} | ||
|
||
public String getForwardParameters() { | ||
return getConfig().get("forwardParameters"); | ||
} | ||
|
||
public void setForwardParameters(String params) { | ||
getConfig().put("forwardParameters", params); | ||
} | ||
|
||
public String getFHIRVersion() { | ||
return getConfig().get("fhirVersion"); | ||
} | ||
|
||
public void setFHIRVersion(String version) { | ||
getConfig().put("fhirVersion", version); | ||
} | ||
} |
67 changes: 67 additions & 0 deletions
67
...n/src/main/java/org/tidepool/keycloak/extensions/broker/SMARTIdentityProviderFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package org.tidepool.keycloak.extensions.broker; | ||
|
||
import org.keycloak.broker.provider.AbstractIdentityProviderFactory; | ||
import org.keycloak.models.IdentityProviderModel; | ||
import org.keycloak.models.KeycloakSession; | ||
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation; | ||
import org.keycloak.provider.ProviderConfigProperty; | ||
import org.keycloak.provider.ProviderConfigurationBuilder; | ||
import org.keycloak.util.JsonSerialization; | ||
|
||
import java.io.IOException; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class SMARTIdentityProviderFactory extends AbstractIdentityProviderFactory<SMARTIdentityProvider> { | ||
|
||
public static final String PROVIDER_ID = "smart"; | ||
|
||
public static final String[] SUPPORTED_FHIR_VERSIONS = {"R4"}; | ||
|
||
@Override | ||
public String getName() { | ||
return "SMART"; | ||
} | ||
|
||
@Override | ||
public SMARTIdentityProvider create(KeycloakSession session, IdentityProviderModel model) { | ||
return new SMARTIdentityProvider(session, new SMARTIdentityProviderConfig(model)); | ||
} | ||
|
||
@Override | ||
public IdentityProviderModel createConfig() { | ||
return new SMARTIdentityProviderConfig(); | ||
} | ||
|
||
@Override | ||
public Map<String, String> parseConfig(KeycloakSession session, String config) { | ||
return parseSMARTConfig(session, config); | ||
} | ||
|
||
protected static Map<String, String> parseSMARTConfig(KeycloakSession session, String configString) { | ||
OIDCConfigurationRepresentation rep; | ||
try { | ||
rep = JsonSerialization.readValue(configString, OIDCConfigurationRepresentation.class); | ||
} catch (IOException e) { | ||
throw new RuntimeException("failed to load openid connect metadata", e); | ||
} | ||
SMARTIdentityProviderConfig config = new SMARTIdentityProviderConfig(); | ||
config.setIssuer(rep.getIssuer()); | ||
return config.getConfig(); | ||
} | ||
|
||
@Override | ||
public List<ProviderConfigProperty> getConfigProperties() { | ||
return ProviderConfigurationBuilder.create() | ||
.property().name("issuer").label("Issuer").type(ProviderConfigProperty.STRING_TYPE).required(true).add() | ||
.property().name("scopes").label("Scopes").type(ProviderConfigProperty.STRING_TYPE).add() | ||
.property().name("forwardParameters").label("Forward Parameters").type(ProviderConfigProperty.STRING_TYPE).add() | ||
.property().name("fhirVersion").label("FHIR Version").type(ProviderConfigProperty.LIST_TYPE).options(SUPPORTED_FHIR_VERSIONS).defaultValue(SUPPORTED_FHIR_VERSIONS[0]).required(true).add() | ||
.build(); | ||
} | ||
|
||
@Override | ||
public String getId() { | ||
return PROVIDER_ID; | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
...src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderFactory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
org.tidepool.keycloak.extensions.broker.SMARTIdentityProviderFactory |