use of org.keycloak.models.KeyManager in project keycloak by keycloak.
the class SamlProtocol method authenticated.
@Override
public Response authenticated(AuthenticationSessionModel authSession, UserSessionModel userSession, ClientSessionContext clientSessionCtx) {
AuthenticatedClientSessionModel clientSession = clientSessionCtx.getClientSession();
ClientModel client = clientSession.getClient();
SamlClient samlClient = new SamlClient(client);
String requestID = authSession.getClientNote(SAML_REQUEST_ID);
String relayState = authSession.getClientNote(GeneralConstants.RELAY_STATE);
String redirectUri = authSession.getRedirectUri();
String responseIssuer = getResponseIssuer(realm);
String nameIdFormat = getNameIdFormat(samlClient, authSession);
int assertionLifespan = samlClient.getAssertionLifespan();
SAML2LoginResponseBuilder builder = new SAML2LoginResponseBuilder();
builder.requestID(requestID).destination(redirectUri).issuer(responseIssuer).assertionExpiration(assertionLifespan <= 0 ? realm.getAccessCodeLifespan() : assertionLifespan).subjectExpiration(assertionLifespan <= 0 ? realm.getAccessTokenLifespan() : assertionLifespan).sessionExpiration(realm.getSsoSessionMaxLifespan()).requestIssuer(clientSession.getClient().getClientId()).authMethod(JBossSAMLURIConstants.AC_UNSPECIFIED.get());
String sessionIndex = SamlSessionUtils.getSessionIndex(clientSession);
builder.sessionIndex(sessionIndex);
if (!samlClient.includeAuthnStatement()) {
builder.disableAuthnStatement(true);
}
builder.includeOneTimeUseCondition(samlClient.includeOneTimeUseCondition());
List<ProtocolMapperProcessor<SAMLAttributeStatementMapper>> attributeStatementMappers = new LinkedList<>();
List<ProtocolMapperProcessor<SAMLLoginResponseMapper>> loginResponseMappers = new LinkedList<>();
AtomicReference<ProtocolMapperProcessor<SAMLRoleListMapper>> roleListMapper = new AtomicReference<>(null);
List<ProtocolMapperProcessor<SAMLNameIdMapper>> samlNameIdMappers = new LinkedList<>();
ProtocolMapperUtils.getSortedProtocolMappers(session, clientSessionCtx).forEach(entry -> {
ProtocolMapperModel mapping = entry.getKey();
ProtocolMapper mapper = entry.getValue();
if (mapper instanceof SAMLAttributeStatementMapper) {
attributeStatementMappers.add(new ProtocolMapperProcessor<>((SAMLAttributeStatementMapper) mapper, mapping));
}
if (mapper instanceof SAMLLoginResponseMapper) {
loginResponseMappers.add(new ProtocolMapperProcessor<>((SAMLLoginResponseMapper) mapper, mapping));
}
if (mapper instanceof SAMLRoleListMapper) {
roleListMapper.set(new ProtocolMapperProcessor<>((SAMLRoleListMapper) mapper, mapping));
}
if (mapper instanceof SAMLNameIdMapper) {
samlNameIdMappers.add(new ProtocolMapperProcessor<>((SAMLNameIdMapper) mapper, mapping));
}
});
Document samlDocument = null;
ResponseType samlModel = null;
KeyManager keyManager = session.keys();
KeyManager.ActiveRsaKey keys = keyManager.getActiveRsaKey(realm);
boolean postBinding = isPostBinding(authSession);
String keyName = samlClient.getXmlSigKeyInfoKeyNameTransformer().getKeyName(keys.getKid(), keys.getCertificate());
String nameId = getSAMLNameId(samlNameIdMappers, nameIdFormat, session, userSession, clientSession);
if (nameId == null) {
return samlErrorMessage(null, samlClient, isPostBinding(authSession), redirectUri, JBossSAMLURIConstants.STATUS_INVALID_NAMEIDPOLICY, relayState);
}
builder.nameIdentifier(nameIdFormat, nameId);
// save NAME_ID and format in clientSession as they may be persistent or
// transient or email and not username
// we'll need to send this back on a logout
clientSession.setNote(SAML_NAME_ID, nameId);
clientSession.setNote(SAML_NAME_ID_FORMAT, nameIdFormat);
try {
if ((!postBinding) && samlClient.requiresRealmSignature() && samlClient.addExtensionsElementWithKeyInfo()) {
builder.addExtension(new KeycloakKeySamlExtensionGenerator(keyName));
}
samlModel = builder.buildModel();
final AttributeStatementType attributeStatement = populateAttributeStatements(attributeStatementMappers, session, userSession, clientSession);
populateRoles(roleListMapper.get(), session, userSession, clientSessionCtx, attributeStatement);
// SAML Spec 2.7.3 AttributeStatement must contain one or more Attribute or EncryptedAttribute
if (attributeStatement.getAttributes().size() > 0) {
AssertionType assertion = samlModel.getAssertions().get(0).getAssertion();
assertion.addStatement(attributeStatement);
}
samlModel = transformLoginResponse(loginResponseMappers, samlModel, session, userSession, clientSessionCtx);
} catch (Exception e) {
logger.error("failed", e);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_TO_PROCESS_RESPONSE);
}
JaxrsSAML2BindingBuilder bindingBuilder = new JaxrsSAML2BindingBuilder(session);
bindingBuilder.relayState(relayState);
if ("true".equals(clientSession.getNote(JBossSAMLURIConstants.SAML_HTTP_ARTIFACT_BINDING.get()))) {
try {
return buildArtifactAuthenticatedResponse(clientSession, redirectUri, samlModel, bindingBuilder);
} catch (Exception e) {
logger.error("failed", e);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_TO_PROCESS_RESPONSE);
}
}
if (samlClient.requiresRealmSignature() || samlClient.requiresAssertionSignature()) {
String canonicalization = samlClient.getCanonicalizationMethod();
if (canonicalization != null) {
bindingBuilder.canonicalizationMethod(canonicalization);
}
bindingBuilder.signatureAlgorithm(samlClient.getSignatureAlgorithm()).signWith(keyName, keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate());
if (samlClient.requiresRealmSignature())
bindingBuilder.signDocument();
if (samlClient.requiresAssertionSignature())
bindingBuilder.signAssertions();
}
if (samlClient.requiresEncryption()) {
PublicKey publicKey = null;
try {
publicKey = SamlProtocolUtils.getEncryptionKey(client);
} catch (Exception e) {
logger.error("failed", e);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_TO_PROCESS_RESPONSE);
}
bindingBuilder.encrypt(publicKey);
}
try {
samlDocument = builder.buildDocument(samlModel);
return buildAuthenticatedResponse(clientSession, redirectUri, samlDocument, bindingBuilder);
} catch (Exception e) {
logger.error("failed", e);
return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_TO_PROCESS_RESPONSE);
}
}
use of org.keycloak.models.KeyManager in project keycloak by keycloak.
the class ClientAttributeCertificateResource method getKeystore.
private byte[] getKeystore(KeyStoreConfig config, String privatePem, String certPem) {
try {
String format = config.getFormat();
KeyStore keyStore;
if (format.equals("JKS"))
keyStore = KeyStore.getInstance("JKS");
else
keyStore = KeyStore.getInstance(format, "BC");
keyStore.load(null, null);
String keyAlias = config.getKeyAlias();
if (keyAlias == null)
keyAlias = client.getClientId();
if (privatePem != null) {
PrivateKey privateKey = PemUtils.decodePrivateKey(privatePem);
X509Certificate clientCert = PemUtils.decodeCertificate(certPem);
Certificate[] chain = { clientCert };
keyStore.setKeyEntry(keyAlias, privateKey, config.getKeyPassword().trim().toCharArray(), chain);
} else {
X509Certificate clientCert = PemUtils.decodeCertificate(certPem);
keyStore.setCertificateEntry(keyAlias, clientCert);
}
if (config.isRealmCertificate() == null || config.isRealmCertificate().booleanValue()) {
KeyManager keys = session.keys();
String kid = keys.getActiveRsaKey(realm).getKid();
Certificate certificate = keys.getRsaCertificate(realm, kid);
String certificateAlias = config.getRealmAlias();
if (certificateAlias == null)
certificateAlias = realm.getName();
keyStore.setCertificateEntry(certificateAlias, certificate);
}
ByteArrayOutputStream stream = new ByteArrayOutputStream();
keyStore.store(stream, config.getStorePassword().trim().toCharArray());
stream.flush();
stream.close();
byte[] rtn = stream.toByteArray();
return rtn;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
use of org.keycloak.models.KeyManager in project keycloak by keycloak.
the class SamlProtocol method samlErrorMessage.
private Response samlErrorMessage(AuthenticationSessionModel authSession, SamlClient samlClient, boolean isPostBinding, String destination, JBossSAMLURIConstants statusDetail, String relayState) {
JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder(session).relayState(relayState);
SAML2ErrorResponseBuilder builder = new SAML2ErrorResponseBuilder().destination(destination).issuer(getResponseIssuer(realm)).status(statusDetail.get());
KeyManager keyManager = session.keys();
if (samlClient.requiresRealmSignature()) {
KeyManager.ActiveRsaKey keys = keyManager.getActiveRsaKey(realm);
String keyName = samlClient.getXmlSigKeyInfoKeyNameTransformer().getKeyName(keys.getKid(), keys.getCertificate());
String canonicalization = samlClient.getCanonicalizationMethod();
if (canonicalization != null) {
binding.canonicalizationMethod(canonicalization);
}
binding.signatureAlgorithm(samlClient.getSignatureAlgorithm()).signWith(keyName, keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate()).signDocument();
}
try {
// There is no support for encrypting status messages in SAML.
// Only assertions, attributes, base ID and name ID can be encrypted
// See Chapter 6 of saml-core-2.0-os.pdf
Document document = builder.buildDocument();
return buildErrorResponse(isPostBinding, destination, binding, document);
} catch (Exception e) {
return ErrorPage.error(session, authSession, Response.Status.BAD_REQUEST, Messages.FAILED_TO_PROCESS_RESPONSE);
}
}
use of org.keycloak.models.KeyManager in project keycloak by keycloak.
the class SamlService method artifactResponseMessage.
private Response artifactResponseMessage(ArtifactResolveType artifactResolveMessage, Document artifactResponseDocument, ClientModel clientModel) throws ProcessingException, ConfigurationException {
// Add "inResponseTo" to artifactResponse
if (artifactResolveMessage.getID() != null && !artifactResolveMessage.getID().trim().isEmpty()) {
Element artifactResponseElement = artifactResponseDocument.getDocumentElement();
artifactResponseElement.setAttribute("InResponseTo", artifactResolveMessage.getID());
}
JaxrsSAML2BindingBuilder bindingBuilder = new JaxrsSAML2BindingBuilder(session);
if (clientModel != null) {
SamlClient samlClient = new SamlClient(clientModel);
// Sign document/assertion if necessary, necessary to do this here, as the "inResponseTo" can only be set at this point
if (samlClient.requiresRealmSignature() || samlClient.requiresAssertionSignature()) {
KeyManager keyManager = session.keys();
KeyManager.ActiveRsaKey keys = keyManager.getActiveRsaKey(realm);
String keyName = samlClient.getXmlSigKeyInfoKeyNameTransformer().getKeyName(keys.getKid(), keys.getCertificate());
String canonicalization = samlClient.getCanonicalizationMethod();
if (canonicalization != null) {
bindingBuilder.canonicalizationMethod(canonicalization);
}
bindingBuilder.signatureAlgorithm(samlClient.getSignatureAlgorithm()).signWith(keyName, keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate());
if (samlClient.requiresRealmSignature())
bindingBuilder.signDocument();
if (samlClient.requiresAssertionSignature())
bindingBuilder.signAssertions();
}
// Encrypt assertion if client requires it
if (samlClient.requiresEncryption()) {
PublicKey publicKey = null;
try {
publicKey = SamlProtocolUtils.getEncryptionKey(clientModel);
} catch (Exception e) {
logger.error("Failed to obtain encryption key for client", e);
return emptyArtifactResponseMessage(artifactResolveMessage, null);
}
bindingBuilder.encrypt(publicKey);
}
}
bindingBuilder.postBinding(artifactResponseDocument);
Soap.SoapMessageBuilder messageBuilder = Soap.createMessage();
messageBuilder.addToBody(artifactResponseDocument);
if (logger.isDebugEnabled()) {
String artifactResponse = DocumentUtil.asString(artifactResponseDocument);
logger.debugf("Sending artifactResponse message for artifact %s. Message: \n %s", artifactResolveMessage.getArtifact(), artifactResponse);
}
return messageBuilder.build();
}
Aggregations