This commit is contained in:
Bill Burke 2013-07-19 21:33:44 -04:00
parent e1fe001a22
commit 33e9de654b
38 changed files with 3141 additions and 3800 deletions

View file

@ -1,8 +1,8 @@
package org.keycloak;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.keycloak.representations.AccessTokenResponse;
import org.jboss.resteasy.util.BasicAuthHelper;
import org.keycloak.representations.AccessTokenResponse;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.InternalServerErrorException;
@ -20,143 +20,116 @@ import java.util.concurrent.atomic.AtomicLong;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class AbstractOAuthClient
{
protected String clientId;
protected String password;
protected KeyStore truststore;
protected String authUrl;
protected String codeUrl;
protected String stateCookieName = "OAuth_Token_Request_State";
protected Client client;
protected final AtomicLong counter = new AtomicLong();
public class AbstractOAuthClient {
protected String clientId;
protected String password;
protected KeyStore truststore;
protected String authUrl;
protected String codeUrl;
protected String stateCookieName = "OAuth_Token_Request_State";
protected Client client;
protected final AtomicLong counter = new AtomicLong();
protected String getStateCode()
{
return counter.getAndIncrement() + "/" + UUID.randomUUID().toString();
}
protected String getStateCode() {
return counter.getAndIncrement() + "/" + UUID.randomUUID().toString();
}
public void start()
{
if (client == null)
{
client = new ResteasyClientBuilder().trustStore(truststore)
.hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY)
.connectionPoolSize(10)
.build();
}
}
public void start() {
if (client == null) {
client = new ResteasyClientBuilder().trustStore(truststore)
.hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY)
.connectionPoolSize(10)
.build();
}
}
public void stop()
{
client.close();
}
public void stop() {
client.close();
}
public String getClientId()
{
return clientId;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId)
{
this.clientId = clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getPassword()
{
return password;
}
public String getPassword() {
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public void setPassword(String password) {
this.password = password;
}
public KeyStore getTruststore()
{
return truststore;
}
public KeyStore getTruststore() {
return truststore;
}
public void setTruststore(KeyStore truststore)
{
this.truststore = truststore;
}
public void setTruststore(KeyStore truststore) {
this.truststore = truststore;
}
public String getAuthUrl()
{
return authUrl;
}
public String getAuthUrl() {
return authUrl;
}
public void setAuthUrl(String authUrl)
{
this.authUrl = authUrl;
}
public void setAuthUrl(String authUrl) {
this.authUrl = authUrl;
}
public String getCodeUrl()
{
return codeUrl;
}
public String getCodeUrl() {
return codeUrl;
}
public void setCodeUrl(String codeUrl)
{
this.codeUrl = codeUrl;
}
public void setCodeUrl(String codeUrl) {
this.codeUrl = codeUrl;
}
public String getStateCookieName()
{
return stateCookieName;
}
public String getStateCookieName() {
return stateCookieName;
}
public void setStateCookieName(String stateCookieName)
{
this.stateCookieName = stateCookieName;
}
public void setStateCookieName(String stateCookieName) {
this.stateCookieName = stateCookieName;
}
public Client getClient()
{
return client;
}
public Client getClient() {
return client;
}
public void setClient(Client client)
{
this.client = client;
}
public void setClient(Client client) {
this.client = client;
}
public String resolveBearerToken(String redirectUri, String code)
{
redirectUri = stripOauthParametersFromRedirect(redirectUri);
String authHeader = BasicAuthHelper.createHeader(clientId, password);
Form codeForm = new Form()
.param("grant_type", "authorization_code")
.param("code", code)
.param("redirect_uri", redirectUri);
Response res = client.target(codeUrl).request().header(HttpHeaders.AUTHORIZATION, authHeader).post(Entity.form(codeForm));
try
{
if (res.getStatus() == 400)
{
throw new BadRequestException();
}
else if (res.getStatus() != 200)
{
throw new InternalServerErrorException(new Exception("Unknown error when getting acess token"));
}
AccessTokenResponse tokenResponse = res.readEntity(AccessTokenResponse.class);
return tokenResponse.getToken();
}
finally
{
res.close();
}
}
public String resolveBearerToken(String redirectUri, String code) {
redirectUri = stripOauthParametersFromRedirect(redirectUri);
String authHeader = BasicAuthHelper.createHeader(clientId, password);
Form codeForm = new Form()
.param("grant_type", "authorization_code")
.param("code", code)
.param("redirect_uri", redirectUri);
Response res = client.target(codeUrl).request().header(HttpHeaders.AUTHORIZATION, authHeader).post(Entity.form(codeForm));
try {
if (res.getStatus() == 400) {
throw new BadRequestException();
} else if (res.getStatus() != 200) {
throw new InternalServerErrorException(new Exception("Unknown error when getting acess token"));
}
AccessTokenResponse tokenResponse = res.readEntity(AccessTokenResponse.class);
return tokenResponse.getToken();
} finally {
res.close();
}
}
protected String stripOauthParametersFromRedirect(String uri)
{
System.out.println("******************** redirect_uri: " + uri);
UriBuilder builder = UriBuilder.fromUri(uri)
.replaceQueryParam("code", null)
.replaceQueryParam("state", null);
return builder.build().toString();
}
protected String stripOauthParametersFromRedirect(String uri) {
System.out.println("******************** redirect_uri: " + uri);
UriBuilder builder = UriBuilder.fromUri(uri)
.replaceQueryParam("code", null)
.replaceQueryParam("state", null);
return builder.build().toString();
}
}

View file

@ -8,15 +8,12 @@ import java.security.Security;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class BouncyIntegration
{
static
{
if (Security.getProvider("BC") == null) Security.addProvider(new BouncyCastleProvider());
}
public class BouncyIntegration {
static {
if (Security.getProvider("BC") == null) Security.addProvider(new BouncyCastleProvider());
}
public static void init()
{
// empty, the static class does it
}
public static void init() {
// empty, the static class does it
}
}

View file

@ -20,49 +20,43 @@ import java.security.spec.X509EncodedKeySpec;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class DerUtils
{
static
{
BouncyIntegration.init();
}
public class DerUtils {
static {
BouncyIntegration.init();
}
public static PrivateKey decodePrivateKey(InputStream is)
throws Exception
{
public static PrivateKey decodePrivateKey(InputStream is)
throws Exception {
DataInputStream dis = new DataInputStream(is);
byte[] keyBytes = new byte[dis.available()];
dis.readFully(keyBytes);
dis.close();
DataInputStream dis = new DataInputStream(is);
byte[] keyBytes = new byte[dis.available()];
dis.readFully(keyBytes);
dis.close();
PKCS8EncodedKeySpec spec =
new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
return kf.generatePrivate(spec);
}
PKCS8EncodedKeySpec spec =
new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
return kf.generatePrivate(spec);
}
public static PublicKey decodePublicKey(byte[] der) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException
{
X509EncodedKeySpec spec =
new X509EncodedKeySpec(der);
KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
return kf.generatePublic(spec);
}
public static PublicKey decodePublicKey(byte[] der) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
X509EncodedKeySpec spec =
new X509EncodedKeySpec(der);
KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
return kf.generatePublic(spec);
}
public static X509Certificate decodeCertificate(InputStream is) throws Exception
{
CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
is.close();
return cert;
}
public static X509Certificate decodeCertificate(InputStream is) throws Exception {
CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
is.close();
return cert;
}
public static PrivateKey decodePrivateKey(byte[] der) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException
{
PKCS8EncodedKeySpec spec =
new PKCS8EncodedKeySpec(der);
KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
return kf.generatePrivate(spec);
}
public static PrivateKey decodePrivateKey(byte[] der) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {
PKCS8EncodedKeySpec spec =
new PKCS8EncodedKeySpec(der);
KeyFactory kf = KeyFactory.getInstance("RSA", "BC");
return kf.generatePrivate(spec);
}
}

View file

@ -7,30 +7,27 @@ import java.util.regex.Pattern;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class EnvUtil
{
private static final Pattern p = Pattern.compile("[$][{]([^}]+)[}]");
public class EnvUtil {
private static final Pattern p = Pattern.compile("[$][{]([^}]+)[}]");
/**
* Replaces any ${} strings with their corresponding environent variable.
*
* @param val
* @return
*/
public static String replace(String val)
{
Matcher matcher = p.matcher(val);
StringBuffer buf = new StringBuffer();
while (matcher.find())
{
String envVar = matcher.group(1);
String envVal = System.getProperty(envVar);
if (envVal == null) envVal = "NOT-SPECIFIED";
matcher.appendReplacement(buf, envVal.replace("\\", "\\\\"));
}
matcher.appendTail(buf);
return buf.toString();
}
/**
* Replaces any ${} strings with their corresponding environent variable.
*
* @param val
* @return
*/
public static String replace(String val) {
Matcher matcher = p.matcher(val);
StringBuffer buf = new StringBuffer();
while (matcher.find()) {
String envVar = matcher.group(1);
String envVal = System.getProperty(envVar);
if (envVal == null) envVal = "NOT-SPECIFIED";
matcher.appendReplacement(buf, envVal.replace("\\", "\\\\"));
}
matcher.appendTail(buf);
return buf.toString();
}
}

View file

@ -16,102 +16,92 @@ import java.security.cert.X509Certificate;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class PemUtils
{
static
{
BouncyIntegration.init();
}
public static X509Certificate decodeCertificate(InputStream is) throws Exception
{
byte[] der = pemToDer(is);
ByteArrayInputStream bis = new ByteArrayInputStream(der);
return DerUtils.decodeCertificate(bis);
}
public class PemUtils {
static {
BouncyIntegration.init();
}
public static X509Certificate decodeCertificate(String cert) throws Exception
{
byte[] der = pemToDer(cert);
ByteArrayInputStream bis = new ByteArrayInputStream(der);
return DerUtils.decodeCertificate(bis);
}
public static X509Certificate decodeCertificate(InputStream is) throws Exception {
byte[] der = pemToDer(is);
ByteArrayInputStream bis = new ByteArrayInputStream(der);
return DerUtils.decodeCertificate(bis);
}
public static X509Certificate decodeCertificate(String cert) throws Exception {
byte[] der = pemToDer(cert);
ByteArrayInputStream bis = new ByteArrayInputStream(der);
return DerUtils.decodeCertificate(bis);
}
/**
* Extract a public key from a PEM string
*
* @param pem
* @return
* @throws Exception
*/
public static PublicKey decodePublicKey(String pem) throws Exception
{
byte[] der = pemToDer(pem);
return DerUtils.decodePublicKey(der);
}
/**
* Extract a public key from a PEM string
*
* @param pem
* @return
* @throws Exception
*/
public static PublicKey decodePublicKey(String pem) throws Exception {
byte[] der = pemToDer(pem);
return DerUtils.decodePublicKey(der);
}
/**
* Extract a private key that is a PKCS8 pem string (base64 encoded PKCS8)
*
* @param pem
* @return
* @throws Exception
*/
public static PrivateKey decodePrivateKey(String pem) throws Exception
{
byte[] der = pemToDer(pem);
return DerUtils.decodePrivateKey(der);
}
/**
* Extract a private key that is a PKCS8 pem string (base64 encoded PKCS8)
*
* @param pem
* @return
* @throws Exception
*/
public static PrivateKey decodePrivateKey(String pem) throws Exception {
byte[] der = pemToDer(pem);
return DerUtils.decodePrivateKey(der);
}
public static PrivateKey decodePrivateKey(InputStream is) throws Exception
{
String pem = pemFromStream(is);
return decodePrivateKey(pem);
}
public static PrivateKey decodePrivateKey(InputStream is) throws Exception {
String pem = pemFromStream(is);
return decodePrivateKey(pem);
}
/**
* Decode a PEM file to DER format
*
* @param is
* @return
* @throws java.io.IOException
*/
public static byte[] pemToDer(InputStream is) throws IOException
{
String pem = pemFromStream(is);
byte[] der = pemToDer(pem);
return der;
}
/**
* Decode a PEM file to DER format
*
* @param is
* @return
* @throws java.io.IOException
*/
public static byte[] pemToDer(InputStream is) throws IOException {
String pem = pemFromStream(is);
byte[] der = pemToDer(pem);
return der;
}
/**
* Decode a PEM string to DER format
*
* @param pem
* @return
* @throws java.io.IOException
*/
public static byte[] pemToDer(String pem) throws IOException
{
pem = removeBeginEnd(pem);
return Base64.decode(pem);
}
/**
* Decode a PEM string to DER format
*
* @param pem
* @return
* @throws java.io.IOException
*/
public static byte[] pemToDer(String pem) throws IOException {
pem = removeBeginEnd(pem);
return Base64.decode(pem);
}
public static String removeBeginEnd(String pem)
{
pem = pem.replaceAll("-----BEGIN (.*)-----", "");
pem = pem.replaceAll("-----END (.*)----", "");
pem = pem.replaceAll("\r\n", "");
pem = pem.replaceAll("\n", "");
return pem.trim();
}
public static String removeBeginEnd(String pem) {
pem = pem.replaceAll("-----BEGIN (.*)-----", "");
pem = pem.replaceAll("-----END (.*)----", "");
pem = pem.replaceAll("\r\n", "");
pem = pem.replaceAll("\n", "");
return pem.trim();
}
public static String pemFromStream(InputStream is) throws IOException
{
DataInputStream dis = new DataInputStream(is);
byte[] keyBytes = new byte[dis.available()];
dis.readFully(keyBytes);
dis.close();
return new String(keyBytes, "utf-8");
}
public static String pemFromStream(InputStream is) throws IOException {
DataInputStream dis = new DataInputStream(is);
byte[] keyBytes = new byte[dis.available()];
dis.readFully(keyBytes);
dis.close();
return new String(keyBytes, "utf-8");
}
}

View file

@ -12,52 +12,40 @@ import java.security.PublicKey;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RSATokenVerifier
{
public static SkeletonKeyToken verifyToken(String tokenString, ResourceMetadata metadata) throws VerificationException
{
PublicKey realmKey = metadata.getRealmKey();
String realm = metadata.getRealm();
return verifyToken(tokenString, realmKey, realm);
}
public class RSATokenVerifier {
public static SkeletonKeyToken verifyToken(String tokenString, ResourceMetadata metadata) throws VerificationException {
PublicKey realmKey = metadata.getRealmKey();
String realm = metadata.getRealm();
return verifyToken(tokenString, realmKey, realm);
}
public static SkeletonKeyToken verifyToken(String tokenString, PublicKey realmKey, String realm) throws VerificationException
{
JWSInput input = new JWSInput(tokenString);
boolean verified = false;
try
{
verified = RSAProvider.verify(input, realmKey);
}
catch (Exception ignore)
{
public static SkeletonKeyToken verifyToken(String tokenString, PublicKey realmKey, String realm) throws VerificationException {
JWSInput input = new JWSInput(tokenString);
boolean verified = false;
try {
verified = RSAProvider.verify(input, realmKey);
} catch (Exception ignore) {
}
if (!verified) throw new VerificationException("Token signature not validated");
}
if (!verified) throw new VerificationException("Token signature not validated");
SkeletonKeyToken token = null;
try
{
token = JsonSerialization.fromBytes(SkeletonKeyToken.class, input.getContent());
}
catch (IOException e)
{
throw new VerificationException(e);
}
if (!token.isActive())
{
throw new VerificationException("Token is not active.");
}
String user = token.getPrincipal();
if (user == null)
{
throw new VerificationException("Token user was null");
}
if (!realm.equals(token.getAudience()))
{
throw new VerificationException("Token audience doesn't match domain");
SkeletonKeyToken token = null;
try {
token = JsonSerialization.fromBytes(SkeletonKeyToken.class, input.getContent());
} catch (IOException e) {
throw new VerificationException(e);
}
if (!token.isActive()) {
throw new VerificationException("Token is not active.");
}
String user = token.getPrincipal();
if (user == null) {
throw new VerificationException("Token user was null");
}
if (!realm.equals(token.getAudience())) {
throw new VerificationException("Token audience doesn't match domain");
}
return token;
}
}
return token;
}
}

View file

@ -10,89 +10,73 @@ import javax.ws.rs.core.UriBuilder;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RealmConfiguration
{
protected ResourceMetadata metadata;
protected ResteasyClient client;
protected UriBuilder authUrl;
protected ResteasyWebTarget codeUrl;
protected String clientId;
protected Form credentials = new Form();
protected boolean sslRequired = true;
protected String stateCookieName = "OAuth_Token_Request_State";
public class RealmConfiguration {
protected ResourceMetadata metadata;
protected ResteasyClient client;
protected UriBuilder authUrl;
protected ResteasyWebTarget codeUrl;
protected String clientId;
protected Form credentials = new Form();
protected boolean sslRequired = true;
protected String stateCookieName = "OAuth_Token_Request_State";
public ResourceMetadata getMetadata()
{
return metadata;
}
public ResourceMetadata getMetadata() {
return metadata;
}
public void setMetadata(ResourceMetadata metadata)
{
this.metadata = metadata;
}
public void setMetadata(ResourceMetadata metadata) {
this.metadata = metadata;
}
public ResteasyClient getClient()
{
return client;
}
public ResteasyClient getClient() {
return client;
}
public void setClient(ResteasyClient client)
{
this.client = client;
}
public void setClient(ResteasyClient client) {
this.client = client;
}
public UriBuilder getAuthUrl()
{
return authUrl;
}
public UriBuilder getAuthUrl() {
return authUrl;
}
public void setAuthUrl(UriBuilder authUrl)
{
this.authUrl = authUrl;
}
public void setAuthUrl(UriBuilder authUrl) {
this.authUrl = authUrl;
}
public String getClientId()
{
return clientId;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId)
{
this.clientId = clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public Form getCredentials()
{
return credentials;
}
public Form getCredentials() {
return credentials;
}
public ResteasyWebTarget getCodeUrl()
{
return codeUrl;
}
public ResteasyWebTarget getCodeUrl() {
return codeUrl;
}
public void setCodeUrl(ResteasyWebTarget codeUrl)
{
this.codeUrl = codeUrl;
}
public void setCodeUrl(ResteasyWebTarget codeUrl) {
this.codeUrl = codeUrl;
}
public boolean isSslRequired()
{
return sslRequired;
}
public boolean isSslRequired() {
return sslRequired;
}
public void setSslRequired(boolean sslRequired)
{
this.sslRequired = sslRequired;
}
public void setSslRequired(boolean sslRequired) {
this.sslRequired = sslRequired;
}
public String getStateCookieName()
{
return stateCookieName;
}
public String getStateCookieName() {
return stateCookieName;
}
public void setStateCookieName(String stateCookieName)
{
this.stateCookieName = stateCookieName;
}
public void setStateCookieName(String stateCookieName) {
this.stateCookieName = stateCookieName;
}
}

View file

@ -7,88 +7,75 @@ import java.security.PublicKey;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ResourceMetadata
{
protected String resourceName;
protected String realm;
protected KeyStore clientKeystore;
protected String clientKeyPassword;
protected KeyStore truststore;
protected PublicKey realmKey;
public class ResourceMetadata {
protected String resourceName;
protected String realm;
protected KeyStore clientKeystore;
protected String clientKeyPassword;
protected KeyStore truststore;
protected PublicKey realmKey;
public String getResourceName()
{
return resourceName;
}
public String getResourceName() {
return resourceName;
}
public String getRealm()
{
return realm;
}
public String getRealm() {
return realm;
}
/**
* keystore that contains service's private key and certificate.
* Used when making invocations on remote HTTPS endpoints that require client-cert authentication
*
* @return
*/
public KeyStore getClientKeystore()
{
return clientKeystore;
}
/**
* keystore that contains service's private key and certificate.
* Used when making invocations on remote HTTPS endpoints that require client-cert authentication
*
* @return
*/
public KeyStore getClientKeystore() {
return clientKeystore;
}
public String getClientKeyPassword()
{
return clientKeyPassword;
}
public String getClientKeyPassword() {
return clientKeyPassword;
}
public void setClientKeyPassword(String clientKeyPassword)
{
this.clientKeyPassword = clientKeyPassword;
}
public void setClientKeyPassword(String clientKeyPassword) {
this.clientKeyPassword = clientKeyPassword;
}
/**
* Truststore to use if this service makes client invocations on remote HTTPS endpoints.
*
* @return
*/
public KeyStore getTruststore()
{
return truststore;
}
/**
* Truststore to use if this service makes client invocations on remote HTTPS endpoints.
*
* @return
*/
public KeyStore getTruststore() {
return truststore;
}
/**
* Public key of the realm. Used to verify access tokens
*
* @return
*/
public PublicKey getRealmKey()
{
return realmKey;
}
/**
* Public key of the realm. Used to verify access tokens
*
* @return
*/
public PublicKey getRealmKey() {
return realmKey;
}
public void setResourceName(String resourceName)
{
this.resourceName = resourceName;
}
public void setResourceName(String resourceName) {
this.resourceName = resourceName;
}
public void setRealm(String realm)
{
this.realm = realm;
}
public void setRealm(String realm) {
this.realm = realm;
}
public void setClientKeystore(KeyStore clientKeystore)
{
this.clientKeystore = clientKeystore;
}
public void setClientKeystore(KeyStore clientKeystore) {
this.clientKeystore = clientKeystore;
}
public void setTruststore(KeyStore truststore)
{
this.truststore = truststore;
}
public void setTruststore(KeyStore truststore) {
this.truststore = truststore;
}
public void setRealmKey(PublicKey realmKey)
{
this.realmKey = realmKey;
}
public void setRealmKey(PublicKey realmKey) {
this.realmKey = realmKey;
}
}

View file

@ -14,29 +14,24 @@ import javax.ws.rs.ext.Provider;
* @version $Revision: 1 $
*/
@Provider
public class SkeletonKeyContextResolver implements ContextResolver<ObjectMapper>
{
protected ObjectMapper mapper = new ObjectMapper();
public class SkeletonKeyContextResolver implements ContextResolver<ObjectMapper> {
protected ObjectMapper mapper = new ObjectMapper();
public SkeletonKeyContextResolver()
{
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
}
public SkeletonKeyContextResolver() {
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
}
public SkeletonKeyContextResolver(boolean indent)
{
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
if (indent)
{
mapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
}
}
public SkeletonKeyContextResolver(boolean indent) {
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
if (indent) {
mapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
}
}
@Override
public ObjectMapper getContext(Class<?> type)
{
if (type.getPackage().getName().startsWith(getClass().getPackage().getName())) return mapper;
return null;
}
@Override
public ObjectMapper getContext(Class<?> type) {
if (type.getPackage().getName().startsWith(getClass().getPackage().getName())) return mapper;
return null;
}
}

View file

@ -6,53 +6,46 @@ import java.security.Principal;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SkeletonKeyPrincipal implements Principal
{
protected String name;
protected String surrogate;
public class SkeletonKeyPrincipal implements Principal {
protected String name;
protected String surrogate;
public SkeletonKeyPrincipal(String name, String surrogate)
{
this.name = name;
this.surrogate = surrogate;
}
public SkeletonKeyPrincipal(String name, String surrogate) {
this.name = name;
this.surrogate = surrogate;
}
@Override
public String getName()
{
return name;
}
@Override
public String getName() {
return name;
}
public String getSurrogate()
{
return surrogate;
}
public String getSurrogate() {
return surrogate;
}
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SkeletonKeyPrincipal that = (SkeletonKeyPrincipal) o;
SkeletonKeyPrincipal that = (SkeletonKeyPrincipal) o;
if (!name.equals(that.name)) return false;
if (surrogate != null ? !surrogate.equals(that.surrogate) : that.surrogate != null) return false;
if (!name.equals(that.name)) return false;
if (surrogate != null ? !surrogate.equals(that.surrogate) : that.surrogate != null) return false;
return true;
}
return true;
}
@Override
public int hashCode()
{
int result = name.hashCode();
result = 31 * result + (surrogate != null ? surrogate.hashCode() : 0);
return result;
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + (surrogate != null ? surrogate.hashCode() : 0);
return result;
}
@Override
public String toString()
{
return name;
}
@Override
public String toString() {
return name;
}
}

View file

@ -6,29 +6,24 @@ import java.io.Serializable;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SkeletonKeySession implements Serializable
{
protected String token;
protected transient ResourceMetadata metadata;
public class SkeletonKeySession implements Serializable {
protected String token;
protected transient ResourceMetadata metadata;
public SkeletonKeySession()
{
}
public SkeletonKeySession() {
}
public SkeletonKeySession(String token, ResourceMetadata metadata)
{
this.token = token;
this.metadata = metadata;
}
public SkeletonKeySession(String token, ResourceMetadata metadata) {
this.token = token;
this.metadata = metadata;
}
public String getToken()
{
return token;
}
public String getToken() {
return token;
}
public ResourceMetadata getMetadata()
{
return metadata;
}
public ResourceMetadata getMetadata() {
return metadata;
}
}

View file

@ -4,24 +4,19 @@ package org.keycloak;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class VerificationException extends Exception
{
public VerificationException()
{
}
public class VerificationException extends Exception {
public VerificationException() {
}
public VerificationException(String message)
{
super(message);
}
public VerificationException(String message) {
super(message);
}
public VerificationException(String message, Throwable cause)
{
super(message, cause);
}
public VerificationException(String message, Throwable cause) {
super(message, cause);
}
public VerificationException(Throwable cause)
{
super(cause);
}
public VerificationException(Throwable cause) {
super(cause);
}
}

View file

@ -1,13 +1,13 @@
package org.keycloak.jaxrs;
import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.RSATokenVerifier;
import org.keycloak.ResourceMetadata;
import org.keycloak.SkeletonKeyPrincipal;
import org.keycloak.SkeletonKeySession;
import org.keycloak.VerificationException;
import org.keycloak.representations.SkeletonKeyToken;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import javax.annotation.Priority;
import javax.ws.rs.Priorities;
@ -25,105 +25,87 @@ import java.security.Principal;
* @version $Revision: 1 $
*/
@Priority(Priorities.AUTHENTICATION)
public class JaxrsBearerTokenFilter implements ContainerRequestFilter
{
protected ResourceMetadata resourceMetadata;
private static Logger log = Logger.getLogger(JaxrsBearerTokenFilter.class);
public class JaxrsBearerTokenFilter implements ContainerRequestFilter {
protected ResourceMetadata resourceMetadata;
private static Logger log = Logger.getLogger(JaxrsBearerTokenFilter.class);
public JaxrsBearerTokenFilter(ResourceMetadata resourceMetadata)
{
this.resourceMetadata = resourceMetadata;
}
public JaxrsBearerTokenFilter(ResourceMetadata resourceMetadata) {
this.resourceMetadata = resourceMetadata;
}
protected void challengeResponse(ContainerRequestContext request, String error, String description)
{
StringBuilder header = new StringBuilder("Bearer realm=\"");
header.append(resourceMetadata.getRealm()).append("\"");
if (error != null)
{
header.append(", error=\"").append(error).append("\"");
}
if (description != null)
{
header.append(", error_description=\"").append(description).append("\"");
}
request.abortWith(Response.status(401).header("WWW-Authenticate", header.toString()).build());
return;
}
protected void challengeResponse(ContainerRequestContext request, String error, String description) {
StringBuilder header = new StringBuilder("Bearer realm=\"");
header.append(resourceMetadata.getRealm()).append("\"");
if (error != null) {
header.append(", error=\"").append(error).append("\"");
}
if (description != null) {
header.append(", error_description=\"").append(description).append("\"");
}
request.abortWith(Response.status(401).header("WWW-Authenticate", header.toString()).build());
return;
}
@Context
protected SecurityContext securityContext;
@Context
protected SecurityContext securityContext;
@Override
public void filter(ContainerRequestContext request) throws IOException
{
String authHeader = request.getHeaderString(HttpHeaders.AUTHORIZATION);
if (authHeader == null)
{
challengeResponse(request, null, null);
return;
}
@Override
public void filter(ContainerRequestContext request) throws IOException {
String authHeader = request.getHeaderString(HttpHeaders.AUTHORIZATION);
if (authHeader == null) {
challengeResponse(request, null, null);
return;
}
String[] split = authHeader.trim().split("\\s+");
if (split == null || split.length != 2) challengeResponse(request, null, null);
if (!split[0].equalsIgnoreCase("Bearer")) challengeResponse(request, null, null);
String[] split = authHeader.trim().split("\\s+");
if (split == null || split.length != 2) challengeResponse(request, null, null);
if (!split[0].equalsIgnoreCase("Bearer")) challengeResponse(request, null, null);
String tokenString = split[1];
String tokenString = split[1];
try
{
SkeletonKeyToken token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata);
SkeletonKeySession skSession = new SkeletonKeySession(tokenString, resourceMetadata);
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
String callerPrincipal = securityContext.getUserPrincipal() != null ? securityContext.getUserPrincipal().getName() : null;
try {
SkeletonKeyToken token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata);
SkeletonKeySession skSession = new SkeletonKeySession(tokenString, resourceMetadata);
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
String callerPrincipal = securityContext.getUserPrincipal() != null ? securityContext.getUserPrincipal().getName() : null;
final SkeletonKeyPrincipal principal = new SkeletonKeyPrincipal(token.getPrincipal(), callerPrincipal);
final boolean isSecure = securityContext.isSecure();
final SkeletonKeyToken.Access access;
if (resourceMetadata.getResourceName() != null)
{
access = token.getResourceAccess(resourceMetadata.getResourceName());
}
else
{
access = token.getRealmAccess();
}
SecurityContext ctx = new SecurityContext()
{
@Override
public Principal getUserPrincipal()
{
return principal;
final SkeletonKeyPrincipal principal = new SkeletonKeyPrincipal(token.getPrincipal(), callerPrincipal);
final boolean isSecure = securityContext.isSecure();
final SkeletonKeyToken.Access access;
if (resourceMetadata.getResourceName() != null) {
access = token.getResourceAccess(resourceMetadata.getResourceName());
} else {
access = token.getRealmAccess();
}
SecurityContext ctx = new SecurityContext() {
@Override
public Principal getUserPrincipal() {
return principal;
}
@Override
public boolean isUserInRole(String role)
{
if (access.getRoles() == null) return false;
return access.getRoles().contains(role);
}
@Override
public boolean isUserInRole(String role) {
if (access.getRoles() == null) return false;
return access.getRoles().contains(role);
}
@Override
public boolean isSecure()
{
return isSecure;
}
@Override
public boolean isSecure() {
return isSecure;
}
@Override
public String getAuthenticationScheme()
{
return "OAUTH_BEARER";
}
};
request.setSecurityContext(ctx);
}
catch (VerificationException e)
{
log.error("Failed to verify token", e);
challengeResponse(request, "invalid_token", e.getMessage());
}
}
@Override
public String getAuthenticationScheme() {
return "OAUTH_BEARER";
}
};
request.setSecurityContext(ctx);
} catch (VerificationException e) {
log.error("Failed to verify token", e);
challengeResponse(request, "invalid_token", e.getMessage());
}
}
}

View file

@ -18,38 +18,35 @@ import java.net.URI;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JaxrsOAuthClient extends AbstractOAuthClient
{
public Response redirect(UriInfo uriInfo, String redirectUri)
{
String state = getStateCode();
public class JaxrsOAuthClient extends AbstractOAuthClient {
public Response redirect(UriInfo uriInfo, String redirectUri) {
String state = getStateCode();
URI url = UriBuilder.fromUri(authUrl)
.queryParam("client_id", clientId)
.queryParam("redirect_uri", redirectUri)
.queryParam("state", state)
.build();
NewCookie cookie = new NewCookie(stateCookieName, state, uriInfo.getBaseUri().getPath(), null, null, -1, true);
return Response.status(302)
.location(url)
.cookie(cookie).build();
}
URI url = UriBuilder.fromUri(authUrl)
.queryParam("client_id", clientId)
.queryParam("redirect_uri", redirectUri)
.queryParam("state", state)
.build();
NewCookie cookie = new NewCookie(stateCookieName, state, uriInfo.getBaseUri().getPath(), null, null, -1, true);
return Response.status(302)
.location(url)
.cookie(cookie).build();
}
public String getBearerToken(UriInfo uriInfo, HttpHeaders headers) throws BadRequestException, InternalServerErrorException
{
String error = uriInfo.getQueryParameters().getFirst("error");
if (error != null) throw new BadRequestException(new Exception("OAuth error: " + error));
Cookie stateCookie = headers.getCookies().get(stateCookieName);
if (stateCookie == null) throw new BadRequestException(new Exception("state cookie not set"));;
public String getBearerToken(UriInfo uriInfo, HttpHeaders headers) throws BadRequestException, InternalServerErrorException {
String error = uriInfo.getQueryParameters().getFirst("error");
if (error != null) throw new BadRequestException(new Exception("OAuth error: " + error));
Cookie stateCookie = headers.getCookies().get(stateCookieName);
if (stateCookie == null) throw new BadRequestException(new Exception("state cookie not set"));
;
String state = uriInfo.getQueryParameters().getFirst("state");
if (state == null) throw new BadRequestException(new Exception("state parameter was null"));
if (!state.equals(stateCookie.getValue()))
{
throw new BadRequestException(new Exception("state parameter invalid"));
}
String code = uriInfo.getQueryParameters().getFirst("code");
if (code == null) throw new BadRequestException(new Exception("code parameter was null"));
return resolveBearerToken(uriInfo.getRequestUri().toString(), code);
}
String state = uriInfo.getQueryParameters().getFirst("state");
if (state == null) throw new BadRequestException(new Exception("state parameter was null"));
if (!state.equals(stateCookie.getValue())) {
throw new BadRequestException(new Exception("state parameter invalid"));
}
String code = uriInfo.getQueryParameters().getFirst("code");
if (code == null) throw new BadRequestException(new Exception("code parameter was null"));
return resolveBearerToken(uriInfo.getRequestUri().toString(), code);
}
}

View file

@ -8,57 +8,48 @@ import org.codehaus.jackson.annotate.JsonProperty;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class AccessTokenResponse
{
@JsonProperty("access_token")
protected String token;
public class AccessTokenResponse {
@JsonProperty("access_token")
protected String token;
@JsonProperty("expires_in")
protected long expiresIn;
@JsonProperty("expires_in")
protected long expiresIn;
@JsonProperty("refresh_token")
protected String refreshToken;
@JsonProperty("refresh_token")
protected String refreshToken;
@JsonProperty("token_type")
protected String tokenType;
@JsonProperty("token_type")
protected String tokenType;
public String getToken()
{
return token;
}
public String getToken() {
return token;
}
public void setToken(String token)
{
this.token = token;
}
public void setToken(String token) {
this.token = token;
}
public long getExpiresIn()
{
return expiresIn;
}
public long getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(long expiresIn)
{
this.expiresIn = expiresIn;
}
public void setExpiresIn(long expiresIn) {
this.expiresIn = expiresIn;
}
public String getRefreshToken()
{
return refreshToken;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken)
{
this.refreshToken = refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public String getTokenType()
{
return tokenType;
}
public String getTokenType() {
return tokenType;
}
public void setTokenType(String tokenType)
{
this.tokenType = tokenType;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
}

View file

@ -8,6 +8,5 @@ import javax.ws.rs.core.MultivaluedHashMap;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SkeletonKeyScope extends MultivaluedHashMap<String, String>
{
public class SkeletonKeyScope extends MultivaluedHashMap<String, String> {
}

View file

@ -13,190 +13,164 @@ import java.util.Set;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class SkeletonKeyToken extends JsonWebToken
{
public static class Access
{
@JsonProperty("roles")
protected Set<String> roles;
@JsonProperty("verify_caller")
protected Boolean verifyCaller;
public class SkeletonKeyToken extends JsonWebToken {
public static class Access {
@JsonProperty("roles")
protected Set<String> roles;
@JsonProperty("verify_caller")
protected Boolean verifyCaller;
public Set<String> getRoles()
{
return roles;
}
public Set<String> getRoles() {
return roles;
}
public Access roles(Set<String> roles)
{
this.roles = roles;
return this;
}
public Access roles(Set<String> roles) {
this.roles = roles;
return this;
}
@JsonIgnore
public boolean isUserInRole(String role)
{
if (roles == null) return false;
return roles.contains(role);
}
@JsonIgnore
public boolean isUserInRole(String role) {
if (roles == null) return false;
return roles.contains(role);
}
public Access addRole(String role)
{
if (roles == null) roles = new HashSet<String>();
roles.add(role);
return this;
}
public Access addRole(String role) {
if (roles == null) roles = new HashSet<String>();
roles.add(role);
return this;
}
public Boolean getVerifyCaller()
{
return verifyCaller;
}
public Boolean getVerifyCaller() {
return verifyCaller;
}
public Access verifyCaller(Boolean required)
{
this.verifyCaller = required;
return this;
}
}
public Access verifyCaller(Boolean required) {
this.verifyCaller = required;
return this;
}
}
@JsonProperty("issuedFor")
public String issuedFor;
@JsonProperty("issuedFor")
public String issuedFor;
@JsonProperty("trusted-certs")
protected Set<String> trustedCertificates;
@JsonProperty("trusted-certs")
protected Set<String> trustedCertificates;
@JsonProperty("realm_access")
protected Access realmAccess;
@JsonProperty("realm_access")
protected Access realmAccess;
@JsonProperty("resource_access")
protected Map<String, Access> resourceAccess = new HashMap<String, Access>();
@JsonProperty("resource_access")
protected Map<String, Access> resourceAccess = new HashMap<String, Access>();
public Map<String, Access> getResourceAccess()
{
return resourceAccess;
}
public Map<String, Access> getResourceAccess() {
return resourceAccess;
}
/**
* Does the realm require verifying the caller?
*
* @return
*/
@JsonIgnore
public boolean isVerifyCaller()
{
if (getRealmAccess() != null && getRealmAccess().getVerifyCaller() != null) return getRealmAccess().getVerifyCaller().booleanValue();
return false;
}
/**
* Does the realm require verifying the caller?
*
* @return
*/
@JsonIgnore
public boolean isVerifyCaller() {
if (getRealmAccess() != null && getRealmAccess().getVerifyCaller() != null)
return getRealmAccess().getVerifyCaller().booleanValue();
return false;
}
/**
* Does the resource override the requirement of verifying the caller?
*
* @param resource
* @return
*/
@JsonIgnore
public boolean isVerifyCaller(String resource)
{
Access access = getResourceAccess(resource);
if (access != null && access.getVerifyCaller() != null) return access.getVerifyCaller().booleanValue();
return false;
}
/**
* Does the resource override the requirement of verifying the caller?
*
* @param resource
* @return
*/
@JsonIgnore
public boolean isVerifyCaller(String resource) {
Access access = getResourceAccess(resource);
if (access != null && access.getVerifyCaller() != null) return access.getVerifyCaller().booleanValue();
return false;
}
@JsonIgnore
public Access getResourceAccess(String resource)
{
return resourceAccess.get(resource);
}
@JsonIgnore
public Access getResourceAccess(String resource) {
return resourceAccess.get(resource);
}
public Access addAccess(String service)
{
Access token = new Access();
resourceAccess.put(service, token);
return token;
}
public Access addAccess(String service) {
Access token = new Access();
resourceAccess.put(service, token);
return token;
}
@Override
public SkeletonKeyToken id(String id)
{
return (SkeletonKeyToken)super.id(id);
}
@Override
public SkeletonKeyToken id(String id) {
return (SkeletonKeyToken) super.id(id);
}
@Override
public SkeletonKeyToken expiration(long expiration)
{
return (SkeletonKeyToken)super.expiration(expiration);
}
@Override
public SkeletonKeyToken expiration(long expiration) {
return (SkeletonKeyToken) super.expiration(expiration);
}
@Override
public SkeletonKeyToken notBefore(long notBefore)
{
return (SkeletonKeyToken)super.notBefore(notBefore);
}
@Override
public SkeletonKeyToken notBefore(long notBefore) {
return (SkeletonKeyToken) super.notBefore(notBefore);
}
@Override
public SkeletonKeyToken issuedAt(long issuedAt)
{
return (SkeletonKeyToken)super.issuedAt(issuedAt);
}
@Override
public SkeletonKeyToken issuedAt(long issuedAt) {
return (SkeletonKeyToken) super.issuedAt(issuedAt);
}
@Override
public SkeletonKeyToken issuer(String issuer)
{
return (SkeletonKeyToken)super.issuer(issuer);
}
@Override
public SkeletonKeyToken issuer(String issuer) {
return (SkeletonKeyToken) super.issuer(issuer);
}
@Override
public SkeletonKeyToken audience(String audience)
{
return (SkeletonKeyToken)super.audience(audience);
}
@Override
public SkeletonKeyToken audience(String audience) {
return (SkeletonKeyToken) super.audience(audience);
}
@Override
public SkeletonKeyToken principal(String principal)
{
return (SkeletonKeyToken)super.principal(principal);
}
@Override
public SkeletonKeyToken principal(String principal) {
return (SkeletonKeyToken) super.principal(principal);
}
@Override
public SkeletonKeyToken type(String type)
{
return (SkeletonKeyToken)super.type(type);
}
@Override
public SkeletonKeyToken type(String type) {
return (SkeletonKeyToken) super.type(type);
}
public Access getRealmAccess()
{
return realmAccess;
}
public Access getRealmAccess() {
return realmAccess;
}
public void setRealmAccess(Access realmAccess)
{
this.realmAccess = realmAccess;
}
public void setRealmAccess(Access realmAccess) {
this.realmAccess = realmAccess;
}
public Set<String> getTrustedCertificates()
{
return trustedCertificates;
}
public Set<String> getTrustedCertificates() {
return trustedCertificates;
}
public void setTrustedCertificates(Set<String> trustedCertificates)
{
this.trustedCertificates = trustedCertificates;
}
public void setTrustedCertificates(Set<String> trustedCertificates) {
this.trustedCertificates = trustedCertificates;
}
/**
* OAuth client the token was issued for.
*
* @return
*/
public String getIssuedFor()
{
return issuedFor;
}
/**
* OAuth client the token was issued for.
*
* @return
*/
public String getIssuedFor() {
return issuedFor;
}
public SkeletonKeyToken issuedFor(String issuedFor)
{
this.issuedFor = issuedFor;
return this;
}
public SkeletonKeyToken issuedFor(String issuedFor) {
this.issuedFor = issuedFor;
return this;
}
}

View file

@ -13,137 +13,123 @@ import java.security.PublicKey;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class PublishedRealmRepresentation
{
protected String realm;
protected String self;
public class PublishedRealmRepresentation {
protected String realm;
protected String self;
@JsonProperty("public_key")
protected String publicKeyPem;
@JsonProperty("public_key")
protected String publicKeyPem;
@JsonProperty("authorization")
protected String authorizationUrl;
@JsonProperty("authorization")
protected String authorizationUrl;
@JsonProperty("codes")
protected String codeUrl;
@JsonProperty("codes")
protected String codeUrl;
@JsonProperty("grants")
protected String grantUrl;
@JsonProperty("grants")
protected String grantUrl;
@JsonProperty("identity-grants")
protected String identityGrantUrl;
@JsonProperty("identity-grants")
protected String identityGrantUrl;
@JsonIgnore
protected volatile transient PublicKey publicKey;
@JsonProperty("admin-role")
protected String adminRole;
@JsonIgnore
protected volatile transient PublicKey publicKey;
public String getAdminRole() {
return adminRole;
}
public void setAdminRole(String adminRole) {
this.adminRole = adminRole;
}
public String getRealm() {
return realm;
}
public void setRealm(String realm) {
this.realm = realm;
}
public String getSelf() {
return self;
}
public void setSelf(String self) {
this.self = self;
}
public String getPublicKeyPem() {
return publicKeyPem;
}
public void setPublicKeyPem(String publicKeyPem) {
this.publicKeyPem = publicKeyPem;
this.publicKey = null;
}
public String getRealm()
{
return realm;
}
@JsonIgnore
public PublicKey getPublicKey() {
if (publicKey != null) return publicKey;
if (publicKeyPem != null) {
try {
publicKey = PemUtils.decodePublicKey(publicKeyPem);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return publicKey;
}
public void setRealm(String realm)
{
this.realm = realm;
}
public String getSelf()
{
return self;
}
public void setSelf(String self)
{
this.self = self;
}
public String getPublicKeyPem()
{
return publicKeyPem;
}
public void setPublicKeyPem(String publicKeyPem)
{
this.publicKeyPem = publicKeyPem;
this.publicKey = null;
}
@JsonIgnore
public PublicKey getPublicKey()
{
if (publicKey != null) return publicKey;
if (publicKeyPem != null)
{
try
{
publicKey = PemUtils.decodePublicKey(publicKeyPem);
}
catch (Exception e)
{
@JsonIgnore
public void setPublicKey(PublicKey publicKey) {
this.publicKey = publicKey;
StringWriter writer = new StringWriter();
PEMWriter pemWriter = new PEMWriter(writer);
try {
pemWriter.writeObject(publicKey);
pemWriter.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return publicKey;
}
@JsonIgnore
public void setPublicKey(PublicKey publicKey)
{
this.publicKey = publicKey;
StringWriter writer = new StringWriter();
PEMWriter pemWriter = new PEMWriter(writer);
try
{
pemWriter.writeObject(publicKey);
pemWriter.flush();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
String s = writer.toString();
this.publicKeyPem = PemUtils.removeBeginEnd(s);
}
}
String s = writer.toString();
this.publicKeyPem = PemUtils.removeBeginEnd(s);
}
public String getAuthorizationUrl()
{
return authorizationUrl;
}
public String getAuthorizationUrl() {
return authorizationUrl;
}
public void setAuthorizationUrl(String authorizationUrl)
{
this.authorizationUrl = authorizationUrl;
}
public void setAuthorizationUrl(String authorizationUrl) {
this.authorizationUrl = authorizationUrl;
}
public String getCodeUrl()
{
return codeUrl;
}
public String getCodeUrl() {
return codeUrl;
}
public void setCodeUrl(String codeUrl)
{
this.codeUrl = codeUrl;
}
public void setCodeUrl(String codeUrl) {
this.codeUrl = codeUrl;
}
public String getGrantUrl()
{
return grantUrl;
}
public String getGrantUrl() {
return grantUrl;
}
public void setGrantUrl(String grantUrl)
{
this.grantUrl = grantUrl;
}
public void setGrantUrl(String grantUrl) {
this.grantUrl = grantUrl;
}
public String getIdentityGrantUrl()
{
return identityGrantUrl;
}
public String getIdentityGrantUrl() {
return identityGrantUrl;
}
public void setIdentityGrantUrl(String identityGrantUrl)
{
this.identityGrantUrl = identityGrantUrl;
}
public void setIdentityGrantUrl(String identityGrantUrl) {
this.identityGrantUrl = identityGrantUrl;
}
}

View file

@ -8,176 +8,147 @@ import java.util.Set;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RealmRepresentation
{
protected String self; // link
protected String realm;
protected long tokenLifespan;
protected long accessCodeLifespan;
protected boolean enabled;
protected boolean sslNotRequired;
protected boolean cookieLoginAllowed;
protected Set<String> roles;
protected List<RequiredCredentialRepresentation> requiredCredentials;
protected List<UserRepresentation> users;
protected List<RoleMappingRepresentation> roleMappings;
protected List<ScopeMappingRepresentation> scopeMappings;
protected List<ResourceRepresentation> resources;
public class RealmRepresentation {
protected String self; // link
protected String realm;
protected long tokenLifespan;
protected long accessCodeLifespan;
protected boolean enabled;
protected boolean sslNotRequired;
protected boolean cookieLoginAllowed;
protected Set<String> roles;
protected List<RequiredCredentialRepresentation> requiredCredentials;
protected List<UserRepresentation> users;
protected List<RoleMappingRepresentation> roleMappings;
protected List<ScopeMappingRepresentation> scopeMappings;
protected List<ResourceRepresentation> resources;
public String getSelf()
{
return self;
}
public String getSelf() {
return self;
}
public void setSelf(String self)
{
this.self = self;
}
public void setSelf(String self) {
this.self = self;
}
public String getRealm()
{
return realm;
}
public String getRealm() {
return realm;
}
public void setRealm(String realm)
{
this.realm = realm;
}
public void setRealm(String realm) {
this.realm = realm;
}
public List<UserRepresentation> getUsers()
{
return users;
}
public List<UserRepresentation> getUsers() {
return users;
}
public List<ResourceRepresentation> getResources()
{
return resources;
}
public List<ResourceRepresentation> getResources() {
return resources;
}
public ResourceRepresentation resource(String name)
{
ResourceRepresentation resource = new ResourceRepresentation();
if (resources == null) resources = new ArrayList<ResourceRepresentation>();
resources.add(resource);
resource.setName(name);
return resource;
}
public ResourceRepresentation resource(String name) {
ResourceRepresentation resource = new ResourceRepresentation();
if (resources == null) resources = new ArrayList<ResourceRepresentation>();
resources.add(resource);
resource.setName(name);
return resource;
}
public void setUsers(List<UserRepresentation> users)
{
this.users = users;
}
public void setUsers(List<UserRepresentation> users) {
this.users = users;
}
public UserRepresentation user(String username)
{
UserRepresentation user = new UserRepresentation();
user.setUsername(username);
if (users == null) users = new ArrayList<UserRepresentation>();
users.add(user);
return user;
}
public UserRepresentation user(String username) {
UserRepresentation user = new UserRepresentation();
user.setUsername(username);
if (users == null) users = new ArrayList<UserRepresentation>();
users.add(user);
return user;
}
public void setResources(List<ResourceRepresentation> resources)
{
this.resources = resources;
}
public void setResources(List<ResourceRepresentation> resources) {
this.resources = resources;
}
public boolean isEnabled()
{
return enabled;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isSslNotRequired()
{
return sslNotRequired;
}
public boolean isSslNotRequired() {
return sslNotRequired;
}
public void setSslNotRequired(boolean sslNotRequired)
{
this.sslNotRequired = sslNotRequired;
}
public void setSslNotRequired(boolean sslNotRequired) {
this.sslNotRequired = sslNotRequired;
}
public boolean isCookieLoginAllowed()
{
return cookieLoginAllowed;
}
public boolean isCookieLoginAllowed() {
return cookieLoginAllowed;
}
public void setCookieLoginAllowed(boolean cookieLoginAllowed)
{
this.cookieLoginAllowed = cookieLoginAllowed;
}
public void setCookieLoginAllowed(boolean cookieLoginAllowed) {
this.cookieLoginAllowed = cookieLoginAllowed;
}
public long getTokenLifespan()
{
return tokenLifespan;
}
public long getTokenLifespan() {
return tokenLifespan;
}
public void setTokenLifespan(long tokenLifespan)
{
this.tokenLifespan = tokenLifespan;
}
public void setTokenLifespan(long tokenLifespan) {
this.tokenLifespan = tokenLifespan;
}
public List<RoleMappingRepresentation> getRoleMappings()
{
return roleMappings;
}
public List<RoleMappingRepresentation> getRoleMappings() {
return roleMappings;
}
public RoleMappingRepresentation roleMapping(String username)
{
RoleMappingRepresentation mapping = new RoleMappingRepresentation();
mapping.setUsername(username);
if (roleMappings == null) roleMappings = new ArrayList<RoleMappingRepresentation>();
roleMappings.add(mapping);
return mapping;
}
public RoleMappingRepresentation roleMapping(String username) {
RoleMappingRepresentation mapping = new RoleMappingRepresentation();
mapping.setUsername(username);
if (roleMappings == null) roleMappings = new ArrayList<RoleMappingRepresentation>();
roleMappings.add(mapping);
return mapping;
}
public List<ScopeMappingRepresentation> getScopeMappings()
{
return scopeMappings;
}
public List<ScopeMappingRepresentation> getScopeMappings() {
return scopeMappings;
}
public ScopeMappingRepresentation scopeMapping(String username)
{
ScopeMappingRepresentation mapping = new ScopeMappingRepresentation();
mapping.setUsername(username);
if (scopeMappings == null) scopeMappings = new ArrayList<ScopeMappingRepresentation>();
scopeMappings.add(mapping);
return mapping;
}
public ScopeMappingRepresentation scopeMapping(String username) {
ScopeMappingRepresentation mapping = new ScopeMappingRepresentation();
mapping.setUsername(username);
if (scopeMappings == null) scopeMappings = new ArrayList<ScopeMappingRepresentation>();
scopeMappings.add(mapping);
return mapping;
}
public List<RequiredCredentialRepresentation> getRequiredCredentials()
{
return requiredCredentials;
}
public List<RequiredCredentialRepresentation> getRequiredCredentials() {
return requiredCredentials;
}
public void setRequiredCredentials(List<RequiredCredentialRepresentation> requiredCredentials)
{
this.requiredCredentials = requiredCredentials;
}
public void setRequiredCredentials(List<RequiredCredentialRepresentation> requiredCredentials) {
this.requiredCredentials = requiredCredentials;
}
public long getAccessCodeLifespan()
{
return accessCodeLifespan;
}
public long getAccessCodeLifespan() {
return accessCodeLifespan;
}
public void setAccessCodeLifespan(long accessCodeLifespan)
{
this.accessCodeLifespan = accessCodeLifespan;
}
public void setAccessCodeLifespan(long accessCodeLifespan) {
this.accessCodeLifespan = accessCodeLifespan;
}
public Set<String> getRoles()
{
return roles;
}
public Set<String> getRoles() {
return roles;
}
public void setRoles(Set<String> roles)
{
this.roles = roles;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
}

View file

@ -4,43 +4,36 @@ package org.keycloak.representations.idm;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RequiredCredentialRepresentation
{
public static final String PASSWORD = "Password";
public static final String TOTP = "TOTP";
public static final String CLIENT_CERT = "CLIENT_CERT";
public static final String CALLER_PRINCIPAL = "CALLER_PRINCIPAL";
protected String type;
protected boolean input;
protected boolean secret;
public class RequiredCredentialRepresentation {
public static final String PASSWORD = "Password";
public static final String TOTP = "TOTP";
public static final String CLIENT_CERT = "CLIENT_CERT";
public static final String CALLER_PRINCIPAL = "CALLER_PRINCIPAL";
protected String type;
protected boolean input;
protected boolean secret;
public String getType()
{
return type;
}
public String getType() {
return type;
}
public void setType(String type)
{
this.type = type;
}
public void setType(String type) {
this.type = type;
}
public boolean isInput()
{
return input;
}
public boolean isInput() {
return input;
}
public void setInput(boolean input)
{
this.input = input;
}
public void setInput(boolean input) {
this.input = input;
}
public boolean isSecret()
{
return secret;
}
public boolean isSecret() {
return secret;
}
public void setSecret(boolean secret)
{
this.secret = secret;
}
public void setSecret(boolean secret) {
this.secret = secret;
}
}

View file

@ -6,92 +6,78 @@ import java.util.List;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ResourceRepresentation
{
protected String self; // link
protected String name;
protected boolean surrogateAuthRequired;
protected Set<String> roles;
protected List<RoleMappingRepresentation> roleMappings;
protected List<ScopeMappingRepresentation> scopeMappings;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ResourceRepresentation {
protected String self; // link
protected String name;
protected boolean surrogateAuthRequired;
protected Set<String> roles;
protected List<RoleMappingRepresentation> roleMappings;
protected List<ScopeMappingRepresentation> scopeMappings;
public String getSelf()
{
return self;
}
public String getSelf() {
return self;
}
public void setSelf(String self)
{
this.self = self;
}
public void setSelf(String self) {
this.self = self;
}
public String getName()
{
return name;
}
public String getName() {
return name;
}
public void setName(String name)
{
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public boolean isSurrogateAuthRequired()
{
return surrogateAuthRequired;
}
public boolean isSurrogateAuthRequired() {
return surrogateAuthRequired;
}
public void setSurrogateAuthRequired(boolean surrogateAuthRequired)
{
this.surrogateAuthRequired = surrogateAuthRequired;
}
public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
this.surrogateAuthRequired = surrogateAuthRequired;
}
public Set<String> getRoles()
{
return roles;
}
public Set<String> getRoles() {
return roles;
}
public void setRoles(Set<String> roles)
{
this.roles = roles;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
public ResourceRepresentation role(String role)
{
if (this.roles == null) this.roles = new HashSet<String>();
this.roles.add(role);
return this;
}
public ResourceRepresentation role(String role) {
if (this.roles == null) this.roles = new HashSet<String>();
this.roles.add(role);
return this;
}
public List<RoleMappingRepresentation> getRoleMappings()
{
return roleMappings;
}
public List<RoleMappingRepresentation> getRoleMappings() {
return roleMappings;
}
public RoleMappingRepresentation roleMapping(String username)
{
RoleMappingRepresentation mapping = new RoleMappingRepresentation();
mapping.setUsername(username);
if (roleMappings == null) roleMappings = new ArrayList<RoleMappingRepresentation>();
roleMappings.add(mapping);
return mapping;
}
public RoleMappingRepresentation roleMapping(String username) {
RoleMappingRepresentation mapping = new RoleMappingRepresentation();
mapping.setUsername(username);
if (roleMappings == null) roleMappings = new ArrayList<RoleMappingRepresentation>();
roleMappings.add(mapping);
return mapping;
}
public List<ScopeMappingRepresentation> getScopeMappings()
{
return scopeMappings;
}
public List<ScopeMappingRepresentation> getScopeMappings() {
return scopeMappings;
}
public ScopeMappingRepresentation scopeMapping(String username)
{
ScopeMappingRepresentation mapping = new ScopeMappingRepresentation();
mapping.setUsername(username);
if (scopeMappings == null) scopeMappings = new ArrayList<ScopeMappingRepresentation>();
scopeMappings.add(mapping);
return mapping;
}
public ScopeMappingRepresentation scopeMapping(String username) {
ScopeMappingRepresentation mapping = new ScopeMappingRepresentation();
mapping.setUsername(username);
if (scopeMappings == null) scopeMappings = new ArrayList<ScopeMappingRepresentation>();
scopeMappings.add(mapping);
return mapping;
}
}

View file

@ -4,52 +4,42 @@ import java.util.HashSet;
import java.util.Set;
/**
*
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RoleMappingRepresentation
{
protected String self; // link
protected String username;
protected Set<String> roles;
public class RoleMappingRepresentation {
protected String self; // link
protected String username;
protected Set<String> roles;
public String getSelf()
{
return self;
}
public String getSelf() {
return self;
}
public void setSelf(String self)
{
this.self = self;
}
public void setSelf(String self) {
this.self = self;
}
public String getUsername()
{
return username;
}
public String getUsername() {
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public void setUsername(String username) {
this.username = username;
}
public Set<String> getRoles()
{
return roles;
}
public Set<String> getRoles() {
return roles;
}
public void setRoles(Set<String> roles)
{
this.roles = roles;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
public RoleMappingRepresentation role(String role)
{
if (this.roles == null) this.roles = new HashSet<String>();
this.roles.add(role);
return this;
}
public RoleMappingRepresentation role(String role) {
if (this.roles == null) this.roles = new HashSet<String>();
this.roles.add(role);
return this;
}
}

View file

@ -4,52 +4,42 @@ import java.util.HashSet;
import java.util.Set;
/**
*
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ScopeMappingRepresentation
{
protected String self; // link
protected String username;
protected Set<String> roles;
public class ScopeMappingRepresentation {
protected String self; // link
protected String username;
protected Set<String> roles;
public String getSelf()
{
return self;
}
public String getSelf() {
return self;
}
public void setSelf(String self)
{
this.self = self;
}
public void setSelf(String self) {
this.self = self;
}
public String getUsername()
{
return username;
}
public String getUsername() {
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public void setUsername(String username) {
this.username = username;
}
public Set<String> getRoles()
{
return roles;
}
public Set<String> getRoles() {
return roles;
}
public void setRoles(Set<String> roles)
{
this.roles = roles;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
public ScopeMappingRepresentation role(String role)
{
if (this.roles == null) this.roles = new HashSet<String>();
this.roles.add(role);
return this;
}
public ScopeMappingRepresentation role(String role) {
if (this.roles == null) this.roles = new HashSet<String>();
this.roles.add(role);
return this;
}
}

View file

@ -6,119 +6,99 @@ import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserRepresentation
{
public static class Credential
{
protected String type;
protected String value;
protected boolean hashed;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserRepresentation {
public static class Credential {
protected String type;
protected String value;
protected boolean hashed;
public String getType()
{
return type;
}
public String getType() {
return type;
}
public void setType(String type)
{
this.type = type;
}
public void setType(String type) {
this.type = type;
}
public String getValue()
{
return value;
}
public String getValue() {
return value;
}
public void setValue(String value)
{
this.value = value;
}
public void setValue(String value) {
this.value = value;
}
public boolean isHashed()
{
return hashed;
}
public boolean isHashed() {
return hashed;
}
public void setHashed(boolean hashed)
{
this.hashed = hashed;
}
}
public void setHashed(boolean hashed) {
this.hashed = hashed;
}
}
protected String self; // link
protected String username;
protected boolean enabled;
protected Map<String, String> attributes;
protected List<Credential> credentials;
protected String self; // link
protected String username;
protected boolean enabled;
protected Map<String, String> attributes;
protected List<Credential> credentials;
public String getSelf()
{
return self;
}
public String getSelf() {
return self;
}
public void setSelf(String self)
{
this.self = self;
}
public void setSelf(String self) {
this.self = self;
}
public String getUsername()
{
return username;
}
public String getUsername() {
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public void setUsername(String username) {
this.username = username;
}
public Map<String, String> getAttributes()
{
return attributes;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes)
{
this.attributes = attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
public List<Credential> getCredentials()
{
return credentials;
}
public List<Credential> getCredentials() {
return credentials;
}
public void setCredentials(List<Credential> credentials)
{
this.credentials = credentials;
}
public void setCredentials(List<Credential> credentials) {
this.credentials = credentials;
}
public UserRepresentation attribute(String name, String value)
{
if (this.attributes == null) attributes = new HashMap<String, String>();
attributes.put(name, value);
return this;
}
public UserRepresentation attribute(String name, String value) {
if (this.attributes == null) attributes = new HashMap<String, String>();
attributes.put(name, value);
return this;
}
public UserRepresentation credential(String type, String value, boolean hashed)
{
if (this.credentials == null) credentials = new ArrayList<Credential>();
Credential cred = new Credential();
cred.setType(type);
cred.setValue(value);
cred.setHashed(hashed);
credentials.add( cred);
return this;
}
public UserRepresentation credential(String type, String value, boolean hashed) {
if (this.credentials == null) credentials = new ArrayList<Credential>();
Credential cred = new Credential();
cred.setType(type);
cred.setValue(value);
cred.setHashed(hashed);
credentials.add(cred);
return this;
}
public boolean isEnabled()
{
return enabled;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View file

@ -1,8 +1,8 @@
package org.keycloak.servlet;
import org.jboss.resteasy.plugins.server.servlet.ServletUtil;
import org.keycloak.AbstractOAuthClient;
import org.jboss.resteasy.spi.ResteasyUriInfo;
import org.keycloak.AbstractOAuthClient;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
@ -17,111 +17,100 @@ import java.net.URI;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ServletOAuthClient extends AbstractOAuthClient
{
/**
* Start the process of obtaining an access token by redirecting the browser
* to the authentication server
*
*
*
* @param relativePath path relative to context root you want auth server to redirect back to
* @param request
* @param response
* @throws IOException
*/
public void redirectRelative(String relativePath, HttpServletRequest request, HttpServletResponse response) throws IOException
{
ResteasyUriInfo uriInfo = ServletUtil.extractUriInfo(request, null);
String redirect = uriInfo.getBaseUriBuilder().path(relativePath).toTemplate();
redirect(redirect, request, response);
}
public class ServletOAuthClient extends AbstractOAuthClient {
/**
* Start the process of obtaining an access token by redirecting the browser
* to the authentication server
*
* @param relativePath path relative to context root you want auth server to redirect back to
* @param request
* @param response
* @throws IOException
*/
public void redirectRelative(String relativePath, HttpServletRequest request, HttpServletResponse response) throws IOException {
ResteasyUriInfo uriInfo = ServletUtil.extractUriInfo(request, null);
String redirect = uriInfo.getBaseUriBuilder().path(relativePath).toTemplate();
redirect(redirect, request, response);
}
/**
* Start the process of obtaining an access token by redirecting the browser
* to the authentication server
*
* @param redirectUri full URI you want auth server to redirect back to
* @param request
* @param response
* @throws IOException
*/
public void redirect(String redirectUri, HttpServletRequest request, HttpServletResponse response) throws IOException
{
String state = getStateCode();
/**
* Start the process of obtaining an access token by redirecting the browser
* to the authentication server
*
* @param redirectUri full URI you want auth server to redirect back to
* @param request
* @param response
* @throws IOException
*/
public void redirect(String redirectUri, HttpServletRequest request, HttpServletResponse response) throws IOException {
String state = getStateCode();
URI url = UriBuilder.fromUri(authUrl)
.queryParam("client_id", clientId)
.queryParam("redirect_uri", redirectUri)
.queryParam("state", state)
.build();
String cookiePath = request.getContextPath();
if (cookiePath.equals("")) cookiePath = "/";
URI url = UriBuilder.fromUri(authUrl)
.queryParam("client_id", clientId)
.queryParam("redirect_uri", redirectUri)
.queryParam("state", state)
.build();
String cookiePath = request.getContextPath();
if (cookiePath.equals("")) cookiePath = "/";
Cookie cookie = new Cookie(stateCookieName, state);
cookie.setSecure(true);
cookie.setPath(cookiePath);
response.addCookie(cookie);
response.sendRedirect(url.toString());
}
Cookie cookie = new Cookie(stateCookieName, state);
cookie.setSecure(true);
cookie.setPath(cookiePath);
response.addCookie(cookie);
response.sendRedirect(url.toString());
}
protected String getCookieValue(String name, HttpServletRequest request)
{
if (request.getCookies() == null) return null;
protected String getCookieValue(String name, HttpServletRequest request) {
if (request.getCookies() == null) return null;
for (Cookie cookie : request.getCookies())
{
if (cookie.getName().equals(name)) return cookie.getValue();
}
return null;
}
for (Cookie cookie : request.getCookies()) {
if (cookie.getName().equals(name)) return cookie.getValue();
}
return null;
}
protected String getCode(HttpServletRequest request)
{
String query = request.getQueryString();
if (query == null) return null;
String[] params = query.split("&");
for (String param : params)
{
int eq = param.indexOf('=');
if (eq == -1) continue;
String name = param.substring(0, eq);
if (!name.equals("code")) continue;
return param.substring(eq + 1);
}
return null;
}
protected String getCode(HttpServletRequest request) {
String query = request.getQueryString();
if (query == null) return null;
String[] params = query.split("&");
for (String param : params) {
int eq = param.indexOf('=');
if (eq == -1) continue;
String name = param.substring(0, eq);
if (!name.equals("code")) continue;
return param.substring(eq + 1);
}
return null;
}
/**
* Obtain the code parameter from the url after being redirected back from the auth-server. Then
* do an authenticated request back to the auth-server to turn the access code into an access token.
*
* @param request
* @return
* @throws BadRequestException
* @throws InternalServerErrorException
*/
public String getBearerToken(HttpServletRequest request) throws BadRequestException, InternalServerErrorException
{
String error = request.getParameter("error");
if (error != null) throw new BadRequestException(new Exception("OAuth error: " + error));
String redirectUri = request.getRequestURL().append("?").append(request.getQueryString()).toString();
String stateCookie = getCookieValue(stateCookieName, request);
if (stateCookie == null) throw new BadRequestException(new Exception("state cookie not set"));
// we can call get parameter as this should be a redirect
String state = request.getParameter("state");
String code = request.getParameter("code");
/**
* Obtain the code parameter from the url after being redirected back from the auth-server. Then
* do an authenticated request back to the auth-server to turn the access code into an access token.
*
* @param request
* @return
* @throws BadRequestException
* @throws InternalServerErrorException
*/
public String getBearerToken(HttpServletRequest request) throws BadRequestException, InternalServerErrorException {
String error = request.getParameter("error");
if (error != null) throw new BadRequestException(new Exception("OAuth error: " + error));
String redirectUri = request.getRequestURL().append("?").append(request.getQueryString()).toString();
String stateCookie = getCookieValue(stateCookieName, request);
if (stateCookie == null) throw new BadRequestException(new Exception("state cookie not set"));
// we can call get parameter as this should be a redirect
String state = request.getParameter("state");
String code = request.getParameter("code");
if (state == null) throw new BadRequestException(new Exception("state parameter was null"));
if (!state.equals(stateCookie))
{
throw new BadRequestException(new Exception("state parameter invalid"));
}
if (code == null) throw new BadRequestException(new Exception("code parameter was null"));
return resolveBearerToken(redirectUri, code);
}
if (state == null) throw new BadRequestException(new Exception("state parameter was null"));
if (!state.equals(stateCookie)) {
throw new BadRequestException(new Exception("state parameter invalid"));
}
if (code == null) throw new BadRequestException(new Exception("code parameter was null"));
return resolveBearerToken(redirectUri, code);
}
}

View file

@ -2,9 +2,6 @@
<deployment>
<!-- This allows you to define additional dependencies, it is the same as using the Dependencies: manifest attribute -->
<dependencies>
<!--
<module name="org.jboss.resteasy.resteasy-jaxrs" services="import"/>
<module name="org.jboss.resteasy.resteasy-jackson-provider" services="import"/> -->
<module name="org.jboss.resteasy.jose-jwt"/>
<module name="org.jboss.resteasy.resteasy-crypto"/>
<module name="org.bouncycastle"/>

View file

@ -4,11 +4,10 @@ package org.keycloak.adapters.as7;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public interface Actions
{
public static final String J_OAUTH_ADMIN_FORCED_LOGOUT = "j_oauth_admin_forced_logout";
public static final String J_OAUTH_LOGOUT = "j_oauth_logout";
public static final String J_OAUTH_RESOLVE_ACCESS_CODE = "j_oauth_resolve_access_code";
public static final String J_OAUTH_REMOTE_LOGOUT = "j_oauth_remote_logout";
public static final String J_OAUTH_TOKEN_GRANT = "j_oauth_token_grant";
public interface Actions {
public static final String J_OAUTH_ADMIN_FORCED_LOGOUT = "j_oauth_admin_forced_logout";
public static final String J_OAUTH_LOGOUT = "j_oauth_logout";
public static final String J_OAUTH_RESOLVE_ACCESS_CODE = "j_oauth_resolve_access_code";
public static final String J_OAUTH_REMOTE_LOGOUT = "j_oauth_remote_logout";
public static final String J_OAUTH_TOKEN_GRANT = "j_oauth_token_grant";
}

View file

@ -10,10 +10,10 @@ import org.apache.catalina.connector.Response;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.deploy.LoginConfig;
import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.ResourceMetadata;
import org.keycloak.adapters.as7.config.ManagedResourceConfig;
import org.keycloak.adapters.as7.config.ManagedResourceConfigLoader;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import javax.security.auth.login.LoginException;
import javax.servlet.ServletException;
@ -27,61 +27,49 @@ import java.io.IOException;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class BearerTokenAuthenticatorValve extends AuthenticatorBase implements LifecycleListener
{
private static final Logger log = Logger.getLogger(BearerTokenAuthenticatorValve.class);
protected ManagedResourceConfig remoteSkeletonKeyConfig;
protected ResourceMetadata resourceMetadata;
public class BearerTokenAuthenticatorValve extends AuthenticatorBase implements LifecycleListener {
private static final Logger log = Logger.getLogger(BearerTokenAuthenticatorValve.class);
protected ManagedResourceConfig remoteSkeletonKeyConfig;
protected ResourceMetadata resourceMetadata;
@Override
public void start() throws LifecycleException
{
super.start();
StandardContext standardContext = (StandardContext)context;
standardContext.addLifecycleListener(this);
}
@Override
public void start() throws LifecycleException {
super.start();
StandardContext standardContext = (StandardContext) context;
standardContext.addLifecycleListener(this);
}
@Override
public void lifecycleEvent(LifecycleEvent event)
{
if (event.getType() == Lifecycle.AFTER_START_EVENT) init();
}
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (event.getType() == Lifecycle.AFTER_START_EVENT) init();
}
protected void init()
{
ManagedResourceConfigLoader managedResourceConfigLoader = new ManagedResourceConfigLoader(context);
resourceMetadata = managedResourceConfigLoader.getResourceMetadata();
remoteSkeletonKeyConfig = managedResourceConfigLoader.getRemoteSkeletonKeyConfig();
}
protected void init() {
ManagedResourceConfigLoader managedResourceConfigLoader = new ManagedResourceConfigLoader(context);
resourceMetadata = managedResourceConfigLoader.getResourceMetadata();
remoteSkeletonKeyConfig = managedResourceConfigLoader.getRemoteSkeletonKeyConfig();
managedResourceConfigLoader.init(false);
}
@Override
public void invoke(Request request, Response response) throws IOException, ServletException
{
try
{
super.invoke(request, response);
}
finally
{
ResteasyProviderFactory.clearContextData(); // to clear push of SkeletonKeySession
}
}
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
try {
super.invoke(request, response);
} finally {
ResteasyProviderFactory.clearContextData(); // to clear push of SkeletonKeySession
}
}
@Override
protected boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException
{
try
{
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, !remoteSkeletonKeyConfig.isCancelPropagation(), true);
if (bearer.login(request, response))
{
return true;
}
return false;
}
catch (LoginException e)
{
}
return false;
}
@Override
protected boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
try {
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, !remoteSkeletonKeyConfig.isCancelPropagation(), true);
if (bearer.login(request, response)) {
return true;
}
return false;
} catch (LoginException e) {
}
return false;
}
}

View file

@ -2,13 +2,13 @@ package org.keycloak.adapters.as7;
import org.apache.catalina.connector.Request;
import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.RSATokenVerifier;
import org.keycloak.ResourceMetadata;
import org.keycloak.SkeletonKeyPrincipal;
import org.keycloak.SkeletonKeySession;
import org.keycloak.VerificationException;
import org.keycloak.representations.SkeletonKeyToken;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import javax.security.auth.login.LoginException;
import javax.servlet.http.HttpServletResponse;
@ -21,143 +21,116 @@ import java.util.Set;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class CatalinaBearerTokenAuthenticator
{
protected ResourceMetadata resourceMetadata;
protected boolean challenge;
protected Logger log = Logger.getLogger(CatalinaBearerTokenAuthenticator.class);
protected String tokenString;
protected SkeletonKeyToken token;
private Principal principal;
protected boolean propagateToken;
public class CatalinaBearerTokenAuthenticator {
protected ResourceMetadata resourceMetadata;
protected boolean challenge;
protected Logger log = Logger.getLogger(CatalinaBearerTokenAuthenticator.class);
protected String tokenString;
protected SkeletonKeyToken token;
private Principal principal;
protected boolean propagateToken;
public CatalinaBearerTokenAuthenticator(ResourceMetadata resourceMetadata, boolean propagateToken, boolean challenge)
{
this.resourceMetadata = resourceMetadata;
this.challenge = challenge;
this.propagateToken = propagateToken;
}
public CatalinaBearerTokenAuthenticator(ResourceMetadata resourceMetadata, boolean propagateToken, boolean challenge) {
this.resourceMetadata = resourceMetadata;
this.challenge = challenge;
this.propagateToken = propagateToken;
}
public ResourceMetadata getResourceMetadata()
{
return resourceMetadata;
}
public ResourceMetadata getResourceMetadata() {
return resourceMetadata;
}
public String getTokenString()
{
return tokenString;
}
public String getTokenString() {
return tokenString;
}
public SkeletonKeyToken getToken()
{
return token;
}
public SkeletonKeyToken getToken() {
return token;
}
public Principal getPrincipal()
{
return principal;
}
public Principal getPrincipal() {
return principal;
}
public boolean login(Request request, HttpServletResponse response) throws LoginException, IOException
{
String authHeader = request.getHeader("Authorization");
if (authHeader == null)
{
if (challenge)
{
challengeResponse(response, null, null);
return false;
}
else
{
return false;
}
}
public boolean login(Request request, HttpServletResponse response) throws LoginException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader == null) {
if (challenge) {
challengeResponse(response, null, null);
return false;
} else {
return false;
}
}
String[] split = authHeader.trim().split("\\s+");
if (split == null || split.length != 2) challengeResponse(response, null, null);
if (!split[0].equalsIgnoreCase("Bearer")) challengeResponse(response, null, null);
String[] split = authHeader.trim().split("\\s+");
if (split == null || split.length != 2) challengeResponse(response, null, null);
if (!split[0].equalsIgnoreCase("Bearer")) challengeResponse(response, null, null);
tokenString = split[1];
tokenString = split[1];
try
{
token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata);
}
catch (VerificationException e)
{
log.error("Failed to verify token", e);
challengeResponse(response, "invalid_token", e.getMessage());
}
boolean verifyCaller = false;
Set<String> roles = null;
if (resourceMetadata.getResourceName() != null)
{
SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName());
if (access != null) roles = access.getRoles();
verifyCaller = token.isVerifyCaller(resourceMetadata.getResourceName());
}
else
{
verifyCaller = token.isVerifyCaller();
SkeletonKeyToken.Access access = token.getRealmAccess();
if (access != null) roles = access.getRoles();
}
String surrogate = null;
if (verifyCaller)
{
if (token.getTrustedCertificates() == null || token.getTrustedCertificates().size() == 0)
{
response.sendError(400);
throw new LoginException("No trusted certificates in token");
}
// for now, we just make sure JBoss Web did two-way SSL
// assume JBoss Web verifies the client cert
X509Certificate[] chain = request.getCertificateChain();
if (chain == null || chain.length == 0)
{
response.sendError(400);
throw new LoginException("No certificates provided by jboss web to verify the caller");
}
surrogate = chain[0].getSubjectX500Principal().getName();
}
SkeletonKeyPrincipal skeletonKeyPrincipal = new SkeletonKeyPrincipal(token.getPrincipal(), surrogate);
principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), skeletonKeyPrincipal, roles);
request.setUserPrincipal(principal);
request.setAuthType("OAUTH_BEARER");
if (propagateToken)
{
SkeletonKeySession skSession = new SkeletonKeySession(tokenString, resourceMetadata);
request.setAttribute(SkeletonKeySession.class.getName(), skSession);
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
}
try {
token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata);
} catch (VerificationException e) {
log.error("Failed to verify token", e);
challengeResponse(response, "invalid_token", e.getMessage());
}
boolean verifyCaller = false;
Set<String> roles = null;
if (resourceMetadata.getResourceName() != null) {
SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName());
if (access != null) roles = access.getRoles();
verifyCaller = token.isVerifyCaller(resourceMetadata.getResourceName());
} else {
verifyCaller = token.isVerifyCaller();
SkeletonKeyToken.Access access = token.getRealmAccess();
if (access != null) roles = access.getRoles();
}
String surrogate = null;
if (verifyCaller) {
if (token.getTrustedCertificates() == null || token.getTrustedCertificates().size() == 0) {
response.sendError(400);
throw new LoginException("No trusted certificates in token");
}
// for now, we just make sure JBoss Web did two-way SSL
// assume JBoss Web verifies the client cert
X509Certificate[] chain = request.getCertificateChain();
if (chain == null || chain.length == 0) {
response.sendError(400);
throw new LoginException("No certificates provided by jboss web to verify the caller");
}
surrogate = chain[0].getSubjectX500Principal().getName();
}
SkeletonKeyPrincipal skeletonKeyPrincipal = new SkeletonKeyPrincipal(token.getPrincipal(), surrogate);
principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), skeletonKeyPrincipal, roles);
request.setUserPrincipal(principal);
request.setAuthType("OAUTH_BEARER");
if (propagateToken) {
SkeletonKeySession skSession = new SkeletonKeySession(tokenString, resourceMetadata);
request.setAttribute(SkeletonKeySession.class.getName(), skSession);
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
}
return true;
}
return true;
}
protected void challengeResponse(HttpServletResponse response, String error, String description) throws LoginException
{
StringBuilder header = new StringBuilder("Bearer realm=\"");
header.append(resourceMetadata.getRealm()).append("\"");
if (error != null)
{
header.append(", error=\"").append(error).append("\"");
}
if (description != null)
{
header.append(", error_description=\"").append(description).append("\"");
}
response.setHeader("WWW-Authenticate", header.toString());
try
{
response.sendError(401);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
throw new LoginException("Challenged");
}
protected void challengeResponse(HttpServletResponse response, String error, String description) throws LoginException {
StringBuilder header = new StringBuilder("Bearer realm=\"");
header.append(resourceMetadata.getRealm()).append("\"");
if (error != null) {
header.append(", error=\"").append(error).append("\"");
}
if (description != null) {
header.append(", error_description=\"").append(description).append("\"");
}
response.setHeader("WWW-Authenticate", header.toString());
try {
response.sendError(401);
} catch (IOException e) {
throw new RuntimeException(e);
}
throw new LoginException("Challenged");
}
}

View file

@ -24,115 +24,105 @@ import java.util.Set;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class CatalinaSecurityContextHelper
{
public GenericPrincipal createPrincipal(Realm realm, Principal identity, Collection<String> roleSet)
{
Subject subject = new Subject();
String credentials = "";
Set<Principal> principals = subject.getPrincipals();
principals.add(identity);
Group[] roleSets = getRoleSets(roleSet);
for(int g = 0; g < roleSets.length; g ++)
{
Group group = roleSets[g];
String name = group.getName();
Group subjectGroup = createGroup(name, principals);
if( subjectGroup instanceof NestableGroup)
{
/* A NestableGroup only allows Groups to be added to it so we
need to add a SimpleGroup to subjectRoles to contain the roles
*/
SimpleGroup tmp = new SimpleGroup("Roles");
subjectGroup.addMember(tmp);
subjectGroup = tmp;
}
// Copy the group members to the Subject group
Enumeration<? extends Principal> members = group.members();
while( members.hasMoreElements() )
{
Principal role = (Principal) members.nextElement();
subjectGroup.addMember(role);
}
}
// add the CallerPrincipal group if none has been added in getRoleSets
Group callerGroup = new SimpleGroup(SecurityConstants.CALLER_PRINCIPAL_GROUP);
callerGroup.addMember(identity);
principals.add(callerGroup);
SecurityContext sc = SecurityContextAssociation.getSecurityContext();
Principal userPrincipal = getPrincipal(subject);
sc.getUtil().createSubjectInfo(userPrincipal, credentials, subject);
List<String> rolesAsStringList = new ArrayList<String>();
rolesAsStringList.addAll(roleSet);
return new JBossGenericPrincipal(realm, userPrincipal.getName(), null, rolesAsStringList,
userPrincipal, null, credentials, null, subject);
}
/**
* Get the Principal given the authenticated Subject. Currently the first principal that is not of type {@code Group} is
* considered or the single principal inside the CallerPrincipal group.
*
* @param subject
* @return the authenticated principal
*/
protected Principal getPrincipal(Subject subject) {
Principal principal = null;
Principal callerPrincipal = null;
if (subject != null) {
Set<Principal> principals = subject.getPrincipals();
if (principals != null && !principals.isEmpty()) {
for (Principal p : principals) {
if (!(p instanceof Group) && principal == null) {
principal = p;
}
if (p instanceof Group) {
Group g = Group.class.cast(p);
if (g.getName().equals(SecurityConstants.CALLER_PRINCIPAL_GROUP) && callerPrincipal == null) {
Enumeration<? extends Principal> e = g.members();
if (e.hasMoreElements())
callerPrincipal = e.nextElement();
}
}
public class CatalinaSecurityContextHelper {
public GenericPrincipal createPrincipal(Realm realm, Principal identity, Collection<String> roleSet) {
Subject subject = new Subject();
String credentials = "";
Set<Principal> principals = subject.getPrincipals();
principals.add(identity);
Group[] roleSets = getRoleSets(roleSet);
for (int g = 0; g < roleSets.length; g++) {
Group group = roleSets[g];
String name = group.getName();
Group subjectGroup = createGroup(name, principals);
if (subjectGroup instanceof NestableGroup) {
/* A NestableGroup only allows Groups to be added to it so we
need to add a SimpleGroup to subjectRoles to contain the roles
*/
SimpleGroup tmp = new SimpleGroup("Roles");
subjectGroup.addMember(tmp);
subjectGroup = tmp;
}
}
}
return callerPrincipal == null ? principal : callerPrincipal;
}
// Copy the group members to the Subject group
Enumeration<? extends Principal> members = group.members();
while (members.hasMoreElements()) {
Principal role = (Principal) members.nextElement();
subjectGroup.addMember(role);
}
}
// add the CallerPrincipal group if none has been added in getRoleSets
Group callerGroup = new SimpleGroup(SecurityConstants.CALLER_PRINCIPAL_GROUP);
callerGroup.addMember(identity);
principals.add(callerGroup);
SecurityContext sc = SecurityContextAssociation.getSecurityContext();
Principal userPrincipal = getPrincipal(subject);
sc.getUtil().createSubjectInfo(userPrincipal, credentials, subject);
List<String> rolesAsStringList = new ArrayList<String>();
rolesAsStringList.addAll(roleSet);
return new JBossGenericPrincipal(realm, userPrincipal.getName(), null, rolesAsStringList,
userPrincipal, null, credentials, null, subject);
protected Group createGroup(String name, Set<Principal> principals)
{
Group roles = null;
Iterator<Principal> iter = principals.iterator();
while( iter.hasNext() )
{
Object next = iter.next();
if( (next instanceof Group) == false )
continue;
Group grp = (Group) next;
if( grp.getName().equals(name) )
{
roles = grp;
break;
}
}
// If we did not find a group create one
if( roles == null )
{
roles = new SimpleGroup(name);
principals.add(roles);
}
return roles;
}
}
protected Group[] getRoleSets(Collection<String> roleSet)
{
SimpleGroup roles = new SimpleGroup("Roles");
Group[] roleSets = {roles};
for (String role : roleSet)
{
roles.addMember(new SimplePrincipal(role));
}
return roleSets;
}
/**
* Get the Principal given the authenticated Subject. Currently the first principal that is not of type {@code Group} is
* considered or the single principal inside the CallerPrincipal group.
*
* @param subject
* @return the authenticated principal
*/
protected Principal getPrincipal(Subject subject) {
Principal principal = null;
Principal callerPrincipal = null;
if (subject != null) {
Set<Principal> principals = subject.getPrincipals();
if (principals != null && !principals.isEmpty()) {
for (Principal p : principals) {
if (!(p instanceof Group) && principal == null) {
principal = p;
}
if (p instanceof Group) {
Group g = Group.class.cast(p);
if (g.getName().equals(SecurityConstants.CALLER_PRINCIPAL_GROUP) && callerPrincipal == null) {
Enumeration<? extends Principal> e = g.members();
if (e.hasMoreElements())
callerPrincipal = e.nextElement();
}
}
}
}
}
return callerPrincipal == null ? principal : callerPrincipal;
}
protected Group createGroup(String name, Set<Principal> principals) {
Group roles = null;
Iterator<Principal> iter = principals.iterator();
while (iter.hasNext()) {
Object next = iter.next();
if ((next instanceof Group) == false)
continue;
Group grp = (Group) next;
if (grp.getName().equals(name)) {
roles = grp;
break;
}
}
// If we did not find a group create one
if (roles == null) {
roles = new SimpleGroup(name);
principals.add(roles);
}
return roles;
}
protected Group[] getRoleSets(Collection<String> roleSet) {
SimpleGroup roles = new SimpleGroup("Roles");
Group[] roleSets = {roles};
for (String role : roleSet) {
roles.addMember(new SimplePrincipal(role));
}
return roleSets;
}
}

View file

@ -16,6 +16,7 @@ import org.jboss.logging.Logger;
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.RealmConfiguration;
import org.keycloak.ResourceMetadata;
import org.keycloak.SkeletonKeyPrincipal;
@ -23,7 +24,6 @@ import org.keycloak.SkeletonKeySession;
import org.keycloak.adapters.as7.config.ManagedResourceConfig;
import org.keycloak.adapters.as7.config.ManagedResourceConfigLoader;
import org.keycloak.representations.SkeletonKeyToken;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import javax.security.auth.login.LoginException;
import javax.servlet.ServletException;
@ -42,262 +42,192 @@ import java.util.Set;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class OAuthManagedResourceValve extends FormAuthenticator implements LifecycleListener
{
protected RealmConfiguration realmConfiguration;
private static final Logger log = Logger.getLogger(OAuthManagedResourceValve.class);
protected UserSessionManagement userSessionManagement = new UserSessionManagement();
protected ManagedResourceConfig remoteSkeletonKeyConfig;
protected ResourceMetadata resourceMetadata;
public class OAuthManagedResourceValve extends FormAuthenticator implements LifecycleListener {
protected RealmConfiguration realmConfiguration;
private static final Logger log = Logger.getLogger(OAuthManagedResourceValve.class);
protected UserSessionManagement userSessionManagement = new UserSessionManagement();
protected ManagedResourceConfig remoteSkeletonKeyConfig;
protected ResourceMetadata resourceMetadata;
@Override
public void start() throws LifecycleException
{
super.start();
StandardContext standardContext = (StandardContext) context;
standardContext.addLifecycleListener(this);
}
@Override
public void start() throws LifecycleException {
super.start();
StandardContext standardContext = (StandardContext) context;
standardContext.addLifecycleListener(this);
}
@Override
public void lifecycleEvent(LifecycleEvent event)
{
if (event.getType() == Lifecycle.AFTER_START_EVENT) init();
}
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (event.getType() == Lifecycle.AFTER_START_EVENT) init();
}
protected void init()
{
ManagedResourceConfigLoader managedResourceConfigLoader = new ManagedResourceConfigLoader(context);
resourceMetadata = managedResourceConfigLoader.getResourceMetadata();
remoteSkeletonKeyConfig = managedResourceConfigLoader.getRemoteSkeletonKeyConfig();
String client_id = remoteSkeletonKeyConfig.getClientId();
if (client_id == null)
{
throw new IllegalArgumentException("Must set client-id to use with auth server");
}
realmConfiguration = new RealmConfiguration();
String authUrl = remoteSkeletonKeyConfig.getAuthUrl();
if (authUrl == null)
{
throw new RuntimeException("You must specify auth-url");
}
String tokenUrl = remoteSkeletonKeyConfig.getCodeUrl();
if (tokenUrl == null)
{
throw new RuntimeException("You mut specify code-url");
}
realmConfiguration.setMetadata(resourceMetadata);
realmConfiguration.setClientId(client_id);
protected void init() {
ManagedResourceConfigLoader managedResourceConfigLoader = new ManagedResourceConfigLoader(context);
managedResourceConfigLoader.init(true);
resourceMetadata = managedResourceConfigLoader.getResourceMetadata();
remoteSkeletonKeyConfig = managedResourceConfigLoader.getRemoteSkeletonKeyConfig();
String client_id = remoteSkeletonKeyConfig.getClientId();
if (client_id == null) {
throw new IllegalArgumentException("Must set client-id to use with auth server");
}
realmConfiguration = new RealmConfiguration();
String authUrl = remoteSkeletonKeyConfig.getAuthUrl();
if (authUrl == null) {
throw new RuntimeException("You must specify auth-url");
}
String tokenUrl = remoteSkeletonKeyConfig.getCodeUrl();
if (tokenUrl == null) {
throw new RuntimeException("You mut specify code-url");
}
realmConfiguration.setMetadata(resourceMetadata);
realmConfiguration.setClientId(client_id);
for (Map.Entry<String, String> entry : managedResourceConfigLoader.getRemoteSkeletonKeyConfig().getClientCredentials().entrySet())
{
realmConfiguration.getCredentials().param(entry.getKey(), entry.getValue());
}
int size = 10;
if (managedResourceConfigLoader.getRemoteSkeletonKeyConfig().getConnectionPoolSize() > 0)
size = managedResourceConfigLoader.getRemoteSkeletonKeyConfig().getConnectionPoolSize();
ResteasyClientBuilder.HostnameVerificationPolicy policy = ResteasyClientBuilder.HostnameVerificationPolicy.WILDCARD;
if (managedResourceConfigLoader.getRemoteSkeletonKeyConfig().isAllowAnyHostname())
policy = ResteasyClientBuilder.HostnameVerificationPolicy.ANY;
ResteasyProviderFactory providerFactory = new ResteasyProviderFactory();
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(OAuthManagedResourceValve.class.getClassLoader());
try
{
ResteasyProviderFactory.getInstance(); // initialize builtins
RegisterBuiltin.register(providerFactory);
}
finally
{
Thread.currentThread().setContextClassLoader(old);
}
ResteasyClient client = new ResteasyClientBuilder()
.providerFactory(providerFactory)
.connectionPoolSize(size)
.hostnameVerification(policy)
.trustStore(resourceMetadata.getTruststore())
.keyStore(resourceMetadata.getClientKeystore(), resourceMetadata.getClientKeyPassword())
.build();
realmConfiguration.setClient(client);
realmConfiguration.setAuthUrl(UriBuilder.fromUri(authUrl).queryParam("client_id", client_id));
realmConfiguration.setCodeUrl(client.target(tokenUrl));
}
for (Map.Entry<String, String> entry : managedResourceConfigLoader.getRemoteSkeletonKeyConfig().getClientCredentials().entrySet()) {
realmConfiguration.getCredentials().param(entry.getKey(), entry.getValue());
}
@Override
public void invoke(Request request, Response response) throws IOException, ServletException
{
try
{
String requestURI = request.getDecodedRequestURI();
if (requestURI.endsWith("j_oauth_remote_logout"))
{
remoteLogout(request, response);
return;
}
super.invoke(request, response);
}
finally
{
ResteasyProviderFactory.clearContextData(); // to clear push of SkeletonKeySession
}
}
ResteasyClient client = managedResourceConfigLoader.getClient();
@Override
public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException
{
try
{
if (bearer(false, request, response)) return true;
else if (checkLoggedIn(request, response))
{
if (request.getSessionInternal().getNote(Constants.FORM_REQUEST_NOTE) != null)
{
if (restoreRequest(request, request.getSessionInternal()))
{
log.debug("restoreRequest");
return (true);
}
else
{
log.debug("Restore of original request failed");
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return (false);
}
realmConfiguration.setClient(client);
realmConfiguration.setAuthUrl(UriBuilder.fromUri(authUrl).queryParam("client_id", client_id));
realmConfiguration.setCodeUrl(client.target(tokenUrl));
}
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
try {
String requestURI = request.getDecodedRequestURI();
if (requestURI.endsWith("j_oauth_remote_logout")) {
remoteLogout(request, response);
return;
}
else
{
return true;
super.invoke(request, response);
} finally {
ResteasyProviderFactory.clearContextData(); // to clear push of SkeletonKeySession
}
}
@Override
public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
try {
if (bearer(false, request, response)) return true;
else if (checkLoggedIn(request, response)) {
if (request.getSessionInternal().getNote(Constants.FORM_REQUEST_NOTE) != null) {
if (restoreRequest(request, request.getSessionInternal())) {
log.debug("restoreRequest");
return (true);
} else {
log.debug("Restore of original request failed");
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return (false);
}
} else {
return true;
}
}
}
// initiate or continue oauth2 protocol
oauth(request, response);
}
catch (LoginException e)
{
}
return false;
}
// initiate or continue oauth2 protocol
oauth(request, response);
} catch (LoginException e) {
}
return false;
}
protected void remoteLogout(Request request, HttpServletResponse response) throws IOException
{
try
{
log.debug("->> remoteLogout: ");
if (!bearer(true, request, response))
{
log.debug("remoteLogout: bearer auth failed");
protected void remoteLogout(Request request, HttpServletResponse response) throws IOException {
try {
log.debug("->> remoteLogout: ");
if (!bearer(true, request, response)) {
log.debug("remoteLogout: bearer auth failed");
return;
}
GenericPrincipal gp = (GenericPrincipal) request.getPrincipal();
if (!gp.hasRole(remoteSkeletonKeyConfig.getAdminRole())) {
log.debug("remoteLogout: role failure");
response.sendError(403);
return;
}
String user = request.getParameter("user");
if (user != null) {
userSessionManagement.logout(user);
} else {
userSessionManagement.logoutAll();
}
} catch (Exception e) {
log.error("failed to logout", e);
}
response.setStatus(204);
}
protected boolean bearer(boolean challenge, Request request, HttpServletResponse response) throws LoginException, IOException {
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(realmConfiguration.getMetadata(), !remoteSkeletonKeyConfig.isCancelPropagation(), challenge);
if (bearer.login(request, response)) {
return true;
}
return false;
}
protected boolean checkLoggedIn(Request request, HttpServletResponse response) {
if (request.getSessionInternal() == null || request.getSessionInternal().getPrincipal() == null)
return false;
log.debug("remote logged in already");
GenericPrincipal principal = (GenericPrincipal) request.getSessionInternal().getPrincipal();
request.setUserPrincipal(principal);
request.setAuthType("OAUTH");
Session session = request.getSessionInternal();
if (session != null && !remoteSkeletonKeyConfig.isCancelPropagation()) {
SkeletonKeySession skSession = (SkeletonKeySession) session.getNote(SkeletonKeySession.class.getName());
if (skSession != null) {
request.setAttribute(SkeletonKeySession.class.getName(), skSession);
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
}
}
return true;
}
/**
* This method always set the HTTP response, so do not continue after invoking
*/
protected void oauth(Request request, HttpServletResponse response) throws IOException {
ServletOAuthLogin oauth = new ServletOAuthLogin(realmConfiguration, request, response, request.getConnector().getRedirectPort());
String code = oauth.getCode();
if (code == null) {
String error = oauth.getError();
if (error != null) {
response.sendError(400, "OAuth " + error);
return;
} else {
saveRequest(request, request.getSessionInternal(true));
oauth.loginRedirect();
}
return;
}
GenericPrincipal gp = (GenericPrincipal) request.getPrincipal();
if (!gp.hasRole(remoteSkeletonKeyConfig.getAdminRole()))
{
log.debug("remoteLogout: role failure");
response.sendError(403);
return;
}
String user = request.getParameter("user");
if (user != null)
{
userSessionManagement.logout(user);
}
else
{
userSessionManagement.logoutAll();
}
}
catch (Exception e)
{
log.error("failed to logout", e);
}
response.setStatus(204);
}
} else {
if (!oauth.resolveCode(code)) return;
protected boolean bearer(boolean challenge, Request request, HttpServletResponse response) throws LoginException, IOException
{
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(realmConfiguration.getMetadata(), !remoteSkeletonKeyConfig.isCancelPropagation(), challenge);
if (bearer.login(request, response))
{
return true;
}
return false;
}
SkeletonKeyToken token = oauth.getToken();
Set<String> roles = null;
if (resourceMetadata.getResourceName() != null) {
SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName());
if (access != null) roles = access.getRoles();
} else {
SkeletonKeyToken.Access access = token.getRealmAccess();
if (access != null) roles = access.getRoles();
}
SkeletonKeyPrincipal skp = new SkeletonKeyPrincipal(token.getPrincipal(), null);
GenericPrincipal principal = new CatalinaSecurityContextHelper().createPrincipal(context.getRealm(), skp, roles);
Session session = request.getSessionInternal(true);
session.setPrincipal(principal);
session.setAuthType("OAUTH");
if (!remoteSkeletonKeyConfig.isCancelPropagation()) {
SkeletonKeySession skSession = new SkeletonKeySession(oauth.getTokenString(), realmConfiguration.getMetadata());
session.setNote(SkeletonKeySession.class.getName(), skSession);
}
protected boolean checkLoggedIn(Request request, HttpServletResponse response)
{
if (request.getSessionInternal() == null || request.getSessionInternal().getPrincipal() == null)
return false;
log.debug("remote logged in already");
GenericPrincipal principal = (GenericPrincipal) request.getSessionInternal().getPrincipal();
request.setUserPrincipal(principal);
request.setAuthType("OAUTH");
Session session = request.getSessionInternal();
if (session != null && !remoteSkeletonKeyConfig.isCancelPropagation())
{
SkeletonKeySession skSession = (SkeletonKeySession) session.getNote(SkeletonKeySession.class.getName());
if (skSession != null)
{
request.setAttribute(SkeletonKeySession.class.getName(), skSession);
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
}
}
return true;
}
/**
* This method always set the HTTP response, so do not continue after invoking
*/
protected void oauth(Request request, HttpServletResponse response) throws IOException
{
ServletOAuthLogin oauth = new ServletOAuthLogin(realmConfiguration, request, response, request.getConnector().getRedirectPort());
String code = oauth.getCode();
if (code == null)
{
String error = oauth.getError();
if (error != null)
{
response.sendError(400, "OAuth " + error);
return;
}
else
{
saveRequest(request, request.getSessionInternal(true));
oauth.loginRedirect();
}
return;
}
else
{
if (!oauth.resolveCode(code)) return;
SkeletonKeyToken token = oauth.getToken();
Set<String> roles = null;
if (resourceMetadata.getResourceName() != null)
{
SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName());
if (access != null) roles = access.getRoles();
}
else
{
SkeletonKeyToken.Access access = token.getRealmAccess();
if (access != null) roles = access.getRoles();
}
SkeletonKeyPrincipal skp = new SkeletonKeyPrincipal(token.getPrincipal(), null);
GenericPrincipal principal = new CatalinaSecurityContextHelper().createPrincipal(context.getRealm(), skp, roles);
Session session = request.getSessionInternal(true);
session.setPrincipal(principal);
session.setAuthType("OAUTH");
if (!remoteSkeletonKeyConfig.isCancelPropagation())
{
SkeletonKeySession skSession = new SkeletonKeySession(oauth.getTokenString(), realmConfiguration.getMetadata());
session.setNote(SkeletonKeySession.class.getName(), skSession);
}
String username = token.getPrincipal();
log.debug("userSessionManage.login: " + username);
userSessionManagement.login(session, username);
}
}
String username = token.getPrincipal();
log.debug("userSessionManage.login: " + username);
userSessionManagement.login(session, username);
}
}
}

View file

@ -1,12 +1,12 @@
package org.keycloak.adapters.as7;
import org.jboss.logging.Logger;
import org.jboss.resteasy.util.BasicAuthHelper;
import org.keycloak.RSATokenVerifier;
import org.keycloak.RealmConfiguration;
import org.keycloak.VerificationException;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.SkeletonKeyToken;
import org.jboss.resteasy.util.BasicAuthHelper;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
@ -21,300 +21,254 @@ import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
/**
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ServletOAuthLogin
{
private static final Logger log = Logger.getLogger(ServletOAuthLogin.class);
protected HttpServletRequest request;
protected HttpServletResponse response;
protected boolean codePresent;
protected RealmConfiguration realmInfo;
protected int redirectPort;
protected String tokenString;
protected SkeletonKeyToken token;
public class ServletOAuthLogin {
private static final Logger log = Logger.getLogger(ServletOAuthLogin.class);
protected HttpServletRequest request;
protected HttpServletResponse response;
protected boolean codePresent;
protected RealmConfiguration realmInfo;
protected int redirectPort;
protected String tokenString;
protected SkeletonKeyToken token;
public ServletOAuthLogin(RealmConfiguration realmInfo, HttpServletRequest request, HttpServletResponse response, int redirectPort)
{
this.request = request;
this.response = response;
this.realmInfo = realmInfo;
this.redirectPort = redirectPort;
}
public ServletOAuthLogin(RealmConfiguration realmInfo, HttpServletRequest request, HttpServletResponse response, int redirectPort) {
this.request = request;
this.response = response;
this.realmInfo = realmInfo;
this.redirectPort = redirectPort;
}
public String getTokenString()
{
return tokenString;
}
public String getTokenString() {
return tokenString;
}
public SkeletonKeyToken getToken()
{
return token;
}
public SkeletonKeyToken getToken() {
return token;
}
public RealmConfiguration getRealmInfo()
{
return realmInfo;
}
public RealmConfiguration getRealmInfo() {
return realmInfo;
}
protected String getDefaultCookiePath()
{
String path = request.getContextPath();
if ("".equals(path) || path == null) path = "/";
return path;
}
protected String getDefaultCookiePath() {
String path = request.getContextPath();
if ("".equals(path) || path == null) path = "/";
return path;
}
protected String getRequestUrl()
{
return request.getRequestURL().toString();
}
protected String getRequestUrl() {
return request.getRequestURL().toString();
}
protected boolean isRequestSecure()
{
return request.isSecure();
}
protected boolean isRequestSecure() {
return request.isSecure();
}
protected void sendError(int code)
{
try
{
response.sendError(code);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
protected void sendError(int code) {
try {
response.sendError(code);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
protected void sendRedirect(String url)
{
try
{
response.sendRedirect(url);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
protected void sendRedirect(String url) {
try {
response.sendRedirect(url);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
protected Cookie getCookie(String cookieName)
{
if (request.getCookies() == null) return null;
for (Cookie cookie : request.getCookies())
{
if (cookie.getName().equals(cookieName))
{
return cookie;
}
}
return null;
}
protected Cookie getCookie(String cookieName) {
if (request.getCookies() == null) return null;
for (Cookie cookie : request.getCookies()) {
if (cookie.getName().equals(cookieName)) {
return cookie;
}
}
return null;
}
protected String getCookieValue(String cookieName)
{
Cookie cookie = getCookie(cookieName);
if (cookie == null) return null;
return cookie.getValue();
}
protected String getCookieValue(String cookieName) {
Cookie cookie = getCookie(cookieName);
if (cookie == null) return null;
return cookie.getValue();
}
protected String getQueryParamValue(String paramName)
{
String query = request.getQueryString();
if (query == null) return null;
String[] params = query.split("&");
for (String param : params)
{
int eq = param.indexOf('=');
if (eq == -1) continue;
String name = param.substring(0, eq);
if (!name.equals(paramName)) continue;
return param.substring(eq + 1);
}
return null;
}
protected String getQueryParamValue(String paramName) {
String query = request.getQueryString();
if (query == null) return null;
String[] params = query.split("&");
for (String param : params) {
int eq = param.indexOf('=');
if (eq == -1) continue;
String name = param.substring(0, eq);
if (!name.equals(paramName)) continue;
return param.substring(eq + 1);
}
return null;
}
public String getError()
{
return getQueryParamValue("error");
}
public String getError() {
return getQueryParamValue("error");
}
public String getCode()
{
return getQueryParamValue("code");
}
public String getCode() {
return getQueryParamValue("code");
}
protected void setCookie(String name, String value, String domain, String path, boolean secure)
{
Cookie cookie = new Cookie(name, value);
if (domain != null) cookie.setDomain(domain);
if (path != null) cookie.setPath(path);
if (secure) cookie.setSecure(true);
response.addCookie(cookie);
}
protected void setCookie(String name, String value, String domain, String path, boolean secure) {
Cookie cookie = new Cookie(name, value);
if (domain != null) cookie.setDomain(domain);
if (path != null) cookie.setPath(path);
if (secure) cookie.setSecure(true);
response.addCookie(cookie);
}
protected String getRedirectUri(String state)
{
String url = getRequestUrl();
if (!isRequestSecure() && realmInfo.isSslRequired())
{
int port = redirectPort;
if (port < 0)
{
// disabled?
return null;
}
UriBuilder secureUrl = UriBuilder.fromUri(url).scheme("https").port(-1);
if (port != 443) secureUrl.port(port);
url = secureUrl.build().toString();
}
return realmInfo.getAuthUrl().clone()
.queryParam("client_id", realmInfo.getClientId())
.queryParam("redirect_uri", url)
.queryParam("state", state)
.queryParam("login", "true")
.build().toString();
}
protected String getRedirectUri(String state) {
String url = getRequestUrl();
if (!isRequestSecure() && realmInfo.isSslRequired()) {
int port = redirectPort;
if (port < 0) {
// disabled?
return null;
}
UriBuilder secureUrl = UriBuilder.fromUri(url).scheme("https").port(-1);
if (port != 443) secureUrl.port(port);
url = secureUrl.build().toString();
}
return realmInfo.getAuthUrl().clone()
.queryParam("client_id", realmInfo.getClientId())
.queryParam("redirect_uri", url)
.queryParam("state", state)
.queryParam("login", "true")
.build().toString();
}
protected static final AtomicLong counter = new AtomicLong();
protected static final AtomicLong counter = new AtomicLong();
protected String getStateCode()
{
return counter.getAndIncrement() + "/" + UUID.randomUUID().toString();
}
protected String getStateCode() {
return counter.getAndIncrement() + "/" + UUID.randomUUID().toString();
}
public void loginRedirect()
{
String state = getStateCode();
String redirect = getRedirectUri(state);
if (redirect == null)
{
sendError(Response.Status.FORBIDDEN.getStatusCode());
return;
}
setCookie(realmInfo.getStateCookieName(), state, null, getDefaultCookiePath(), realmInfo.isSslRequired());
sendRedirect(redirect);
}
public void loginRedirect() {
String state = getStateCode();
String redirect = getRedirectUri(state);
if (redirect == null) {
sendError(Response.Status.FORBIDDEN.getStatusCode());
return;
}
setCookie(realmInfo.getStateCookieName(), state, null, getDefaultCookiePath(), realmInfo.isSslRequired());
sendRedirect(redirect);
}
public boolean checkStateCookie()
{
Cookie stateCookie = getCookie(realmInfo.getStateCookieName());
public boolean checkStateCookie() {
Cookie stateCookie = getCookie(realmInfo.getStateCookieName());
if (stateCookie == null)
{
sendError(400);
log.warn("No state cookie");
return false;
}
// reset the cookie
Cookie reset = new Cookie(stateCookie.getName(), stateCookie.getValue());
reset.setPath(stateCookie.getPath());
reset.setMaxAge(0);
response.addCookie(reset);
if (stateCookie == null) {
sendError(400);
log.warn("No state cookie");
return false;
}
// reset the cookie
Cookie reset = new Cookie(stateCookie.getName(), stateCookie.getValue());
reset.setPath(stateCookie.getPath());
reset.setMaxAge(0);
response.addCookie(reset);
String stateCookieValue = getCookieValue(realmInfo.getStateCookieName());
// its ok to call request.getParameter() because this should be a redirect
String state = request.getParameter("state");
if (state == null)
{
sendError(400);
log.warn("state parameter was null");
return false;
}
if (!state.equals(stateCookieValue))
{
sendError(400);
log.warn("state parameter invalid");
log.warn("cookie: " + stateCookieValue);
log.warn("queryParam: " + state);
return false;
}
return true;
String stateCookieValue = getCookieValue(realmInfo.getStateCookieName());
// its ok to call request.getParameter() because this should be a redirect
String state = request.getParameter("state");
if (state == null) {
sendError(400);
log.warn("state parameter was null");
return false;
}
if (!state.equals(stateCookieValue)) {
sendError(400);
log.warn("state parameter invalid");
log.warn("cookie: " + stateCookieValue);
log.warn("queryParam: " + state);
return false;
}
return true;
}
}
/**
* Start or continue the oauth login process.
*
* if code query parameter is not present, then browser is redirected to authUrl. The redirect URL will be
* the URL of the current request.
*
* If code query parameter is present, then an access token is obtained by invoking a secure request to the codeUrl.
* If the access token is obtained, the browser is again redirected to the current request URL, but any OAuth
* protocol specific query parameters are removed.
*
* @return true if an access token was obtained
*/
public boolean resolveCode(String code)
{
// abort if not HTTPS
if (realmInfo.isSslRequired() && !isRequestSecure())
{
log.error("SSL is required");
sendError(Response.Status.FORBIDDEN.getStatusCode());
return false;
}
if (!checkStateCookie()) return false;
String client_id = realmInfo.getClientId();
String password = realmInfo.getCredentials().asMap().getFirst("password");
String authHeader = BasicAuthHelper.createHeader(client_id, password);
String redirectUri = stripOauthParametersFromRedirect();
Form form = new Form();
form.param("grant_type", "authorization_code")
.param("code", code)
.param("redirect_uri", redirectUri);
Response res = realmInfo.getCodeUrl().request().header(HttpHeaders.AUTHORIZATION, authHeader).post(Entity.form(form));
AccessTokenResponse tokenResponse;
try
{
if (res.getStatus() != 200)
{
log.error("failed to turn code into token");
/**
* Start or continue the oauth login process.
* <p/>
* if code query parameter is not present, then browser is redirected to authUrl. The redirect URL will be
* the URL of the current request.
* <p/>
* If code query parameter is present, then an access token is obtained by invoking a secure request to the codeUrl.
* If the access token is obtained, the browser is again redirected to the current request URL, but any OAuth
* protocol specific query parameters are removed.
*
* @return true if an access token was obtained
*/
public boolean resolveCode(String code) {
// abort if not HTTPS
if (realmInfo.isSslRequired() && !isRequestSecure()) {
log.error("SSL is required");
sendError(Response.Status.FORBIDDEN.getStatusCode());
return false;
}
log.debug("media type: " + res.getMediaType());
log.debug("Content-Type header: " + res.getHeaderString("Content-Type"));
tokenResponse = res.readEntity(AccessTokenResponse.class);
}
finally
{
res.close();
}
}
tokenString = tokenResponse.getToken();
try
{
token = RSATokenVerifier.verifyToken(tokenString, realmInfo.getMetadata());
log.debug("Verification succeeded!");
}
catch (VerificationException e)
{
log.error("failed verification of token");
sendError(Response.Status.FORBIDDEN.getStatusCode());
return false;
}
// redirect to URL without oauth query parameters
sendRedirect(redirectUri);
return true;
}
if (!checkStateCookie()) return false;
/**
* strip out unwanted query parameters and redirect so bookmarks don't retain oauth protocol bits
*/
protected String stripOauthParametersFromRedirect()
{
StringBuffer buf = request.getRequestURL().append("?").append(request.getQueryString());
UriBuilder builder = UriBuilder.fromUri(buf.toString())
.replaceQueryParam("code", null)
.replaceQueryParam("state", null);
return builder.build().toString();
}
String client_id = realmInfo.getClientId();
String password = realmInfo.getCredentials().asMap().getFirst("password");
String authHeader = BasicAuthHelper.createHeader(client_id, password);
String redirectUri = stripOauthParametersFromRedirect();
Form form = new Form();
form.param("grant_type", "authorization_code")
.param("code", code)
.param("redirect_uri", redirectUri);
Response res = realmInfo.getCodeUrl().request().header(HttpHeaders.AUTHORIZATION, authHeader).post(Entity.form(form));
AccessTokenResponse tokenResponse;
try {
if (res.getStatus() != 200) {
log.error("failed to turn code into token");
sendError(Response.Status.FORBIDDEN.getStatusCode());
return false;
}
log.debug("media type: " + res.getMediaType());
log.debug("Content-Type header: " + res.getHeaderString("Content-Type"));
tokenResponse = res.readEntity(AccessTokenResponse.class);
} finally {
res.close();
}
tokenString = tokenResponse.getToken();
try {
token = RSATokenVerifier.verifyToken(tokenString, realmInfo.getMetadata());
log.debug("Verification succeeded!");
} catch (VerificationException e) {
log.error("failed verification of token");
sendError(Response.Status.FORBIDDEN.getStatusCode());
return false;
}
// redirect to URL without oauth query parameters
sendRedirect(redirectUri);
return true;
}
/**
* strip out unwanted query parameters and redirect so bookmarks don't retain oauth protocol bits
*/
protected String stripOauthParametersFromRedirect() {
StringBuffer buf = request.getRequestURL().append("?").append(request.getQueryString());
UriBuilder builder = UriBuilder.fromUri(buf.toString())
.replaceQueryParam("code", null)
.replaceQueryParam("state", null);
return builder.build().toString();
}
}

View file

@ -18,94 +18,80 @@ import java.util.concurrent.ConcurrentHashMap;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class UserSessionManagement implements SessionListener
{
private static final Logger log = Logger.getLogger(UserSessionManagement.class);
protected ConcurrentHashMap<String, Map<String, Session>> userSessionMap = new ConcurrentHashMap<String, Map<String, Session>>();
public class UserSessionManagement implements SessionListener {
private static final Logger log = Logger.getLogger(UserSessionManagement.class);
protected ConcurrentHashMap<String, Map<String, Session>> userSessionMap = new ConcurrentHashMap<String, Map<String, Session>>();
protected void login(Session session, String username)
{
Map<String, Session> map = userSessionMap.get(username);
if (map == null)
{
final Map<String, Session> value = new HashMap<String, Session>();
map = userSessionMap.putIfAbsent(username, value);
if (map == null)
{
map = value;
}
}
synchronized (map)
{
map.put(session.getId(), session);
}
session.addSessionListener(this);
}
protected void login(Session session, String username) {
Map<String, Session> map = userSessionMap.get(username);
if (map == null) {
final Map<String, Session> value = new HashMap<String, Session>();
map = userSessionMap.putIfAbsent(username, value);
if (map == null) {
map = value;
}
}
synchronized (map) {
map.put(session.getId(), session);
}
session.addSessionListener(this);
}
public void logoutAll()
{
List<String> users = new ArrayList<String>();
users.addAll(userSessionMap.keySet());
for (String user : users) logout(user);
}
public void logoutAll() {
List<String> users = new ArrayList<String>();
users.addAll(userSessionMap.keySet());
for (String user : users) logout(user);
}
public void logoutAllBut(String but)
{
List<String> users = new ArrayList<String>();
users.addAll(userSessionMap.keySet());
for (String user : users)
{
if (!but.equals(user)) logout(user);
}
}
public void logoutAllBut(String but) {
List<String> users = new ArrayList<String>();
users.addAll(userSessionMap.keySet());
for (String user : users) {
if (!but.equals(user)) logout(user);
}
}
public void logout(String user)
{
log.debug("logoutUser: " + user);
Map<String, Session> map = userSessionMap.remove(user);
if (map == null)
{
log.debug("no session for user: " + user);
return;
}
log.debug("found session for user");
synchronized (map)
{
for (Session session : map.values())
{
log.debug("invalidating session for user: " + user);
session.setPrincipal(null);
session.setAuthType(null);
session.getSession().invalidate();
}
}
public void logout(String user) {
log.debug("logoutUser: " + user);
Map<String, Session> map = userSessionMap.remove(user);
if (map == null) {
log.debug("no session for user: " + user);
return;
}
log.debug("found session for user");
synchronized (map) {
for (Session session : map.values()) {
log.debug("invalidating session for user: " + user);
session.setPrincipal(null);
session.setAuthType(null);
session.getSession().invalidate();
}
}
}
}
public void sessionEvent(SessionEvent event)
{
// We only care about session destroyed events
if (!Session.SESSION_DESTROYED_EVENT.equals(event.getType())
&& (!Session.SESSION_PASSIVATED_EVENT.equals(event.getType())))
return;
public void sessionEvent(SessionEvent event) {
// We only care about session destroyed events
if (!Session.SESSION_DESTROYED_EVENT.equals(event.getType())
&& (!Session.SESSION_PASSIVATED_EVENT.equals(event.getType())))
return;
// Look up the single session id associated with this session (if any)
Session session = event.getSession();
GenericPrincipal principal = (GenericPrincipal) session.getPrincipal();
if (principal == null) return;
session.setPrincipal(null);
session.setAuthType(null);
// Look up the single session id associated with this session (if any)
Session session = event.getSession();
GenericPrincipal principal = (GenericPrincipal) session.getPrincipal();
if (principal == null) return;
session.setPrincipal(null);
session.setAuthType(null);
String username = principal.getUserPrincipal().getName();
Map<String, Session> map = userSessionMap.get(username);
if (map == null) return;
synchronized (map)
{
map.remove(session.getId());
if (map.isEmpty()) userSessionMap.remove(username);
}
String username = principal.getUserPrincipal().getName();
Map<String, Session> map = userSessionMap.get(username);
if (map == null) return;
synchronized (map) {
map.remove(session.getId());
if (map.isEmpty()) userSessionMap.remove(username);
}
}
}
}

View file

@ -9,271 +9,229 @@ import java.util.List;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class AuthServerConfig
{
@JsonProperty("realm")
protected String realm;
public class AuthServerConfig {
@JsonProperty("realm")
protected String realm;
@JsonProperty("realm-private-key")
protected String realmPrivateKey;
@JsonProperty("realm-private-key")
protected String realmPrivateKey;
@JsonProperty("realm-public-key")
protected String realmPublicKey;
@JsonProperty("realm-public-key")
protected String realmPublicKey;
@JsonProperty("realm-keystore")
protected String realmKeyStore;
@JsonProperty("realm-keystore")
protected String realmKeyStore;
@JsonProperty("realm-keystore-password")
protected String realmKeystorePassword;
@JsonProperty("realm-keystore-password")
protected String realmKeystorePassword;
@JsonProperty("realm-key-alias")
protected String realmKeyAlias;
@JsonProperty("realm-key-alias")
protected String realmKeyAlias;
@JsonProperty("realm-private-key-password")
protected String realmPrivateKeyPassword;
@JsonProperty("realm-private-key-password")
protected String realmPrivateKeyPassword;
@JsonProperty("access-code-lifetime")
protected int accessCodeLifetime;
@JsonProperty("access-code-lifetime")
protected int accessCodeLifetime;
@JsonProperty("token-lifetime")
protected int tokenLifetime;
@JsonProperty("token-lifetime")
protected int tokenLifetime;
@JsonProperty("admin-role")
protected String adminRole;
@JsonProperty("admin-role")
protected String adminRole;
@JsonProperty("login-role")
protected String loginRole;
@JsonProperty("login-role")
protected String loginRole;
@JsonProperty("oauth-client-role")
protected String clientRole;
@JsonProperty("oauth-client-role")
protected String clientRole;
@JsonProperty("wildcard-role")
protected String wildcardRole;
@JsonProperty("wildcard-role")
protected String wildcardRole;
@JsonProperty("cancel-propagation")
protected boolean cancelPropagation;
@JsonProperty("cancel-propagation")
protected boolean cancelPropagation;
@JsonProperty("sso-disabled")
protected boolean ssoDisabled;
@JsonProperty("sso-disabled")
protected boolean ssoDisabled;
// these properties are optional and used to provide connection metadata when the server wants to make
// remote SSL connections
// these properties are optional and used to provide connection metadata when the server wants to make
// remote SSL connections
protected String truststore;
@JsonProperty("truststore-password")
protected String truststorePassword;
@JsonProperty("client-keystore")
protected String clientKeystore;
@JsonProperty("client-keystore-password")
protected String clientKeystorePassword;
@JsonProperty("client-key-password")
protected String clientKeyPassword;
protected String truststore;
@JsonProperty("truststore-password")
protected String truststorePassword;
@JsonProperty("client-keystore")
protected String clientKeystore;
@JsonProperty("client-keystore-password")
protected String clientKeystorePassword;
@JsonProperty("client-key-password")
protected String clientKeyPassword;
protected List<String> resources = new ArrayList<String>();
protected List<String> resources = new ArrayList<String>();
public String getRealm()
{
return realm;
}
public String getRealm() {
return realm;
}
public void setRealm(String realm)
{
this.realm = realm;
}
public void setRealm(String realm) {
this.realm = realm;
}
public String getRealmPrivateKey()
{
return realmPrivateKey;
}
public String getRealmPrivateKey() {
return realmPrivateKey;
}
public void setRealmPrivateKey(String realmPrivateKey)
{
this.realmPrivateKey = realmPrivateKey;
}
public void setRealmPrivateKey(String realmPrivateKey) {
this.realmPrivateKey = realmPrivateKey;
}
public String getRealmPublicKey()
{
return realmPublicKey;
}
public String getRealmPublicKey() {
return realmPublicKey;
}
public void setRealmPublicKey(String realmPublicKey)
{
this.realmPublicKey = realmPublicKey;
}
public void setRealmPublicKey(String realmPublicKey) {
this.realmPublicKey = realmPublicKey;
}
public int getAccessCodeLifetime()
{
return accessCodeLifetime;
}
public int getAccessCodeLifetime() {
return accessCodeLifetime;
}
public void setAccessCodeLifetime(int accessCodeLifetime)
{
this.accessCodeLifetime = accessCodeLifetime;
}
public void setAccessCodeLifetime(int accessCodeLifetime) {
this.accessCodeLifetime = accessCodeLifetime;
}
public String getTruststore()
{
return truststore;
}
public String getTruststore() {
return truststore;
}
public void setTruststore(String truststore)
{
this.truststore = truststore;
}
public void setTruststore(String truststore) {
this.truststore = truststore;
}
public String getTruststorePassword()
{
return truststorePassword;
}
public String getTruststorePassword() {
return truststorePassword;
}
public void setTruststorePassword(String truststorePassword)
{
this.truststorePassword = truststorePassword;
}
public void setTruststorePassword(String truststorePassword) {
this.truststorePassword = truststorePassword;
}
public String getClientKeystore()
{
return clientKeystore;
}
public String getClientKeystore() {
return clientKeystore;
}
public void setClientKeystore(String clientKeystore)
{
this.clientKeystore = clientKeystore;
}
public void setClientKeystore(String clientKeystore) {
this.clientKeystore = clientKeystore;
}
public String getClientKeystorePassword()
{
return clientKeystorePassword;
}
public String getClientKeystorePassword() {
return clientKeystorePassword;
}
public void setClientKeystorePassword(String clientKeystorePassword)
{
this.clientKeystorePassword = clientKeystorePassword;
}
public void setClientKeystorePassword(String clientKeystorePassword) {
this.clientKeystorePassword = clientKeystorePassword;
}
public String getClientKeyPassword()
{
return clientKeyPassword;
}
public String getClientKeyPassword() {
return clientKeyPassword;
}
public void setClientKeyPassword(String clientKeyPassword)
{
this.clientKeyPassword = clientKeyPassword;
}
public void setClientKeyPassword(String clientKeyPassword) {
this.clientKeyPassword = clientKeyPassword;
}
public boolean isCancelPropagation()
{
return cancelPropagation;
}
public boolean isCancelPropagation() {
return cancelPropagation;
}
public void setCancelPropagation(boolean cancelPropagation)
{
this.cancelPropagation = cancelPropagation;
}
public void setCancelPropagation(boolean cancelPropagation) {
this.cancelPropagation = cancelPropagation;
}
public boolean isSsoDisabled()
{
return ssoDisabled;
}
public boolean isSsoDisabled() {
return ssoDisabled;
}
public void setSsoDisabled(boolean ssoDisabled)
{
this.ssoDisabled = ssoDisabled;
}
public void setSsoDisabled(boolean ssoDisabled) {
this.ssoDisabled = ssoDisabled;
}
public List<String> getResources()
{
return resources;
}
public List<String> getResources() {
return resources;
}
public String getAdminRole()
{
return adminRole;
}
public String getAdminRole() {
return adminRole;
}
public void setAdminRole(String adminRole)
{
this.adminRole = adminRole;
}
public void setAdminRole(String adminRole) {
this.adminRole = adminRole;
}
public String getLoginRole()
{
return loginRole;
}
public String getLoginRole() {
return loginRole;
}
public void setLoginRole(String loginRole)
{
this.loginRole = loginRole;
}
public void setLoginRole(String loginRole) {
this.loginRole = loginRole;
}
public String getClientRole()
{
return clientRole;
}
public String getClientRole() {
return clientRole;
}
public void setClientRole(String clientRole)
{
this.clientRole = clientRole;
}
public void setClientRole(String clientRole) {
this.clientRole = clientRole;
}
public String getWildcardRole()
{
return wildcardRole;
}
public String getWildcardRole() {
return wildcardRole;
}
public void setWildcardRole(String wildcardRole)
{
this.wildcardRole = wildcardRole;
}
public void setWildcardRole(String wildcardRole) {
this.wildcardRole = wildcardRole;
}
public String getRealmKeyStore()
{
return realmKeyStore;
}
public String getRealmKeyStore() {
return realmKeyStore;
}
public void setRealmKeyStore(String realmKeyStore)
{
this.realmKeyStore = realmKeyStore;
}
public void setRealmKeyStore(String realmKeyStore) {
this.realmKeyStore = realmKeyStore;
}
public String getRealmKeystorePassword()
{
return realmKeystorePassword;
}
public String getRealmKeystorePassword() {
return realmKeystorePassword;
}
public void setRealmKeystorePassword(String realmKeystorePassword)
{
this.realmKeystorePassword = realmKeystorePassword;
}
public void setRealmKeystorePassword(String realmKeystorePassword) {
this.realmKeystorePassword = realmKeystorePassword;
}
public String getRealmKeyAlias()
{
return realmKeyAlias;
}
public String getRealmKeyAlias() {
return realmKeyAlias;
}
public void setRealmKeyAlias(String realmKeyAlias)
{
this.realmKeyAlias = realmKeyAlias;
}
public void setRealmKeyAlias(String realmKeyAlias) {
this.realmKeyAlias = realmKeyAlias;
}
public String getRealmPrivateKeyPassword()
{
return realmPrivateKeyPassword;
}
public String getRealmPrivateKeyPassword() {
return realmPrivateKeyPassword;
}
public void setRealmPrivateKeyPassword(String realmPrivateKeyPassword)
{
this.realmPrivateKeyPassword = realmPrivateKeyPassword;
}
public void setRealmPrivateKeyPassword(String realmPrivateKeyPassword) {
this.realmPrivateKeyPassword = realmPrivateKeyPassword;
}
public int getTokenLifetime()
{
return tokenLifetime;
}
public int getTokenLifetime() {
return tokenLifetime;
}
public void setTokenLifetime(int tokenLifetime)
{
this.tokenLifetime = tokenLifetime;
}
public void setTokenLifetime(int tokenLifetime) {
this.tokenLifetime = tokenLifetime;
}
}

View file

@ -10,204 +10,183 @@ import java.util.Map;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@JsonPropertyOrder({"realm", "resource", "realm-public-key", "admin-role", "auth-url", "code-url", "truststore", "truststore-password", "client-id", "client-credentials"})
public class ManagedResourceConfig
{
@JsonProperty("realm")
protected String realm;
@JsonProperty("resource")
protected String resource;
@JsonPropertyOrder({"realm-url", "realm", "resource", "realm-public-key", "admin-role", "auth-url", "code-url", "allow-any-hostname", "disable-trust-manager", "truststore", "truststore-password", "client-id", "client-credentials"})
public class ManagedResourceConfig {
@JsonProperty("realm-url")
protected String realmUrl;
@JsonProperty("realm")
protected String realm;
@JsonProperty("resource")
protected String resource;
@JsonProperty("realm-public-key")
protected String realmKey;
@JsonProperty("admin-role")
protected String adminRole;
@JsonProperty("auth-url")
protected String authUrl;
@JsonProperty("code-url")
protected String codeUrl;
@JsonProperty("realm-public-key")
protected String realmKey;
@JsonProperty("allow-any-hostname")
protected boolean allowAnyHostname;
@JsonProperty("disable-trust-manager")
protected boolean disableTrustManager;
@JsonProperty("truststore")
protected String truststore;
@JsonProperty("truststore-password")
protected String truststorePassword;
@JsonProperty("client-id")
protected String clientId;
@JsonProperty("client-keystore")
protected String clientKeystore;
@JsonProperty("client-keystore-password")
protected String clientKeystorePassword;
@JsonProperty("client-key-password")
protected String clientKeyPassword;
@JsonProperty("client-credentials")
protected Map<String, String> clientCredentials = new HashMap<String, String>();
@JsonProperty("connection-pool-size")
protected int connectionPoolSize;
@JsonProperty("cancel-propagation")
protected boolean cancelPropagation;
@JsonProperty("admin-role")
protected String adminRole;
public String getRealmUrl() {
return realmUrl;
}
@JsonProperty("auth-url")
protected String authUrl;
@JsonProperty("code-url")
protected String codeUrl;
public void setRealmUrl(String realmUrl) {
this.realmUrl = realmUrl;
}
@JsonProperty("allow-any-hostname")
protected boolean allowAnyHostname;
public String getRealm() {
return realm;
}
@JsonProperty("truststore")
protected String truststore;
public void setRealm(String realm) {
this.realm = realm;
}
@JsonProperty("truststore-password")
protected String truststorePassword;
@JsonProperty("client-id")
protected String clientId;
@JsonProperty("client-keystore")
protected String clientKeystore;
@JsonProperty("client-keystore-password")
protected String clientKeystorePassword;
@JsonProperty("client-key-password")
protected String clientKeyPassword;
public String getResource() {
return resource;
}
@JsonProperty("client-credentials")
protected Map<String, String> clientCredentials = new HashMap<String, String>();
public void setResource(String resource) {
this.resource = resource;
}
@JsonProperty("connection-pool-size")
protected int connectionPoolSize;
public String getRealmKey() {
return realmKey;
}
@JsonProperty("cancel-propagation")
protected boolean cancelPropagation;
public void setRealmKey(String realmKey) {
this.realmKey = realmKey;
}
public String getAuthUrl() {
return authUrl;
}
public String getRealm()
{
return realm;
}
public void setAuthUrl(String authUrl) {
this.authUrl = authUrl;
}
public void setRealm(String realm)
{
this.realm = realm;
}
public String getCodeUrl() {
return codeUrl;
}
public String getResource()
{
return resource;
}
public void setCodeUrl(String codeUrl) {
this.codeUrl = codeUrl;
}
public void setResource(String resource)
{
this.resource = resource;
}
public boolean isAllowAnyHostname() {
return allowAnyHostname;
}
public String getRealmKey()
{
return realmKey;
}
public void setAllowAnyHostname(boolean allowAnyHostname) {
this.allowAnyHostname = allowAnyHostname;
}
public void setRealmKey(String realmKey)
{
this.realmKey = realmKey;
}
public boolean isDisableTrustManager() {
return disableTrustManager;
}
public String getAuthUrl()
{
return authUrl;
}
public void setDisableTrustManager(boolean disableTrustManager) {
this.disableTrustManager = disableTrustManager;
}
public void setAuthUrl(String authUrl)
{
this.authUrl = authUrl;
}
public String getTruststore() {
return truststore;
}
public String getCodeUrl()
{
return codeUrl;
}
public void setTruststore(String truststore) {
this.truststore = truststore;
}
public void setCodeUrl(String codeUrl)
{
this.codeUrl = codeUrl;
}
public String getTruststorePassword() {
return truststorePassword;
}
public boolean isAllowAnyHostname()
{
return allowAnyHostname;
}
public void setTruststorePassword(String truststorePassword) {
this.truststorePassword = truststorePassword;
}
public void setAllowAnyHostname(boolean allowAnyHostname)
{
this.allowAnyHostname = allowAnyHostname;
}
public String getClientId() {
return clientId;
}
public String getTruststore()
{
return truststore;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public void setTruststore(String truststore)
{
this.truststore = truststore;
}
public Map<String, String> getClientCredentials() {
return clientCredentials;
}
public String getTruststorePassword()
{
return truststorePassword;
}
public String getClientKeystore() {
return clientKeystore;
}
public void setTruststorePassword(String truststorePassword)
{
this.truststorePassword = truststorePassword;
}
public void setClientKeystore(String clientKeystore) {
this.clientKeystore = clientKeystore;
}
public String getClientId()
{
return clientId;
}
public String getClientKeystorePassword() {
return clientKeystorePassword;
}
public void setClientId(String clientId)
{
this.clientId = clientId;
}
public void setClientKeystorePassword(String clientKeystorePassword) {
this.clientKeystorePassword = clientKeystorePassword;
}
public Map<String, String> getClientCredentials()
{
return clientCredentials;
}
public String getClientKeyPassword() {
return clientKeyPassword;
}
public String getClientKeystore()
{
return clientKeystore;
}
public void setClientKeyPassword(String clientKeyPassword) {
this.clientKeyPassword = clientKeyPassword;
}
public void setClientKeystore(String clientKeystore)
{
this.clientKeystore = clientKeystore;
}
public int getConnectionPoolSize() {
return connectionPoolSize;
}
public String getClientKeystorePassword()
{
return clientKeystorePassword;
}
public void setConnectionPoolSize(int connectionPoolSize) {
this.connectionPoolSize = connectionPoolSize;
}
public void setClientKeystorePassword(String clientKeystorePassword)
{
this.clientKeystorePassword = clientKeystorePassword;
}
public boolean isCancelPropagation() {
return cancelPropagation;
}
public String getClientKeyPassword()
{
return clientKeyPassword;
}
public void setCancelPropagation(boolean cancelPropagation) {
this.cancelPropagation = cancelPropagation;
}
public void setClientKeyPassword(String clientKeyPassword)
{
this.clientKeyPassword = clientKeyPassword;
}
public String getAdminRole() {
return adminRole;
}
public int getConnectionPoolSize()
{
return connectionPoolSize;
}
public void setConnectionPoolSize(int connectionPoolSize)
{
this.connectionPoolSize = connectionPoolSize;
}
public boolean isCancelPropagation()
{
return cancelPropagation;
}
public void setCancelPropagation(boolean cancelPropagation)
{
this.cancelPropagation = cancelPropagation;
}
public String getAdminRole()
{
return adminRole;
}
public void setAdminRole(String adminRole)
{
this.adminRole = adminRole;
}
public void setAdminRole(String adminRole) {
this.adminRole = adminRole;
}
}

View file

@ -4,10 +4,16 @@ import org.apache.catalina.Context;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.jboss.logging.Logger;
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.EnvUtil;
import org.keycloak.PemUtils;
import org.keycloak.ResourceMetadata;
import org.keycloak.representations.idm.PublishedRealmRepresentation;
import javax.ws.rs.client.WebTarget;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@ -16,124 +22,166 @@ import java.io.InputStream;
import java.security.KeyStore;
import java.security.PublicKey;
public class ManagedResourceConfigLoader
{
static final Logger log = Logger.getLogger(ManagedResourceConfigLoader.class);
protected ManagedResourceConfig remoteSkeletonKeyConfig;
protected ResourceMetadata resourceMetadata;
public class ManagedResourceConfigLoader {
static final Logger log = Logger.getLogger(ManagedResourceConfigLoader.class);
protected ManagedResourceConfig remoteSkeletonKeyConfig;
protected ResourceMetadata resourceMetadata;
protected KeyStore clientCertKeystore;
protected KeyStore truststore;
protected ResteasyClient client;
public ManagedResourceConfigLoader(Context context)
{
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
InputStream is = null;
String path = context.getServletContext().getInitParameter("skeleton.key.config.file");
if (path == null)
{
is = context.getServletContext().getResourceAsStream("/WEB-INF/resteasy-oauth.json");
}
else
{
try
{
is = new FileInputStream(path);
}
catch (FileNotFoundException e)
{
public ManagedResourceConfigLoader(Context context) {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
InputStream is = null;
String path = context.getServletContext().getInitParameter("keycloak.config.file");
if (path == null) {
is = context.getServletContext().getResourceAsStream("/WEB-INF/resteasy-oauth.json");
} else {
try {
is = new FileInputStream(path);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
remoteSkeletonKeyConfig = null;
try {
remoteSkeletonKeyConfig = mapper.readValue(is, ManagedResourceConfig.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
remoteSkeletonKeyConfig = null;
try
{
remoteSkeletonKeyConfig = mapper.readValue(is, ManagedResourceConfig.class);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
}
String name = remoteSkeletonKeyConfig.getResource();
String realm = remoteSkeletonKeyConfig.getRealm();
if (realm == null) throw new RuntimeException("Must set 'realm' in config");
String realmKeyPem = remoteSkeletonKeyConfig.getRealmKey();
if (realmKeyPem == null)
{
throw new IllegalArgumentException("You must set the realm-public-key");
}
PublicKey realmKey = null;
try
{
realmKey = PemUtils.decodePublicKey(realmKeyPem);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
resourceMetadata = new ResourceMetadata();
resourceMetadata.setRealm(realm);
resourceMetadata.setResourceName(name);
resourceMetadata.setRealmKey(realmKey);
public void init(boolean setupClient) {
String truststore = remoteSkeletonKeyConfig.getTruststore();
if (truststore != null)
{
truststore = EnvUtil.replace(truststore);
String truststorePassword = remoteSkeletonKeyConfig.getTruststorePassword();
KeyStore trust = null;
try
{
trust = loadKeyStore(truststore, truststorePassword);
}
catch (Exception e)
{
throw new RuntimeException("Failed to load truststore", e);
}
resourceMetadata.setTruststore(trust);
}
String clientKeystore = remoteSkeletonKeyConfig.getClientKeystore();
String clientKeyPassword = null;
if (clientKeystore != null)
{
clientKeystore = EnvUtil.replace(clientKeystore);
String clientKeystorePassword = remoteSkeletonKeyConfig.getClientKeystorePassword();
KeyStore serverKS = null;
try
{
serverKS = loadKeyStore(clientKeystore, clientKeystorePassword);
}
catch (Exception e)
{
throw new RuntimeException("Failed to load keystore", e);
}
resourceMetadata.setClientKeystore(serverKS);
clientKeyPassword = remoteSkeletonKeyConfig.getClientKeyPassword();
resourceMetadata.setClientKeyPassword(clientKeyPassword);
}
}
public static KeyStore loadKeyStore(String filename, String password) throws Exception
{
KeyStore trustStore = KeyStore.getInstance(KeyStore
.getDefaultType());
File truststoreFile = new File(filename);
FileInputStream trustStream = new FileInputStream(truststoreFile);
trustStore.load(trustStream, password.toCharArray());
trustStream.close();
return trustStore;
}
String truststorePath = remoteSkeletonKeyConfig.getTruststore();
if (truststorePath != null) {
truststorePath = EnvUtil.replace(truststorePath);
String truststorePassword = remoteSkeletonKeyConfig.getTruststorePassword();
truststorePath = null;
try {
this.truststore = loadKeyStore(truststorePath, truststorePassword);
} catch (Exception e) {
throw new RuntimeException("Failed to load truststore", e);
}
}
String clientKeystore = remoteSkeletonKeyConfig.getClientKeystore();
String clientKeyPassword = null;
if (clientKeystore != null) {
clientKeystore = EnvUtil.replace(clientKeystore);
String clientKeystorePassword = remoteSkeletonKeyConfig.getClientKeystorePassword();
clientCertKeystore = null;
try {
clientCertKeystore = loadKeyStore(clientKeystore, clientKeystorePassword);
} catch (Exception e) {
throw new RuntimeException("Failed to load keystore", e);
}
}
public ManagedResourceConfig getRemoteSkeletonKeyConfig()
{
return remoteSkeletonKeyConfig;
}
initClient();
public ResourceMetadata getResourceMetadata()
{
return resourceMetadata;
}
String realm = remoteSkeletonKeyConfig.getRealm();
if (remoteSkeletonKeyConfig.getRealmUrl() != null) {
PublishedRealmRepresentation rep = null;
try {
rep = client.target(remoteSkeletonKeyConfig.getRealmUrl()).request().get(PublishedRealmRepresentation.class);
} finally {
if (!setupClient) {
client.close();
}
}
remoteSkeletonKeyConfig.setRealm(rep.getRealm());
remoteSkeletonKeyConfig.setAuthUrl(rep.getAuthorizationUrl());
remoteSkeletonKeyConfig.setCodeUrl(rep.getCodeUrl());
remoteSkeletonKeyConfig.setRealmKey(rep.getPublicKeyPem());
remoteSkeletonKeyConfig.setAdminRole(rep.getAdminRole());
}
String resource = remoteSkeletonKeyConfig.getResource();
if (realm == null) throw new RuntimeException("Must set 'realm' in config");
String realmKeyPem = remoteSkeletonKeyConfig.getRealmKey();
if (realmKeyPem == null) {
throw new IllegalArgumentException("You must set the realm-public-key");
}
PublicKey realmKey = null;
try {
realmKey = PemUtils.decodePublicKey(realmKeyPem);
} catch (Exception e) {
throw new RuntimeException(e);
}
resourceMetadata = new ResourceMetadata();
resourceMetadata.setRealm(realm);
resourceMetadata.setResourceName(resource);
resourceMetadata.setRealmKey(realmKey);
resourceMetadata.setClientKeystore(clientCertKeystore);
clientKeyPassword = remoteSkeletonKeyConfig.getClientKeyPassword();
resourceMetadata.setClientKeyPassword(clientKeyPassword);
resourceMetadata.setTruststore(this.truststore);
}
protected void initClient() {
int size = 10;
if (remoteSkeletonKeyConfig.getConnectionPoolSize() > 0)
size = remoteSkeletonKeyConfig.getConnectionPoolSize();
ResteasyClientBuilder.HostnameVerificationPolicy policy = ResteasyClientBuilder.HostnameVerificationPolicy.WILDCARD;
if (remoteSkeletonKeyConfig.isAllowAnyHostname())
policy = ResteasyClientBuilder.HostnameVerificationPolicy.ANY;
ResteasyProviderFactory providerFactory = new ResteasyProviderFactory();
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(ManagedResourceConfigLoader.class.getClassLoader());
try {
ResteasyProviderFactory.getInstance(); // initialize builtins
RegisterBuiltin.register(providerFactory);
} finally {
Thread.currentThread().setContextClassLoader(old);
}
ResteasyClientBuilder builder = new ResteasyClientBuilder()
.providerFactory(providerFactory)
.connectionPoolSize(size)
.hostnameVerification(policy)
.keyStore(clientCertKeystore, remoteSkeletonKeyConfig.getClientKeyPassword());
if (remoteSkeletonKeyConfig.isDisableTrustManager()) {
builder.disableTrustManager();
} else {
builder.trustStore(truststore);
}
client = builder.build();
}
public static KeyStore loadKeyStore(String filename, String password) throws Exception {
KeyStore trustStore = KeyStore.getInstance(KeyStore
.getDefaultType());
File truststoreFile = new File(filename);
FileInputStream trustStream = new FileInputStream(truststoreFile);
trustStore.load(trustStream, password.toCharArray());
trustStream.close();
return trustStore;
}
public ManagedResourceConfig getRemoteSkeletonKeyConfig() {
return remoteSkeletonKeyConfig;
}
public ResourceMetadata getResourceMetadata() {
return resourceMetadata;
}
public ResteasyClient getClient() {
return client;
}
public KeyStore getClientCertKeystore() {
return clientCertKeystore;
}
public KeyStore getTruststore() {
return truststore;
}
}

View file

@ -19,6 +19,7 @@ import javax.ws.rs.core.UriInfo;
*/
public class RealmSubResource {
protected static final Logger logger = Logger.getLogger(RealmSubResource.class);
public static final String ADMIN_ROLE = "$REALM-ADMIN$";
@Context
protected UriInfo uriInfo;
@ -32,8 +33,13 @@ public class RealmSubResource {
this.realm = realm;
}
public static UriBuilder realmUrl(UriInfo uriInfo) {
UriBuilder base = uriInfo.getBaseUriBuilder()
.path(RealmsResource.class).path(RealmsResource.class, "getRealmResource");
return base;
}
@GET
@Path("json")
@Produces("application/json")
public PublishedRealmRepresentation getRealm(@PathParam("realm") String id) {
return realmRep(realm, uriInfo);
@ -65,26 +71,14 @@ public class RealmSubResource {
public static PublishedRealmRepresentation realmRep(RealmModel realm, UriInfo uriInfo) {
PublishedRealmRepresentation rep = new PublishedRealmRepresentation();
rep.setRealm(realm.getName());
rep.setSelf(uriInfo.getRequestUri().toString());
rep.setSelf(realmUrl(uriInfo).build(realm.getId()).toString());
rep.setPublicKeyPem(realm.getPublicKeyPem());
rep.setAdminRole(ADMIN_ROLE);
UriBuilder auth = uriInfo.getBaseUriBuilder();
auth.path(RealmsResource.class).path(RealmsResource.class, "getTokenService")
.path(TokenService.class, "requestAccessCode");
rep.setAuthorizationUrl(auth.build(realm.getId()).toString());
UriBuilder code = uriInfo.getBaseUriBuilder();
code.path(RealmsResource.class).path(RealmsResource.class, "getTokenService").path(TokenService.class, "accessRequest");
rep.setCodeUrl(code.build(realm.getId()).toString());
UriBuilder grant = uriInfo.getBaseUriBuilder();
grant.path(RealmsResource.class).path(RealmsResource.class, "getTokenService").path(TokenService.class, "accessTokenGrant");
String grantUrl = grant.build(realm.getId()).toString();
rep.setGrantUrl(grantUrl);
UriBuilder idGrant = uriInfo.getBaseUriBuilder();
grant.path(RealmsResource.class).path(RealmsResource.class, "getTokenService").path(TokenService.class, "identityTokenGrant");
String idGrantUrl = idGrant.build(realm.getId()).toString();
rep.setAuthorizationUrl(TokenService.loginPage(uriInfo).build(realm.getId()).toString());
rep.setCodeUrl(TokenService.accessCodeRequest(uriInfo).build(realm.getId()).toString());
rep.setGrantUrl(TokenService.grantRequest(uriInfo).build(realm.getId()).toString());
String idGrantUrl = TokenService.identityGrantRequest(uriInfo).build(realm.getId()).toString();
rep.setIdentityGrantUrl(idGrantUrl);
return rep;
}