Merge pull request #1641 from patriot1burke/master
initial saml sp adapter
This commit is contained in:
commit
c1cb50b39f
192 changed files with 6402 additions and 959 deletions
|
@ -10,7 +10,6 @@ import org.keycloak.dom.saml.v2.assertion.AssertionType;
|
|||
import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
|
||||
import org.keycloak.dom.saml.v2.assertion.AttributeType;
|
||||
import org.keycloak.dom.saml.v2.assertion.AuthnStatementType;
|
||||
import org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType;
|
||||
import org.keycloak.dom.saml.v2.assertion.NameIDType;
|
||||
import org.keycloak.dom.saml.v2.assertion.SubjectType;
|
||||
import org.keycloak.dom.saml.v2.protocol.LogoutRequestType;
|
||||
|
@ -24,31 +23,23 @@ import org.keycloak.events.EventType;
|
|||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.protocol.saml.SAML2LogoutResponseBuilder;
|
||||
import org.keycloak.protocol.saml.SAMLRequestParser;
|
||||
import org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder;
|
||||
import org.keycloak.saml.SAML2LogoutResponseBuilder;
|
||||
import org.keycloak.saml.SAMLRequestParser;
|
||||
import org.keycloak.protocol.saml.SamlProtocol;
|
||||
import org.keycloak.protocol.saml.SamlProtocolUtils;
|
||||
import org.keycloak.saml.common.constants.GeneralConstants;
|
||||
import org.keycloak.saml.common.constants.JBossSAMLConstants;
|
||||
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
||||
import org.keycloak.saml.common.exceptions.ConfigurationException;
|
||||
import org.keycloak.saml.common.exceptions.ProcessingException;
|
||||
import org.keycloak.saml.common.util.DocumentUtil;
|
||||
import org.keycloak.saml.common.util.StaxParserUtil;
|
||||
import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
|
||||
import org.keycloak.saml.processing.core.parsers.saml.SAMLParser;
|
||||
import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
|
||||
import org.keycloak.saml.processing.core.saml.v2.constants.X500SAMLProfileConstants;
|
||||
import org.keycloak.saml.processing.core.util.JAXPValidationUtil;
|
||||
import org.keycloak.saml.processing.core.util.XMLEncryptionUtil;
|
||||
import org.keycloak.saml.processing.core.saml.v2.util.AssertionUtil;
|
||||
import org.keycloak.saml.processing.core.util.XMLSignatureUtil;
|
||||
import org.keycloak.saml.processing.web.util.PostBindingUtil;
|
||||
import org.keycloak.services.ErrorPage;
|
||||
import org.keycloak.services.managers.AuthenticationManager;
|
||||
import org.keycloak.services.messages.Messages;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.FormParam;
|
||||
|
@ -61,9 +52,7 @@ import javax.ws.rs.core.MediaType;
|
|||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import javax.xml.namespace.QName;
|
||||
import java.io.IOException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.List;
|
||||
|
@ -155,7 +144,7 @@ public class SAMLEndpoint {
|
|||
}
|
||||
|
||||
protected abstract String getBindingType();
|
||||
protected abstract void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException;
|
||||
protected abstract void verifySignature(String key, SAMLDocumentHolder documentHolder) throws VerificationException;
|
||||
protected abstract SAMLDocumentHolder extractRequestDocument(String samlRequest);
|
||||
protected abstract SAMLDocumentHolder extractResponseDocument(String response);
|
||||
protected PublicKey getIDPKey() {
|
||||
|
@ -188,7 +177,7 @@ public class SAMLEndpoint {
|
|||
}
|
||||
if (config.isValidateSignature()) {
|
||||
try {
|
||||
verifySignature(holder);
|
||||
verifySignature(GeneralConstants.SAML_REQUEST_KEY, holder);
|
||||
} catch (VerificationException e) {
|
||||
logger.error("validation failed", e);
|
||||
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
|
||||
|
@ -247,17 +236,18 @@ public class SAMLEndpoint {
|
|||
builder.logoutRequestID(request.getID());
|
||||
builder.destination(config.getSingleLogoutServiceUrl());
|
||||
builder.issuer(issuerURL);
|
||||
builder.relayState(relayState);
|
||||
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder()
|
||||
.relayState(relayState);
|
||||
if (config.isWantAuthnRequestsSigned()) {
|
||||
builder.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
|
||||
binding.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
|
||||
.signatureAlgorithm(provider.getSignatureAlgorithm())
|
||||
.signDocument();
|
||||
}
|
||||
try {
|
||||
if (config.isPostBindingResponse()) {
|
||||
return builder.postBinding().response();
|
||||
return binding.postBinding(builder.buildDocument()).response(config.getSingleLogoutServiceUrl());
|
||||
} else {
|
||||
return builder.redirectBinding().response();
|
||||
return binding.redirectBinding(builder.buildDocument()).response(config.getSingleLogoutServiceUrl());
|
||||
}
|
||||
} catch (ConfigurationException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
@ -275,7 +265,7 @@ public class SAMLEndpoint {
|
|||
protected Response handleLoginResponse(String samlResponse, SAMLDocumentHolder holder, ResponseType responseType, String relayState) {
|
||||
|
||||
try {
|
||||
AssertionType assertion = getAssertion(responseType);
|
||||
AssertionType assertion = AssertionUtil.getAssertion(responseType, realm.getPrivateKey());
|
||||
SubjectType subject = assertion.getSubject();
|
||||
SubjectType.STSubType subType = subject.getSubType();
|
||||
NameIDType subjectNameID = (NameIDType) subType.getBaseID();
|
||||
|
@ -335,22 +325,6 @@ public class SAMLEndpoint {
|
|||
|
||||
|
||||
|
||||
private AssertionType getAssertion(ResponseType responseType) throws ProcessingException {
|
||||
List<ResponseType.RTChoiceType> assertions = responseType.getAssertions();
|
||||
|
||||
if (assertions.isEmpty()) {
|
||||
throw new IdentityBrokerException("No assertion from response.");
|
||||
}
|
||||
|
||||
ResponseType.RTChoiceType rtChoiceType = assertions.get(0);
|
||||
EncryptedAssertionType encryptedAssertion = rtChoiceType.getEncryptedAssertion();
|
||||
|
||||
if (encryptedAssertion != null) {
|
||||
decryptAssertion(responseType, realm.getPrivateKey());
|
||||
|
||||
}
|
||||
return responseType.getAssertions().get(0).getAssertion();
|
||||
}
|
||||
|
||||
public Response handleSamlResponse(String samlResponse, String relayState) {
|
||||
SAMLDocumentHolder holder = extractResponseDocument(samlResponse);
|
||||
|
@ -364,7 +338,7 @@ public class SAMLEndpoint {
|
|||
}
|
||||
if (config.isValidateSignature()) {
|
||||
try {
|
||||
verifySignature(holder);
|
||||
verifySignature(GeneralConstants.SAML_RESPONSE_KEY, holder);
|
||||
} catch (VerificationException e) {
|
||||
logger.error("validation failed", e);
|
||||
event.event(EventType.IDENTITY_PROVIDER_RESPONSE);
|
||||
|
@ -407,43 +381,14 @@ public class SAMLEndpoint {
|
|||
}
|
||||
|
||||
|
||||
protected ResponseType decryptAssertion(ResponseType responseType, PrivateKey privateKey) throws ProcessingException {
|
||||
SAML2Response saml2Response = new SAML2Response();
|
||||
|
||||
try {
|
||||
Document doc = saml2Response.convert(responseType);
|
||||
Element enc = DocumentUtil.getElement(doc, new QName(JBossSAMLConstants.ENCRYPTED_ASSERTION.get()));
|
||||
|
||||
if (enc == null) {
|
||||
throw new IdentityBrokerException("No encrypted assertion found.");
|
||||
}
|
||||
|
||||
String oldID = enc.getAttribute(JBossSAMLConstants.ID.get());
|
||||
Document newDoc = DocumentUtil.createDocument();
|
||||
Node importedNode = newDoc.importNode(enc, true);
|
||||
newDoc.appendChild(importedNode);
|
||||
|
||||
Element decryptedDocumentElement = XMLEncryptionUtil.decryptElementInDocument(newDoc, privateKey);
|
||||
SAMLParser parser = new SAMLParser();
|
||||
|
||||
JAXPValidationUtil.checkSchemaValidation(decryptedDocumentElement);
|
||||
AssertionType assertion = (AssertionType) parser.parse(StaxParserUtil.getXMLEventReader(DocumentUtil
|
||||
.getNodeAsStream(decryptedDocumentElement)));
|
||||
|
||||
responseType.replaceAssertion(oldID, new ResponseType.RTChoiceType(assertion));
|
||||
|
||||
return responseType;
|
||||
} catch (Exception e) {
|
||||
throw new IdentityBrokerException("Could not decrypt assertion.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected class PostBinding extends Binding {
|
||||
@Override
|
||||
protected void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException {
|
||||
protected void verifySignature(String key, SAMLDocumentHolder documentHolder) throws VerificationException {
|
||||
SamlProtocolUtils.verifyDocumentSignature(documentHolder.getSamlDocument(), getIDPKey());
|
||||
}
|
||||
|
||||
|
@ -466,9 +411,9 @@ public class SAMLEndpoint {
|
|||
|
||||
protected class RedirectBinding extends Binding {
|
||||
@Override
|
||||
protected void verifySignature(SAMLDocumentHolder documentHolder) throws VerificationException {
|
||||
protected void verifySignature(String key, SAMLDocumentHolder documentHolder) throws VerificationException {
|
||||
PublicKey publicKey = getIDPKey();
|
||||
SamlProtocolUtils.verifyRedirectSignature(publicKey, uriInfo);
|
||||
SamlProtocolUtils.verifyRedirectSignature(publicKey, uriInfo, key);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -33,21 +33,18 @@ import org.keycloak.models.ClientSessionModel;
|
|||
import org.keycloak.models.FederatedIdentityModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.protocol.saml.SAML2AuthnRequestBuilder;
|
||||
import org.keycloak.protocol.saml.SAML2LogoutRequestBuilder;
|
||||
import org.keycloak.protocol.saml.SAML2NameIDPolicyBuilder;
|
||||
import org.keycloak.protocol.saml.SignatureAlgorithm;
|
||||
import org.keycloak.protocol.saml.JaxrsSAML2BindingBuilder;
|
||||
import org.keycloak.saml.SAML2AuthnRequestBuilder;
|
||||
import org.keycloak.saml.SAML2LogoutRequestBuilder;
|
||||
import org.keycloak.saml.SAML2NameIDPolicyBuilder;
|
||||
import org.keycloak.saml.SignatureAlgorithm;
|
||||
import org.keycloak.saml.common.constants.GeneralConstants;
|
||||
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
|
||||
import org.keycloak.saml.common.exceptions.ConfigurationException;
|
||||
import org.keycloak.saml.common.exceptions.ParsingException;
|
||||
import org.keycloak.saml.common.exceptions.ProcessingException;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
@ -93,7 +90,8 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
|
|||
.issuer(issuerURL)
|
||||
.forceAuthn(getConfig().isForceAuthn())
|
||||
.protocolBinding(protocolBinding)
|
||||
.nameIdPolicy(SAML2NameIDPolicyBuilder.format(nameIDPolicyFormat))
|
||||
.nameIdPolicy(SAML2NameIDPolicyBuilder.format(nameIDPolicyFormat));
|
||||
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder()
|
||||
.relayState(request.getState());
|
||||
|
||||
if (getConfig().isWantAuthnRequestsSigned()) {
|
||||
|
@ -110,15 +108,15 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
|
|||
|
||||
KeyPair keypair = new KeyPair(publicKey, privateKey);
|
||||
|
||||
authnRequestBuilder.signWith(keypair);
|
||||
authnRequestBuilder.signatureAlgorithm(getSignatureAlgorithm());
|
||||
authnRequestBuilder.signDocument();
|
||||
binding.signWith(keypair);
|
||||
binding.signatureAlgorithm(getSignatureAlgorithm());
|
||||
binding.signDocument();
|
||||
}
|
||||
|
||||
if (getConfig().isPostBindingAuthnRequest()) {
|
||||
return authnRequestBuilder.postBinding().request();
|
||||
return binding.postBinding(authnRequestBuilder.toDocument()).request(destinationUrl);
|
||||
} else {
|
||||
return authnRequestBuilder.redirectBinding().request();
|
||||
return binding.redirectBinding(authnRequestBuilder.toDocument()).request(destinationUrl);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IdentityBrokerException("Could not create authentication request.", e);
|
||||
|
@ -155,9 +153,10 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
|
|||
String singleLogoutServiceUrl = getConfig().getSingleLogoutServiceUrl();
|
||||
if (singleLogoutServiceUrl == null || singleLogoutServiceUrl.trim().equals("") || !getConfig().isBackchannelSupported()) return;
|
||||
SAML2LogoutRequestBuilder logoutBuilder = buildLogoutRequest(userSession, uriInfo, realm, singleLogoutServiceUrl);
|
||||
JaxrsSAML2BindingBuilder binding = buildLogoutBinding(userSession, realm);
|
||||
try {
|
||||
int status = SimpleHttp.doPost(singleLogoutServiceUrl)
|
||||
.param(GeneralConstants.SAML_REQUEST_KEY, logoutBuilder.postBinding().encoded())
|
||||
.param(GeneralConstants.SAML_REQUEST_KEY, binding.postBinding(logoutBuilder.buildDocument()).encoded())
|
||||
.param(GeneralConstants.RELAY_STATE, userSession.getId()).asStatus();
|
||||
boolean success = status >=200 && status < 400;
|
||||
if (!success) {
|
||||
|
@ -180,7 +179,8 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
|
|||
} else {
|
||||
try {
|
||||
SAML2LogoutRequestBuilder logoutBuilder = buildLogoutRequest(userSession, uriInfo, realm, singleLogoutServiceUrl);
|
||||
return logoutBuilder.postBinding().request();
|
||||
JaxrsSAML2BindingBuilder binding = buildLogoutBinding(userSession, realm);
|
||||
return binding.postBinding(logoutBuilder.buildDocument()).request(singleLogoutServiceUrl);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -194,14 +194,19 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
|
|||
.issuer(getEntityId(uriInfo, realm))
|
||||
.sessionIndex(userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SESSION_INDEX))
|
||||
.userPrincipal(userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT), userSession.getNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT_NAMEFORMAT))
|
||||
.destination(singleLogoutServiceUrl)
|
||||
.destination(singleLogoutServiceUrl);
|
||||
return logoutBuilder;
|
||||
}
|
||||
|
||||
private JaxrsSAML2BindingBuilder buildLogoutBinding(UserSessionModel userSession, RealmModel realm) {
|
||||
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder()
|
||||
.relayState(userSession.getId());
|
||||
if (getConfig().isWantAuthnRequestsSigned()) {
|
||||
logoutBuilder.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
|
||||
binding.signWith(realm.getPrivateKey(), realm.getPublicKey(), realm.getCertificate())
|
||||
.signatureAlgorithm(getSignatureAlgorithm())
|
||||
.signDocument();
|
||||
}
|
||||
return logoutBuilder;
|
||||
return binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -257,4 +262,5 @@ public class SAMLIdentityProvider extends AbstractIdentityProvider<SAMLIdentityP
|
|||
}
|
||||
return SignatureAlgorithm.RSA_SHA256;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<include>org/bouncycastle/**</include>
|
||||
<include>net/iharder/base64/**</include>
|
||||
<include>org/keycloak/keycloak-core/**</include>
|
||||
<include>org/keycloak/keycloak-adapter-spi/**</include>
|
||||
<include>org/keycloak/keycloak-adapter-core/**</include>
|
||||
<include>org/keycloak/keycloak-jboss-adapter-core/**</include>
|
||||
<include>org/keycloak/keycloak-as7-adapter/**</include>
|
||||
|
|
|
@ -53,6 +53,11 @@
|
|||
|
||||
<!-- subsystems -->
|
||||
|
||||
<module-def name="org.keycloak.keycloak-adapter-spi">
|
||||
<maven-resource group="org.keycloak" artifact="keycloak-adapter-spi"/>
|
||||
<maven-resource group="org.keycloak" artifact="keycloak-tomcat-adapter-spi"/>
|
||||
</module-def>
|
||||
|
||||
<module-def name="org.keycloak.keycloak-adapter-core">
|
||||
<maven-resource group="org.keycloak" artifact="keycloak-adapter-core"/>
|
||||
</module-def>
|
||||
|
|
|
@ -21,6 +21,14 @@
|
|||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-tomcat-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<module name="org.apache.httpcomponents"/>
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="net.iharder.base64"/>
|
||||
</dependencies>
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
|
||||
|
||||
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-adapter-spi">
|
||||
<resources>
|
||||
<!-- Insert resources here -->
|
||||
</resources>
|
||||
<dependencies>
|
||||
<module name="javax.api"/>
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.jboss.as.web"/>
|
||||
<module name="javax.servlet.api"/>
|
||||
<module name="org.apache.httpcomponents"/>
|
||||
<module name="org.bouncycastle" />
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
<module name="net.iharder.base64"/>
|
||||
</dependencies>
|
||||
|
||||
</module>
|
|
@ -18,6 +18,7 @@
|
|||
<module name="org.jboss.as.security"/>
|
||||
<module name="org.jboss.as.web"/>
|
||||
<module name="org.picketbox"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<module name="javax.api"/>
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.picketbox"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<module name="org.jboss.logging"/>
|
||||
<module name="org.picketbox"/>
|
||||
<module name="org.apache.httpcomponents"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<include>org/bouncycastle/**</include>
|
||||
<include>net/iharder/base64/**</include>
|
||||
<include>org/keycloak/keycloak-core/**</include>
|
||||
<include>org/keycloak/keycloak-adapter-spi/**</include>
|
||||
<include>org/keycloak/keycloak-adapter-core/**</include>
|
||||
<include>org/keycloak/keycloak-jboss-adapter-core/**</include>
|
||||
<include>org/keycloak/keycloak-as7-adapter/**</include>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<include>net/iharder/base64/**</include>
|
||||
<include>org/apache/httpcomponents/**</include>
|
||||
<include>org/keycloak/keycloak-core/**</include>
|
||||
<include>org/keycloak/keycloak-adapter-spi/**</include>
|
||||
<include>org/keycloak/keycloak-adapter-core/**</include>
|
||||
<include>org/keycloak/keycloak-jboss-adapter-core/**</include>
|
||||
<include>org/keycloak/keycloak-undertow-adapter/**</include>
|
||||
|
|
|
@ -49,6 +49,11 @@
|
|||
|
||||
<!-- subsystems -->
|
||||
|
||||
<module-def name="org.keycloak.keycloak-adapter-spi">
|
||||
<maven-resource group="org.keycloak" artifact="keycloak-adapter-spi"/>
|
||||
<maven-resource group="org.keycloak" artifact="keycloak-undertow-adapter-spi"/>
|
||||
</module-def>
|
||||
|
||||
<module-def name="org.keycloak.keycloak-adapter-core">
|
||||
<maven-resource group="org.keycloak" artifact="keycloak-adapter-core"/>
|
||||
</module-def>
|
||||
|
|
|
@ -21,6 +21,14 @@
|
|||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-undertow-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<module name="org.codehaus.jackson.jackson-xc"/>
|
||||
<module name="org.apache.httpcomponents" slot="4.3" />
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
<module name="net.iharder.base64"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
|
||||
|
||||
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-adapter-spi">
|
||||
<resources>
|
||||
<!-- Insert resources here -->
|
||||
</resources>
|
||||
<dependencies>
|
||||
<module name="javax.api"/>
|
||||
<module name="org.apache.httpcomponents" slot="4.3" />
|
||||
<module name="javax.servlet.api"/>
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.jboss.xnio"/>
|
||||
<module name="io.undertow.core"/>
|
||||
<module name="io.undertow.servlet"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
||||
</module>
|
|
@ -10,6 +10,7 @@
|
|||
<module name="javax.api"/>
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.picketbox"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<module name="org.jboss.logging"/>
|
||||
<module name="org.picketbox"/>
|
||||
<module name="org.apache.httpcomponents" slot="4.3"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
<module name="org.jboss.xnio"/>
|
||||
<module name="io.undertow.core"/>
|
||||
<module name="io.undertow.servlet"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
<module name="io.undertow.servlet"/>
|
||||
<module name="org.picketbox"/>
|
||||
<module name="org.keycloak.keycloak-undertow-adapter"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<include>net/iharder/base64/**</include>
|
||||
<include>org/keycloak/keycloak-core/**</include>
|
||||
<include>org/keycloak/keycloak-adapter-core/**</include>
|
||||
<include>org/keycloak/keycloak-adapter-spi/**</include>
|
||||
<include>org/keycloak/keycloak-jboss-adapter-core/**</include>
|
||||
<include>org/keycloak/keycloak-undertow-adapter/**</include>
|
||||
<include>org/keycloak/keycloak-wildfly-adapter/**</include>
|
||||
|
|
|
@ -49,6 +49,11 @@
|
|||
|
||||
<!-- subsystems -->
|
||||
|
||||
<module-def name="org.keycloak.keycloak-adapter-spi">
|
||||
<maven-resource group="org.keycloak" artifact="keycloak-adapter-spi"/>
|
||||
<maven-resource group="org.keycloak" artifact="keycloak-undertow-adapter-spi"/>
|
||||
</module-def>
|
||||
|
||||
<module-def name="org.keycloak.keycloak-adapter-core">
|
||||
<maven-resource group="org.keycloak" artifact="keycloak-adapter-core"/>
|
||||
</module-def>
|
||||
|
|
|
@ -21,6 +21,14 @@
|
|||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-undertow-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<module name="org.codehaus.jackson.jackson-xc"/>
|
||||
<module name="org.apache.httpcomponents"/>
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
<module name="net.iharder.base64"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
|
||||
|
||||
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-adapter-spi">
|
||||
<resources>
|
||||
<!-- Insert resources here -->
|
||||
</resources>
|
||||
<dependencies>
|
||||
<module name="javax.api"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
<module name="org.apache.httpcomponents"/>
|
||||
<module name="javax.servlet.api"/>
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.jboss.xnio"/>
|
||||
<module name="io.undertow.core"/>
|
||||
<module name="io.undertow.servlet"/>
|
||||
</dependencies>
|
||||
|
||||
</module>
|
|
@ -10,6 +10,7 @@
|
|||
<module name="javax.api"/>
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.picketbox"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<module name="org.jboss.logging"/>
|
||||
<module name="org.picketbox"/>
|
||||
<module name="org.apache.httpcomponents"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
<module name="org.jboss.xnio"/>
|
||||
<module name="io.undertow.core"/>
|
||||
<module name="io.undertow.servlet"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
<module name="io.undertow.servlet"/>
|
||||
<module name="org.picketbox"/>
|
||||
<module name="org.keycloak.keycloak-undertow-adapter"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
8
distribution/feature-packs/adapter-feature-pack/pom.xml
Normal file → Executable file
8
distribution/feature-packs/adapter-feature-pack/pom.xml
Normal file → Executable file
|
@ -44,6 +44,14 @@
|
|||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-servlet-oauth-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-undertow-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-undertow-adapter</artifactId>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<module name="org.codehaus.jackson.jackson-xc"/>
|
||||
<module name="org.apache.httpcomponents" />
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
<module name="net.iharder.base64"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
|
||||
|
||||
<module xmlns="urn:jboss:module:1.3" name="org.keycloak.keycloak-adapter-spi">
|
||||
<resources>
|
||||
<artifact name="${org.keycloak:keycloak-adapter-spi}"/>
|
||||
<artifact name="${org.keycloak:keycloak-undertow-adapter-spi}"/>
|
||||
</resources>
|
||||
<dependencies>
|
||||
<module name="javax.api"/>
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.jboss.xnio"/>
|
||||
<module name="io.undertow.core"/>
|
||||
<module name="io.undertow.servlet"/>
|
||||
<module name="javax.servlet.api"/>
|
||||
<module name="org.bouncycastle" />
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
<module name="net.iharder.base64"/>
|
||||
</dependencies>
|
||||
|
||||
</module>
|
|
@ -10,6 +10,7 @@
|
|||
<module name="javax.api"/>
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.picketbox"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<module name="org.jboss.logging"/>
|
||||
<module name="org.picketbox"/>
|
||||
<module name="org.apache.httpcomponents"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
<module name="org.jboss.xnio"/>
|
||||
<module name="io.undertow.core"/>
|
||||
<module name="io.undertow.servlet"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
<module name="io.undertow.servlet"/>
|
||||
<module name="org.picketbox"/>
|
||||
<module name="org.keycloak.keycloak-undertow-adapter"/>
|
||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
<module name="org.keycloak.keycloak-core"/>
|
||||
</dependencies>
|
||||
|
|
|
@ -39,6 +39,10 @@
|
|||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Contains KeycloakPrincipal -->
|
||||
<dependency>
|
||||
|
|
5
examples/multi-tenant/src/main/java/org/keycloak/example/multitenant/control/PathBasedKeycloakConfigResolver.java
Normal file → Executable file
5
examples/multi-tenant/src/main/java/org/keycloak/example/multitenant/control/PathBasedKeycloakConfigResolver.java
Normal file → Executable file
|
@ -17,14 +17,13 @@
|
|||
package org.keycloak.example.multitenant.control;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.keycloak.adapters.HttpFacade;
|
||||
import org.keycloak.adapters.KeycloakConfigResolver;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.KeycloakDeploymentBuilder;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -35,7 +34,7 @@ public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver {
|
|||
private final Map<String, KeycloakDeployment> cache = new ConcurrentHashMap<String, KeycloakDeployment>();
|
||||
|
||||
@Override
|
||||
public KeycloakDeployment resolve(HttpFacade.Request request) {
|
||||
public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
|
||||
String path = request.getURI();
|
||||
int multitenantIndex = path.indexOf("multitenant/");
|
||||
if (multitenantIndex == -1) {
|
||||
|
|
|
@ -38,6 +38,11 @@
|
|||
<version>${jboss.logging.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@ package org.keycloak.adapters;
|
|||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public interface AdapterTokenStore {
|
||||
public interface AdapterTokenStore extends AdapterSessionStore {
|
||||
|
||||
/**
|
||||
* Impl can validate if current token exists and perform refreshing if it exists and is expired
|
||||
|
@ -39,6 +39,4 @@ public interface AdapterTokenStore {
|
|||
*/
|
||||
void refreshCallback(RefreshableKeycloakSecurityContext securityContext);
|
||||
|
||||
void saveRequest();
|
||||
boolean restoreRequest();
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@ import java.util.Set;
|
|||
public class AuthenticatedActionsHandler {
|
||||
private static final Logger log = Logger.getLogger(AuthenticatedActionsHandler.class);
|
||||
protected KeycloakDeployment deployment;
|
||||
protected HttpFacade facade;
|
||||
protected OIDCHttpFacade facade;
|
||||
|
||||
public AuthenticatedActionsHandler(KeycloakDeployment deployment, HttpFacade facade) {
|
||||
public AuthenticatedActionsHandler(KeycloakDeployment deployment, OIDCHttpFacade facade) {
|
||||
this.deployment = deployment;
|
||||
this.facade = facade;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ public class CookieTokenStore {
|
|||
}
|
||||
|
||||
public static KeycloakPrincipal<RefreshableKeycloakSecurityContext> getPrincipalFromCookie(KeycloakDeployment deployment, HttpFacade facade, AdapterTokenStore tokenStore) {
|
||||
HttpFacade.Cookie cookie = facade.getRequest().getCookie(AdapterConstants.KEYCLOAK_ADAPTER_STATE_COOKIE);
|
||||
OIDCHttpFacade.Cookie cookie = facade.getRequest().getCookie(AdapterConstants.KEYCLOAK_ADAPTER_STATE_COOKIE);
|
||||
if (cookie == null) {
|
||||
log.debug("Not found adapter state cookie in current request");
|
||||
return null;
|
||||
|
|
|
@ -14,7 +14,6 @@ import org.keycloak.util.KeycloakUriBuilder;
|
|||
import org.keycloak.util.UriUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
|
||||
|
@ -27,7 +26,7 @@ public class OAuthRequestAuthenticator {
|
|||
protected KeycloakDeployment deployment;
|
||||
protected RequestAuthenticator reqAuthenticator;
|
||||
protected int sslRedirectPort;
|
||||
protected AdapterTokenStore tokenStore;
|
||||
protected AdapterSessionStore tokenStore;
|
||||
protected String tokenString;
|
||||
protected String idTokenString;
|
||||
protected IDToken idToken;
|
||||
|
@ -37,7 +36,7 @@ public class OAuthRequestAuthenticator {
|
|||
protected String refreshToken;
|
||||
protected String strippedOauthParametersRequestUri;
|
||||
|
||||
public OAuthRequestAuthenticator(RequestAuthenticator requestAuthenticator, HttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort, AdapterTokenStore tokenStore) {
|
||||
public OAuthRequestAuthenticator(RequestAuthenticator requestAuthenticator, HttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort, AdapterSessionStore tokenStore) {
|
||||
this.reqAuthenticator = requestAuthenticator;
|
||||
this.facade = facade;
|
||||
this.deployment = deployment;
|
||||
|
@ -93,12 +92,12 @@ public class OAuthRequestAuthenticator {
|
|||
return facade.getRequest().isSecure();
|
||||
}
|
||||
|
||||
protected HttpFacade.Cookie getCookie(String cookieName) {
|
||||
protected OIDCHttpFacade.Cookie getCookie(String cookieName) {
|
||||
return facade.getRequest().getCookie(cookieName);
|
||||
}
|
||||
|
||||
protected String getCookieValue(String cookieName) {
|
||||
HttpFacade.Cookie cookie = getCookie(cookieName);
|
||||
OIDCHttpFacade.Cookie cookie = getCookie(cookieName);
|
||||
if (cookie == null) return null;
|
||||
return cookie.getValue();
|
||||
}
|
||||
|
@ -204,7 +203,7 @@ public class OAuthRequestAuthenticator {
|
|||
}
|
||||
|
||||
protected AuthChallenge checkStateCookie() {
|
||||
HttpFacade.Cookie stateCookie = getCookie(deployment.getStateCookieName());
|
||||
OIDCHttpFacade.Cookie stateCookie = getCookie(deployment.getStateCookieName());
|
||||
|
||||
if (stateCookie == null) {
|
||||
log.warn("No state cookie");
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package org.keycloak.adapters;
|
||||
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
|
||||
/**
|
||||
* Bridge between core adapter and HTTP Engine
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface OIDCHttpFacade extends HttpFacade {
|
||||
|
||||
KeycloakSecurityContext getSecurityContext();
|
||||
}
|
|
@ -9,11 +9,11 @@ import org.keycloak.KeycloakPrincipal;
|
|||
*/
|
||||
public abstract class RequestAuthenticator {
|
||||
protected static Logger log = Logger.getLogger(RequestAuthenticator.class);
|
||||
|
||||
protected HttpFacade facade;
|
||||
protected AuthChallenge challenge;
|
||||
|
||||
protected KeycloakDeployment deployment;
|
||||
protected AdapterTokenStore tokenStore;
|
||||
protected AuthChallenge challenge;
|
||||
protected int sslRedirectPort;
|
||||
|
||||
public RequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, AdapterTokenStore tokenStore, int sslRedirectPort) {
|
||||
|
|
93
integration/adapter-spi/pom.xml
Executable file
93
integration/adapter-spi/pom.xml
Executable file
|
@ -0,0 +1,93 @@
|
|||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.6.0.Final-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
<name>Keycloak Adapter SPI</name>
|
||||
<description/>
|
||||
|
||||
<properties>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
org.keycloak.*;version="${project.version}",
|
||||
org.apache.http.*;version=${apache.httpcomponents.version},
|
||||
org.apache.karaf.jaas.boot.principal;resolution:=optional,
|
||||
org.apache.karaf.jaas.modules;resolution:=optional,
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<version>${jboss.logging.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,10 @@
|
|||
package org.keycloak.adapters;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface AdapterSessionStore {
|
||||
void saveRequest();
|
||||
boolean restoreRequest();
|
||||
}
|
|
@ -7,5 +7,6 @@ package org.keycloak.adapters;
|
|||
public enum AuthOutcome {
|
||||
NOT_ATTEMPTED,
|
||||
FAILED,
|
||||
AUTHENTICATED
|
||||
AUTHENTICATED,
|
||||
LOGGED_OUT
|
||||
}
|
|
@ -1,19 +1,69 @@
|
|||
package org.keycloak.adapters;
|
||||
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
|
||||
import javax.security.cert.X509Certificate;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Bridge between core adapter and HTTP Engine
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface HttpFacade {
|
||||
Request getRequest();
|
||||
|
||||
Response getResponse();
|
||||
|
||||
X509Certificate[] getCertificateChain();
|
||||
|
||||
interface Request {
|
||||
|
||||
String getMethod();
|
||||
/**
|
||||
* Full request URI with query params
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getURI();
|
||||
|
||||
/**
|
||||
* HTTPS?
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isSecure();
|
||||
|
||||
/**
|
||||
* Get first query or form param
|
||||
*
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
String getFirstParam(String param);
|
||||
String getQueryParamValue(String param);
|
||||
Cookie getCookie(String cookieName);
|
||||
String getHeader(String name);
|
||||
List<String> getHeaders(String name);
|
||||
InputStream getInputStream();
|
||||
|
||||
String getRemoteAddr();
|
||||
}
|
||||
|
||||
interface Response {
|
||||
void setStatus(int status);
|
||||
void addHeader(String name, String value);
|
||||
void setHeader(String name, String value);
|
||||
void resetCookie(String name, String path);
|
||||
void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly);
|
||||
OutputStream getOutputStream();
|
||||
void sendError(int code, String message);
|
||||
|
||||
/**
|
||||
* If the response is finished, end it.
|
||||
*
|
||||
*/
|
||||
void end();
|
||||
}
|
||||
|
||||
public class Cookie {
|
||||
protected String name;
|
||||
|
@ -50,51 +100,4 @@ public interface HttpFacade {
|
|||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
interface Request {
|
||||
|
||||
String getMethod();
|
||||
/**
|
||||
* Full request URI with query params
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getURI();
|
||||
|
||||
/**
|
||||
* HTTPS?
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isSecure();
|
||||
|
||||
String getQueryParamValue(String param);
|
||||
Cookie getCookie(String cookieName);
|
||||
String getHeader(String name);
|
||||
List<String> getHeaders(String name);
|
||||
InputStream getInputStream();
|
||||
|
||||
String getRemoteAddr();
|
||||
}
|
||||
|
||||
interface Response {
|
||||
void setStatus(int status);
|
||||
void addHeader(String name, String value);
|
||||
void setHeader(String name, String value);
|
||||
void resetCookie(String name, String path);
|
||||
void setCookie(String name, String value, String path, String domain, int maxAge, boolean secure, boolean httpOnly);
|
||||
OutputStream getOutputStream();
|
||||
void sendError(int code, String message);
|
||||
|
||||
/**
|
||||
* If the response is finished, end it.
|
||||
*
|
||||
*/
|
||||
void end();
|
||||
}
|
||||
|
||||
KeycloakSecurityContext getSecurityContext();
|
||||
Request getRequest();
|
||||
Response getResponse();
|
||||
X509Certificate[] getCertificateChain();
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package org.keycloak.adapters;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Maps external principal and SSO id to internal local http session id
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class InMemorySessionIdMapper implements SessionIdMapper {
|
||||
ConcurrentHashMap<String, String> ssoToSession = new ConcurrentHashMap<>();
|
||||
ConcurrentHashMap<String, String> sessionToSso = new ConcurrentHashMap<>();
|
||||
ConcurrentHashMap<String, Set<String>> principalToSession = new ConcurrentHashMap<>();
|
||||
ConcurrentHashMap<String, String> sessionToPrincipal = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public Set<String> getUserSessions(String principal) {
|
||||
Set<String> lookup = principalToSession.get(principal);
|
||||
if (lookup == null) return null;
|
||||
Set<String> copy = new HashSet<>();
|
||||
copy.addAll(lookup);
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSessionFromSSO(String sso) {
|
||||
return ssoToSession.get(sso);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void map(String sso, String principal, String session) {
|
||||
if (sso != null) {
|
||||
ssoToSession.put(sso, session);
|
||||
sessionToSso.put(session, sso);
|
||||
}
|
||||
Set<String> userSessions = principalToSession.get(principal);
|
||||
if (userSessions == null) {
|
||||
final Set<String> tmp = Collections.synchronizedSet(new HashSet<String>());
|
||||
userSessions = principalToSession.putIfAbsent(principal, tmp);
|
||||
if (userSessions == null) {
|
||||
userSessions = tmp;
|
||||
}
|
||||
}
|
||||
userSessions.add(session);
|
||||
sessionToPrincipal.put(session, principal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSession(String session) {
|
||||
String sso = sessionToSso.remove(session);
|
||||
if (sso != null) {
|
||||
ssoToSession.remove(sso);
|
||||
}
|
||||
String principal = sessionToPrincipal.remove(session);
|
||||
if (principal != null) {
|
||||
Set<String> sessions = principalToSession.get(principal);
|
||||
sessions.remove(session);
|
||||
if (sessions.isEmpty()) {
|
||||
principalToSession.remove(principal, sessions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.keycloak.adapters;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface SessionIdMapper {
|
||||
Set<String> getUserSessions(String principal);
|
||||
|
||||
String getSessionFromSSO(String sso);
|
||||
|
||||
void map(String sso, String principal, String session);
|
||||
|
||||
void removeSession(String session);
|
||||
}
|
|
@ -18,6 +18,10 @@
|
|||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
|
13
integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsHttpFacade.java
Normal file → Executable file
13
integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsHttpFacade.java
Normal file → Executable file
|
@ -11,13 +11,13 @@ import javax.ws.rs.core.MultivaluedMap;
|
|||
import javax.ws.rs.core.SecurityContext;
|
||||
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.HttpFacade;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
import org.keycloak.util.HostUtils;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class JaxrsHttpFacade implements HttpFacade {
|
||||
public class JaxrsHttpFacade implements OIDCHttpFacade {
|
||||
|
||||
protected final ContainerRequestContext requestContext;
|
||||
protected final SecurityContext securityContext;
|
||||
|
@ -31,7 +31,12 @@ public class JaxrsHttpFacade implements HttpFacade {
|
|||
this.securityContext = securityContext;
|
||||
}
|
||||
|
||||
protected class RequestFacade implements HttpFacade.Request {
|
||||
protected class RequestFacade implements OIDCHttpFacade.Request {
|
||||
|
||||
@Override
|
||||
public String getFirstParam(String param) {
|
||||
throw new RuntimeException("NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
|
@ -90,7 +95,7 @@ public class JaxrsHttpFacade implements HttpFacade {
|
|||
}
|
||||
}
|
||||
|
||||
protected class ResponseFacade implements HttpFacade.Response {
|
||||
protected class ResponseFacade implements OIDCHttpFacade.Response {
|
||||
|
||||
private javax.ws.rs.core.Response.ResponseBuilder responseBuilder = javax.ws.rs.core.Response.status(204);
|
||||
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
|
115
integration/jetty/jetty-adapter-spi/pom.xml
Executable file
115
integration/jetty/jetty-adapter-spi/pom.xml
Executable file
|
@ -0,0 +1,115 @@
|
|||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.6.0.Final-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-jetty-adapter-spi</artifactId>
|
||||
<name>Keycloak Jetty Adapter SPI</name>
|
||||
<properties>
|
||||
<jetty9.version>8.1.16.v20140903</jetty9.version>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.jetty.core.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
org.eclipse.jetty.*;version="[8.1,10)";resolution:=optional,
|
||||
javax.servlet.*;version="[2.5,4)";resolution:=optional,
|
||||
org.keycloak.*;version="${project.version}",
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
</properties>
|
||||
<description />
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<version>${jboss.logging.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-security</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -1,6 +1,5 @@
|
|||
package org.keycloak.adapters.jetty.core;
|
||||
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.HttpFacade;
|
||||
import org.keycloak.util.MultivaluedHashMap;
|
||||
import org.keycloak.util.UriUtils;
|
||||
|
@ -19,12 +18,37 @@ import java.util.List;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JettyHttpFacade implements HttpFacade {
|
||||
public final static String __J_METHOD = "org.eclipse.jetty.security.HTTP_METHOD";
|
||||
protected org.eclipse.jetty.server.Request request;
|
||||
protected HttpServletResponse response;
|
||||
protected RequestFacade requestFacade = new RequestFacade();
|
||||
protected ResponseFacade responseFacade = new ResponseFacade();
|
||||
protected MultivaluedHashMap<String, String> queryParameters;
|
||||
|
||||
public JettyHttpFacade(org.eclipse.jetty.server.Request request, HttpServletResponse response) {
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request getRequest() {
|
||||
return requestFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response getResponse() {
|
||||
return responseFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getCertificateChain() {
|
||||
throw new IllegalStateException("Not supported yet");
|
||||
}
|
||||
|
||||
public boolean isEnded() {
|
||||
return responseFacade.isEnded();
|
||||
}
|
||||
|
||||
protected class RequestFacade implements Request {
|
||||
@Override
|
||||
public String getURI() {
|
||||
|
@ -35,6 +59,11 @@ public class JettyHttpFacade implements HttpFacade {
|
|||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstParam(String param) {
|
||||
return request.getParameter(param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return request.isSecure();
|
||||
|
@ -159,33 +188,4 @@ public class JettyHttpFacade implements HttpFacade {
|
|||
return ended;
|
||||
}
|
||||
}
|
||||
|
||||
public JettyHttpFacade(org.eclipse.jetty.server.Request request, HttpServletResponse response) {
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request getRequest() {
|
||||
return requestFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response getResponse() {
|
||||
return responseFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakSecurityContext getSecurityContext() {
|
||||
return (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getCertificateChain() {
|
||||
throw new IllegalStateException("Not supported yet");
|
||||
}
|
||||
|
||||
public boolean isEnded() {
|
||||
return responseFacade.isEnded();
|
||||
}
|
||||
}
|
|
@ -35,6 +35,14 @@
|
|||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-jetty-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
|
|
@ -92,7 +92,7 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
|
|||
AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext) request.getAttribute(AdapterDeploymentContext.class.getName());
|
||||
KeycloakSecurityContext ksc = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
if (ksc != null) {
|
||||
JettyHttpFacade facade = new JettyHttpFacade(request, null);
|
||||
JettyHttpFacade facade = new OIDCJettyHttpFacade(request, null);
|
||||
KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
|
||||
if (ksc instanceof RefreshableKeycloakSecurityContext) {
|
||||
((RefreshableKeycloakSecurityContext) ksc).logout(deployment);
|
||||
|
@ -229,7 +229,7 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
|
|||
log.trace("*** authenticate");
|
||||
}
|
||||
Request request = resolveRequest(req);
|
||||
JettyHttpFacade facade = new JettyHttpFacade(request, (HttpServletResponse) res);
|
||||
OIDCJettyHttpFacade facade = new OIDCJettyHttpFacade(request, (HttpServletResponse) res);
|
||||
KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
|
||||
if (deployment == null || !deployment.isConfigured()) {
|
||||
log.debug("*** deployment isn't configured return false");
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.eclipse.jetty.server.Request;
|
|||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.AdapterSessionStore;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.AdapterUtils;
|
||||
import org.keycloak.adapters.KeycloakAccount;
|
||||
|
@ -18,17 +19,18 @@ import javax.servlet.http.HttpSession;
|
|||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public abstract class AbstractJettySessionTokenStore implements AdapterTokenStore {
|
||||
public final static String __J_METHOD = "org.eclipse.jetty.security.HTTP_METHOD";
|
||||
public class JettySessionTokenStore implements AdapterTokenStore {
|
||||
|
||||
private static final Logger log = Logger.getLogger(AbstractJettySessionTokenStore.class);
|
||||
private static final Logger log = Logger.getLogger(JettySessionTokenStore.class);
|
||||
|
||||
private Request request;
|
||||
protected KeycloakDeployment deployment;
|
||||
protected AdapterSessionStore sessionStore;
|
||||
|
||||
public AbstractJettySessionTokenStore(Request request, KeycloakDeployment deployment) {
|
||||
public JettySessionTokenStore(Request request, KeycloakDeployment deployment, AdapterSessionStore sessionStore) {
|
||||
this.request = request;
|
||||
this.deployment = deployment;
|
||||
this.sessionStore = sessionStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -93,4 +95,14 @@ public abstract class AbstractJettySessionTokenStore implements AdapterTokenStor
|
|||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRequest() {
|
||||
sessionStore.saveRequest();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean restoreRequest() {
|
||||
return sessionStore.restoreRequest();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package org.keycloak.adapters.jetty.core;
|
||||
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class OIDCJettyHttpFacade extends JettyHttpFacade implements OIDCHttpFacade {
|
||||
|
||||
public OIDCJettyHttpFacade(org.eclipse.jetty.server.Request request, HttpServletResponse response) {
|
||||
super(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakSecurityContext getSecurityContext() {
|
||||
return (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
}
|
||||
|
||||
}
|
|
@ -38,6 +38,10 @@
|
|||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-jetty-core</artifactId>
|
||||
|
|
|
@ -3,8 +3,8 @@ package org.keycloak.adapters.jetty;
|
|||
import org.eclipse.jetty.security.authentication.FormAuthenticator;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractJettySessionTokenStore;
|
||||
import org.keycloak.adapters.AdapterSessionStore;
|
||||
import org.keycloak.adapters.jetty.core.JettyHttpFacade;
|
||||
import org.keycloak.util.MultivaluedHashMap;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
@ -13,12 +13,11 @@ import javax.servlet.http.HttpSession;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
|
||||
public class JettyAdapterSessionStore implements AdapterSessionStore {
|
||||
public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
|
||||
protected Request myRequest;
|
||||
|
||||
public JettySessionTokenStore(Request request, KeycloakDeployment deployment) {
|
||||
super(request, deployment);
|
||||
public JettyAdapterSessionStore(Request request) {
|
||||
this.myRequest = request; // for IDE/compilation purposes
|
||||
}
|
||||
|
||||
|
@ -43,7 +42,7 @@ public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
|
|||
if (myRequest.getQueryString() != null)
|
||||
buf.append("?").append(myRequest.getQueryString());
|
||||
if (j_uri.equals(buf.toString())) {
|
||||
String method = (String)session.getAttribute(__J_METHOD);
|
||||
String method = (String)session.getAttribute(JettyHttpFacade.__J_METHOD);
|
||||
myRequest.setMethod(method);
|
||||
MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
|
||||
if (j_post != null) {
|
||||
|
@ -57,7 +56,7 @@ public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
|
|||
restoreFormParameters(map, myRequest);
|
||||
}
|
||||
session.removeAttribute(FormAuthenticator.__J_URI);
|
||||
session.removeAttribute(__J_METHOD);
|
||||
session.removeAttribute(JettyHttpFacade.__J_METHOD);
|
||||
session.removeAttribute(FormAuthenticator.__J_POST);
|
||||
}
|
||||
return true;
|
||||
|
@ -76,7 +75,7 @@ public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
|
|||
if (myRequest.getQueryString() != null)
|
||||
buf.append("?").append(myRequest.getQueryString());
|
||||
session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
|
||||
session.setAttribute(__J_METHOD, myRequest.getMethod());
|
||||
session.setAttribute(JettyHttpFacade.__J_METHOD, myRequest.getMethod());
|
||||
|
||||
if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
|
||||
MultiMap<String> formParameters = extractFormParameters(myRequest);
|
|
@ -7,6 +7,7 @@ import org.eclipse.jetty.server.UserIdentity;
|
|||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
|
||||
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
|
@ -23,7 +24,7 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat
|
|||
|
||||
@Override
|
||||
public AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment) {
|
||||
return new JettySessionTokenStore(request, resolvedDeployment);
|
||||
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,8 +4,8 @@ import org.eclipse.jetty.http.HttpMethod;
|
|||
import org.eclipse.jetty.security.authentication.FormAuthenticator;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractJettySessionTokenStore;
|
||||
import org.keycloak.adapters.AdapterSessionStore;
|
||||
import org.keycloak.adapters.jetty.core.JettyHttpFacade;
|
||||
import org.keycloak.util.MultivaluedHashMap;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
@ -14,17 +14,15 @@ import javax.servlet.http.HttpSession;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
|
||||
public class JettyAdapterSessionStore implements AdapterSessionStore {
|
||||
public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
|
||||
protected Request myRequest;
|
||||
|
||||
public JettySessionTokenStore(Request request, KeycloakDeployment deployment) {
|
||||
super(request, deployment);
|
||||
public JettyAdapterSessionStore(Request request) {
|
||||
this.myRequest = request; // for IDE/compilation purposes
|
||||
}
|
||||
|
||||
protected MultiMap<String> extractFormParameters(Request base_request) {
|
||||
MultiMap<String> formParameters = new MultiMap<String>();
|
||||
base_request.extractParameters();
|
||||
return base_request.getParameters();
|
||||
}
|
||||
|
@ -44,7 +42,7 @@ public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
|
|||
if (myRequest.getQueryString() != null)
|
||||
buf.append("?").append(myRequest.getQueryString());
|
||||
if (j_uri.equals(buf.toString())) {
|
||||
String method = (String)session.getAttribute(__J_METHOD);
|
||||
String method = (String)session.getAttribute(JettyHttpFacade.__J_METHOD);
|
||||
myRequest.setMethod(HttpMethod.valueOf(method.toUpperCase()), method);
|
||||
MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
|
||||
if (j_post != null) {
|
||||
|
@ -58,7 +56,7 @@ public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
|
|||
restoreFormParameters(map, myRequest);
|
||||
}
|
||||
session.removeAttribute(FormAuthenticator.__J_URI);
|
||||
session.removeAttribute(__J_METHOD);
|
||||
session.removeAttribute(JettyHttpFacade.__J_METHOD);
|
||||
session.removeAttribute(FormAuthenticator.__J_POST);
|
||||
}
|
||||
return true;
|
||||
|
@ -77,7 +75,7 @@ public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
|
|||
if (myRequest.getQueryString() != null)
|
||||
buf.append("?").append(myRequest.getQueryString());
|
||||
session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
|
||||
session.setAttribute(__J_METHOD, myRequest.getMethod());
|
||||
session.setAttribute(JettyHttpFacade.__J_METHOD, myRequest.getMethod());
|
||||
|
||||
if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
|
||||
MultiMap<String> formParameters = extractFormParameters(myRequest);
|
|
@ -7,6 +7,7 @@ import org.eclipse.jetty.server.UserIdentity;
|
|||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
|
||||
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
|
@ -23,7 +24,7 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat
|
|||
|
||||
@Override
|
||||
public AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment) {
|
||||
return new JettySessionTokenStore(request, resolvedDeployment);
|
||||
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,8 +4,8 @@ import org.eclipse.jetty.http.HttpMethod;
|
|||
import org.eclipse.jetty.security.authentication.FormAuthenticator;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractJettySessionTokenStore;
|
||||
import org.keycloak.adapters.AdapterSessionStore;
|
||||
import org.keycloak.adapters.jetty.core.JettyHttpFacade;
|
||||
import org.keycloak.util.MultivaluedHashMap;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
@ -14,12 +14,11 @@ import javax.servlet.http.HttpSession;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
|
||||
public class JettyAdapterSessionStore implements AdapterSessionStore {
|
||||
public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
|
||||
protected Request myRequest;
|
||||
|
||||
public JettySessionTokenStore(Request request, KeycloakDeployment deployment) {
|
||||
super(request, deployment);
|
||||
public JettyAdapterSessionStore(Request request) {
|
||||
this.myRequest = request; // for IDE/compilation purposes
|
||||
}
|
||||
|
||||
|
@ -44,7 +43,7 @@ public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
|
|||
if (myRequest.getQueryString() != null)
|
||||
buf.append("?").append(myRequest.getQueryString());
|
||||
if (j_uri.equals(buf.toString())) {
|
||||
String method = (String)session.getAttribute(__J_METHOD);
|
||||
String method = (String)session.getAttribute(JettyHttpFacade.__J_METHOD);
|
||||
myRequest.setMethod(HttpMethod.valueOf(method.toUpperCase()), method);
|
||||
MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
|
||||
if (j_post != null) {
|
||||
|
@ -58,7 +57,7 @@ public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
|
|||
restoreFormParameters(map, myRequest);
|
||||
}
|
||||
session.removeAttribute(FormAuthenticator.__J_URI);
|
||||
session.removeAttribute(__J_METHOD);
|
||||
session.removeAttribute(JettyHttpFacade.__J_METHOD);
|
||||
session.removeAttribute(FormAuthenticator.__J_POST);
|
||||
}
|
||||
return true;
|
||||
|
@ -77,7 +76,7 @@ public class JettySessionTokenStore extends AbstractJettySessionTokenStore {
|
|||
if (myRequest.getQueryString() != null)
|
||||
buf.append("?").append(myRequest.getQueryString());
|
||||
session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
|
||||
session.setAttribute(__J_METHOD, myRequest.getMethod());
|
||||
session.setAttribute(JettyHttpFacade.__J_METHOD, myRequest.getMethod());
|
||||
|
||||
if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
|
||||
MultiMap<String> formParameters = extractFormParameters(myRequest);
|
|
@ -7,6 +7,7 @@ import org.eclipse.jetty.server.UserIdentity;
|
|||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
|
||||
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
|
@ -38,6 +39,6 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat
|
|||
|
||||
@Override
|
||||
public AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment) {
|
||||
return new JettySessionTokenStore(request, resolvedDeployment);
|
||||
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>jetty-adapter-spi</module>
|
||||
<module>jetty-core</module>
|
||||
<module>jetty8.1</module>
|
||||
<module>jetty9.2</module>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>adapter-spi</module>
|
||||
<module>adapter-core</module>
|
||||
<module>jaxrs-oauth-client</module>
|
||||
<module>servlet-oauth-client</module>
|
||||
|
@ -21,6 +22,7 @@
|
|||
<module>tomcat</module>
|
||||
<module>as7-eap6</module>
|
||||
<module>jetty</module>
|
||||
<module>undertow-adapter-spi</module>
|
||||
<module>undertow</module>
|
||||
<module>wildfly</module>
|
||||
<module>js</module>
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
|
|
@ -3,15 +3,13 @@ package org.keycloak.servlet;
|
|||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.HttpFacade;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
import org.keycloak.adapters.ServerRequest;
|
||||
import org.keycloak.enums.RelativeUrlsUsed;
|
||||
import org.keycloak.jose.jws.JWSInput;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.representations.IDToken;
|
||||
import org.keycloak.util.KeycloakUriBuilder;
|
||||
import org.keycloak.util.UriUtils;
|
||||
|
||||
import javax.security.cert.X509Certificate;
|
||||
import javax.servlet.http.Cookie;
|
||||
|
@ -167,7 +165,7 @@ public class ServletOAuthClient extends KeycloakDeploymentDelegateOAuthClient {
|
|||
}
|
||||
|
||||
|
||||
public static class ServletFacade implements HttpFacade {
|
||||
public static class ServletFacade implements OIDCHttpFacade {
|
||||
|
||||
private final HttpServletRequest servletRequest;
|
||||
|
||||
|
@ -184,6 +182,11 @@ public class ServletOAuthClient extends KeycloakDeploymentDelegateOAuthClient {
|
|||
public Request getRequest() {
|
||||
return new Request() {
|
||||
|
||||
@Override
|
||||
public String getFirstParam(String param) {
|
||||
return servletRequest.getParameter(param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return servletRequest.getMethod();
|
||||
|
|
4
integration/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfigResolver.java
Normal file → Executable file
4
integration/spring-boot/src/main/java/org/keycloak/adapters/springboot/KeycloakSpringBootConfigResolver.java
Normal file → Executable file
|
@ -1,8 +1,8 @@
|
|||
package org.keycloak.adapters.springboot;
|
||||
|
||||
import org.keycloak.adapters.HttpFacade;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.KeycloakDeploymentBuilder;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||
|
||||
public class KeycloakSpringBootConfigResolver implements org.keycloak.adapters.KeycloakConfigResolver {
|
||||
|
@ -12,7 +12,7 @@ public class KeycloakSpringBootConfigResolver implements org.keycloak.adapters.K
|
|||
private static AdapterConfig adapterConfig;
|
||||
|
||||
@Override
|
||||
public KeycloakDeployment resolve(HttpFacade.Request request) {
|
||||
public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
|
||||
if (keycloakDeployment != null) {
|
||||
return keycloakDeployment;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
|
8
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/SimpleHttpFacade.java
Normal file → Executable file
8
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/SimpleHttpFacade.java
Normal file → Executable file
|
@ -1,9 +1,7 @@
|
|||
package org.keycloak.adapters.springsecurity.facade;
|
||||
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.HttpFacade;
|
||||
import org.keycloak.adapters.springsecurity.facade.WrappedHttpServletRequest;
|
||||
import org.keycloak.adapters.springsecurity.facade.WrappedHttpServletResponse;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.util.Assert;
|
||||
|
@ -13,12 +11,12 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Simple {@link HttpFacade} wrapping an {@link HttpServletRequest} and {@link HttpServletResponse}.
|
||||
* Simple {@link org.keycloak.adapters.OIDCHttpFacade} wrapping an {@link HttpServletRequest} and {@link HttpServletResponse}.
|
||||
*
|
||||
* @author <a href="mailto:srossillo@smartling.com">Scott Rossillo</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class SimpleHttpFacade implements HttpFacade {
|
||||
public class SimpleHttpFacade implements OIDCHttpFacade {
|
||||
|
||||
private final HttpServletRequest request;
|
||||
private final HttpServletResponse response;
|
||||
|
|
5
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/WrappedHttpServletRequest.java
Normal file → Executable file
5
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/WrappedHttpServletRequest.java
Normal file → Executable file
|
@ -32,6 +32,11 @@ class WrappedHttpServletRequest implements Request {
|
|||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstParam(String param) {
|
||||
return request.getParameter(param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return request.getMethod();
|
||||
|
|
2
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/package-info.java
Normal file → Executable file
2
integration/spring-security/src/main/java/org/keycloak/adapters/springsecurity/facade/package-info.java
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
* Provides an {@link org.keycloak.adapters.HttpFacade} implementation.
|
||||
* Provides an {@link org.keycloak.adapters.OIDCHttpFacade} implementation.
|
||||
*/
|
||||
package org.keycloak.adapters.springsecurity.facade;
|
|
@ -2,10 +2,9 @@ package org.keycloak.adapters.springsecurity.token;
|
|||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.AdapterSessionStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -32,7 +31,7 @@ public class SpringSecurityAdapterTokenStoreFactoryTest {
|
|||
|
||||
@Test
|
||||
public void testCreateAdapterTokenStore() throws Exception {
|
||||
AdapterTokenStore store = factory.createAdapterTokenStore(deployment, request);
|
||||
AdapterSessionStore store = factory.createAdapterTokenStore(deployment, request);
|
||||
assertNotNull(store);
|
||||
assertTrue(store instanceof SpringSecurityTokenStore);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>tomcat-adapter-spi</module>
|
||||
<module>tomcat-core</module>
|
||||
<module>tomcat6</module>
|
||||
<module>tomcat7</module>
|
||||
|
|
69
integration/tomcat/tomcat-adapter-spi/pom.xml
Executable file
69
integration/tomcat/tomcat-adapter-spi/pom.xml
Executable file
|
@ -0,0 +1,69 @@
|
|||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.6.0.Final-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-tomcat-adapter-spi</artifactId>
|
||||
<name>Keycloak Tomcat Adapter SPI</name>
|
||||
<properties>
|
||||
<!-- <tomcat.version>8.0.14</tomcat.version> -->
|
||||
<!-- <tomcat.version>7.0.52</tomcat.version> -->
|
||||
<tomcat.version>6.0.41</tomcat.version>
|
||||
</properties>
|
||||
<description />
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<version>${jboss.logging.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>tomcat-servlet-api</artifactId>
|
||||
<version>${tomcat.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>catalina</artifactId>
|
||||
<version>${tomcat.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -1,6 +1,5 @@
|
|||
package org.keycloak.adapters.tomcat;
|
||||
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.HttpFacade;
|
||||
import org.keycloak.util.MultivaluedHashMap;
|
||||
import org.keycloak.util.ServerCookie;
|
||||
|
@ -26,6 +25,30 @@ public class CatalinaHttpFacade implements HttpFacade {
|
|||
protected ResponseFacade responseFacade = new ResponseFacade();
|
||||
protected MultivaluedHashMap<String, String> queryParameters;
|
||||
|
||||
public CatalinaHttpFacade(HttpServletResponse response, org.apache.catalina.connector.Request request) {
|
||||
this.response = response;
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request getRequest() {
|
||||
return requestFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response getResponse() {
|
||||
return responseFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getCertificateChain() {
|
||||
throw new IllegalStateException("Not supported yet");
|
||||
}
|
||||
|
||||
public boolean isEnded() {
|
||||
return responseFacade.isEnded();
|
||||
}
|
||||
|
||||
protected class RequestFacade implements Request {
|
||||
@Override
|
||||
public String getURI() {
|
||||
|
@ -41,6 +64,11 @@ public class CatalinaHttpFacade implements HttpFacade {
|
|||
return request.isSecure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstParam(String param) {
|
||||
return request.getParameter(param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParamValue(String paramName) {
|
||||
if (queryParameters == null) {
|
||||
|
@ -157,33 +185,4 @@ public class CatalinaHttpFacade implements HttpFacade {
|
|||
return ended;
|
||||
}
|
||||
}
|
||||
|
||||
public CatalinaHttpFacade(org.apache.catalina.connector.Request request, HttpServletResponse response) {
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request getRequest() {
|
||||
return requestFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response getResponse() {
|
||||
return responseFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakSecurityContext getSecurityContext() {
|
||||
return (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getCertificateChain() {
|
||||
throw new IllegalStateException("Not supported yet");
|
||||
}
|
||||
|
||||
public boolean isEnded() {
|
||||
return responseFacade.isEnded();
|
||||
}
|
||||
}
|
|
@ -28,6 +28,14 @@
|
|||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-tomcat-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
|
|
|
@ -5,13 +5,9 @@ import org.apache.catalina.Lifecycle;
|
|||
import org.apache.catalina.LifecycleEvent;
|
||||
import org.apache.catalina.LifecycleListener;
|
||||
import org.apache.catalina.Manager;
|
||||
import org.apache.catalina.authenticator.Constants;
|
||||
import org.apache.catalina.authenticator.FormAuthenticator;
|
||||
import org.apache.catalina.authenticator.SavedRequest;
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.Response;
|
||||
import org.apache.catalina.deploy.LoginConfig;
|
||||
import org.apache.tomcat.util.buf.ByteChunk;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.constants.AdapterConstants;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
|
@ -28,15 +24,12 @@ import org.keycloak.enums.TokenStore;
|
|||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.keycloak.adapters.KeycloakConfigResolver;
|
||||
|
@ -71,7 +64,7 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
|
|||
protected void logoutInternal(Request request) {
|
||||
KeycloakSecurityContext ksc = (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
if (ksc != null) {
|
||||
CatalinaHttpFacade facade = new CatalinaHttpFacade(request, null);
|
||||
CatalinaHttpFacade facade = new OIDCCatalinaHttpFacade(request, null);
|
||||
KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
|
||||
if (ksc instanceof RefreshableKeycloakSecurityContext) {
|
||||
((RefreshableKeycloakSecurityContext) ksc).logout(deployment);
|
||||
|
@ -164,7 +157,7 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
|
|||
@Override
|
||||
public void invoke(Request request, Response response) throws IOException, ServletException {
|
||||
try {
|
||||
CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response);
|
||||
CatalinaHttpFacade facade = new OIDCCatalinaHttpFacade(request, response);
|
||||
Manager sessionManager = request.getContext().getManager();
|
||||
CatalinaUserSessionManagementWrapper sessionManagementWrapper = new CatalinaUserSessionManagementWrapper(userSessionManagement, sessionManager);
|
||||
PreAuthActionsHandler handler = new PreAuthActionsHandler(sessionManagementWrapper, deploymentContext, facade);
|
||||
|
@ -181,7 +174,7 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
|
|||
protected abstract boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException;
|
||||
|
||||
protected boolean authenticateInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
|
||||
CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response);
|
||||
CatalinaHttpFacade facade = new OIDCCatalinaHttpFacade(request, response);
|
||||
KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
|
||||
if (deployment == null || !deployment.isConfigured()) {
|
||||
return false;
|
||||
|
|
|
@ -39,10 +39,10 @@ public class AuthenticatedActionsValve extends ValveBase {
|
|||
@Override
|
||||
public void invoke(Request request, Response response) throws IOException, ServletException {
|
||||
log.debugv("AuthenticatedActionsValve.invoke {0}", request.getRequestURI());
|
||||
CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response);
|
||||
CatalinaHttpFacade facade = new OIDCCatalinaHttpFacade(request, response);
|
||||
KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
|
||||
if (deployment != null && deployment.isConfigured()) {
|
||||
AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deployment, new CatalinaHttpFacade(request, response));
|
||||
AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deployment, new OIDCCatalinaHttpFacade(request, response));
|
||||
if (handler.handledRequest()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package org.keycloak.adapters.tomcat;
|
||||
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.keycloak.adapters.AdapterSessionStore;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CatalinaAdapterSessionStore implements AdapterSessionStore {
|
||||
protected Request request;
|
||||
protected AbstractKeycloakAuthenticatorValve valve;
|
||||
|
||||
public CatalinaAdapterSessionStore(Request request, AbstractKeycloakAuthenticatorValve valve) {
|
||||
this.request = request;
|
||||
this.valve = valve;
|
||||
}
|
||||
|
||||
public void saveRequest() {
|
||||
try {
|
||||
valve.keycloakSaveRequest(request);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean restoreRequest() {
|
||||
return valve.keycloakRestoreRequest(request);
|
||||
}
|
||||
}
|
|
@ -19,26 +19,23 @@ import java.util.logging.Logger;
|
|||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class CatalinaSessionTokenStore implements AdapterTokenStore {
|
||||
public class CatalinaSessionTokenStore extends CatalinaAdapterSessionStore implements AdapterTokenStore {
|
||||
|
||||
private static final Logger log = Logger.getLogger("" + CatalinaSessionTokenStore.class);
|
||||
|
||||
private Request request;
|
||||
private KeycloakDeployment deployment;
|
||||
private CatalinaUserSessionManagement sessionManagement;
|
||||
protected GenericPrincipalFactory principalFactory;
|
||||
protected AbstractKeycloakAuthenticatorValve valve;
|
||||
|
||||
|
||||
public CatalinaSessionTokenStore(Request request, KeycloakDeployment deployment,
|
||||
CatalinaUserSessionManagement sessionManagement,
|
||||
GenericPrincipalFactory principalFactory,
|
||||
AbstractKeycloakAuthenticatorValve valve) {
|
||||
this.request = request;
|
||||
super(request, valve);
|
||||
this.deployment = deployment;
|
||||
this.sessionManagement = sessionManagement;
|
||||
this.principalFactory = principalFactory;
|
||||
this.valve = valve;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -169,17 +166,4 @@ public class CatalinaSessionTokenStore implements AdapterTokenStore {
|
|||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveRequest() {
|
||||
try {
|
||||
valve.keycloakSaveRequest(request);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean restoreRequest() {
|
||||
return valve.keycloakRestoreRequest(request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package org.keycloak.adapters.tomcat;
|
||||
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class OIDCCatalinaHttpFacade extends CatalinaHttpFacade implements OIDCHttpFacade{
|
||||
|
||||
public OIDCCatalinaHttpFacade(org.apache.catalina.connector.Request request, HttpServletResponse response) {
|
||||
super(response, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakSecurityContext getSecurityContext() {
|
||||
return (KeycloakSecurityContext)request.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
}
|
||||
|
||||
}
|
65
integration/undertow-adapter-spi/pom.xml
Executable file
65
integration/undertow-adapter-spi/pom.xml
Executable file
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.6.0.Final-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-undertow-adapter-spi</artifactId>
|
||||
<name>Keycloak Undertow Integration</name>
|
||||
<description/>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<version>${jboss.logging.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-servlet</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,39 @@
|
|||
package org.keycloak.adapters.undertow;
|
||||
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.servlet.handlers.ServletRequestContext;
|
||||
import org.keycloak.adapters.HttpFacade;
|
||||
|
||||
import javax.security.cert.X509Certificate;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ServletHttpFacade extends UndertowHttpFacade {
|
||||
protected HttpServletRequest request;
|
||||
protected HttpServletResponse response;
|
||||
|
||||
public ServletHttpFacade(HttpServerExchange exchange) {
|
||||
super(exchange);
|
||||
final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
|
||||
request = (HttpServletRequest)servletRequestContext.getServletRequest();
|
||||
}
|
||||
|
||||
protected class RequestFacade extends UndertowHttpFacade.RequestFacade {
|
||||
@Override
|
||||
public String getFirstParam(String param) {
|
||||
return request.getParameter(param);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request getRequest() {
|
||||
return new RequestFacade();
|
||||
}
|
||||
}
|
|
@ -1,27 +1,9 @@
|
|||
/*
|
||||
* Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
|
||||
* as indicated by the @author tags. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package org.keycloak.adapters.undertow;
|
||||
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.server.handlers.CookieImpl;
|
||||
import io.undertow.util.AttachmentKey;
|
||||
import io.undertow.util.Headers;
|
||||
import io.undertow.util.HttpString;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.HttpFacade;
|
||||
import org.keycloak.util.KeycloakUriBuilder;
|
||||
|
||||
|
@ -40,12 +22,35 @@ import java.util.Map;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class UndertowHttpFacade implements HttpFacade {
|
||||
public static final AttachmentKey<KeycloakSecurityContext> KEYCLOAK_SECURITY_CONTEXT_KEY = AttachmentKey.create(KeycloakSecurityContext.class);
|
||||
|
||||
protected HttpServerExchange exchange;
|
||||
protected RequestFacade requestFacade = new RequestFacade();
|
||||
protected ResponseFacade responseFacade = new ResponseFacade();
|
||||
|
||||
public UndertowHttpFacade(HttpServerExchange exchange) {
|
||||
this.exchange = exchange;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request getRequest() {
|
||||
return requestFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response getResponse() {
|
||||
return responseFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getCertificateChain() {
|
||||
X509Certificate[] chain = new X509Certificate[0];
|
||||
try {
|
||||
chain = exchange.getConnection().getSslSessionInfo().getPeerCertificateChain();
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
return chain;
|
||||
}
|
||||
|
||||
protected class RequestFacade implements Request {
|
||||
@Override
|
||||
public String getURI() {
|
||||
|
@ -61,6 +66,11 @@ public class UndertowHttpFacade implements HttpFacade {
|
|||
return protocol.equalsIgnoreCase("https");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstParam(String param) {
|
||||
throw new RuntimeException("Not implemented yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryParamValue(String param) {
|
||||
Map<String,Deque<String>> queryParameters = exchange.getQueryParameters();
|
||||
|
@ -178,34 +188,4 @@ public class UndertowHttpFacade implements HttpFacade {
|
|||
exchange.endExchange();
|
||||
}
|
||||
}
|
||||
|
||||
public UndertowHttpFacade(HttpServerExchange exchange) {
|
||||
this.exchange = exchange;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request getRequest() {
|
||||
return requestFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response getResponse() {
|
||||
return responseFacade;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakSecurityContext getSecurityContext() {
|
||||
return exchange.getAttachment(KEYCLOAK_SECURITY_CONTEXT_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getCertificateChain() {
|
||||
X509Certificate[] chain = new X509Certificate[0];
|
||||
try {
|
||||
chain = exchange.getConnection().getSslSessionInfo().getPeerCertificateChain();
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
return chain;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue