use of org.keycloak.dom.saml.v2.assertion.AssertionType in project keycloak by keycloak.
the class AbstractSamlAuthenticationHandler method handleLoginResponse.
protected AuthOutcome handleLoginResponse(SAMLDocumentHolder responseHolder, boolean postBinding, OnSessionCreated onCreateSession) {
if (!sessionStore.isLoggingIn()) {
log.warn("Adapter obtained LoginResponse, however containers session is not aware of sending any request. " + "This may be because the session cookies created by container are not properly configured " + "with SameSite settings. Refer to KEYCLOAK-14103 for more details.");
}
final ResponseType responseType = (ResponseType) responseHolder.getSamlObject();
AssertionType assertion = null;
if (!isSuccessfulSamlResponse(responseType) || responseType.getAssertions() == null || responseType.getAssertions().isEmpty()) {
return failed(createAuthChallenge403(responseType));
}
try {
assertion = AssertionUtil.getAssertion(responseHolder, responseType, deployment.getDecryptionKey());
ConditionsValidator.Builder cvb = new ConditionsValidator.Builder(assertion.getID(), assertion.getConditions(), destinationValidator);
try {
cvb.clockSkewInMillis(deployment.getIDP().getAllowedClockSkew());
cvb.addAllowedAudience(URI.create(deployment.getEntityID()));
if (responseType.getDestination() != null) {
// getDestination has been validated to match request URL already so it matches SAML endpoint
cvb.addAllowedAudience(URI.create(responseType.getDestination()));
}
} catch (IllegalArgumentException ex) {
// warning has been already emitted in DeploymentBuilder
}
if (!cvb.build().isValid()) {
return initiateLogin();
}
} catch (Exception e) {
log.error("Error extracting SAML assertion: " + e.getMessage());
return failed(CHALLENGE_EXTRACTION_FAILURE);
}
Element assertionElement = null;
if (deployment.getIDP().getSingleSignOnService().validateAssertionSignature()) {
try {
assertionElement = getAssertionFromResponse(responseHolder);
if (!AssertionUtil.isSignatureValid(assertionElement, deployment.getIDP().getSignatureValidationKeyLocator())) {
log.error("Failed to verify saml assertion signature");
return failed(CHALLENGE_INVALID_SIGNATURE);
}
} catch (Exception e) {
log.error("Error processing validation of SAML assertion: " + e.getMessage());
return failed(CHALLENGE_EXTRACTION_FAILURE);
}
}
SubjectType subject = assertion.getSubject();
SubjectType.STSubType subType = subject.getSubType();
NameIDType subjectNameID = subType == null ? null : (NameIDType) subType.getBaseID();
String principalName = subjectNameID == null ? null : subjectNameID.getValue();
Set<String> roles = new HashSet<>();
MultivaluedHashMap<String, String> attributes = new MultivaluedHashMap<>();
MultivaluedHashMap<String, String> friendlyAttributes = new MultivaluedHashMap<>();
Set<StatementAbstractType> statements = assertion.getStatements();
for (StatementAbstractType statement : statements) {
if (statement instanceof AttributeStatementType) {
AttributeStatementType attributeStatement = (AttributeStatementType) statement;
List<AttributeStatementType.ASTChoiceType> attList = attributeStatement.getAttributes();
for (AttributeStatementType.ASTChoiceType obj : attList) {
AttributeType attr = obj.getAttribute();
if (isRole(attr)) {
List<Object> attributeValues = attr.getAttributeValue();
if (attributeValues != null) {
for (Object attrValue : attributeValues) {
String role = getAttributeValue(attrValue);
log.debugv("Add role: {0}", role);
roles.add(role);
}
}
} else {
List<Object> attributeValues = attr.getAttributeValue();
if (attributeValues != null) {
for (Object attrValue : attributeValues) {
String value = getAttributeValue(attrValue);
if (attr.getName() != null) {
attributes.add(attr.getName(), value);
}
if (attr.getFriendlyName() != null) {
friendlyAttributes.add(attr.getFriendlyName(), value);
}
}
}
}
}
}
}
if (deployment.getPrincipalNamePolicy() == SamlDeployment.PrincipalNamePolicy.FROM_ATTRIBUTE) {
if (deployment.getPrincipalAttributeName() != null) {
String attribute = attributes.getFirst(deployment.getPrincipalAttributeName());
if (attribute != null)
principalName = attribute;
else {
attribute = friendlyAttributes.getFirst(deployment.getPrincipalAttributeName());
if (attribute != null)
principalName = attribute;
}
}
}
// use the configured role mappings provider to map roles if necessary.
if (deployment.getRoleMappingsProvider() != null) {
roles = deployment.getRoleMappingsProvider().map(principalName, roles);
}
// roles should also be there as regular attributes
// this mainly required for elytron and its ABAC nature
attributes.put(DEFAULT_ROLE_ATTRIBUTE_NAME, new ArrayList<>(roles));
AuthnStatementType authn = null;
for (Object statement : assertion.getStatements()) {
if (statement instanceof AuthnStatementType) {
authn = (AuthnStatementType) statement;
break;
}
}
URI nameFormat = subjectNameID == null ? null : subjectNameID.getFormat();
String nameFormatString = nameFormat == null ? JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get() : nameFormat.toString();
if (deployment.isKeepDOMAssertion() && assertionElement == null) {
// obtain the assertion from the response to add the DOM document to the principal
assertionElement = getAssertionFromResponseNoException(responseHolder);
}
final SamlPrincipal principal = new SamlPrincipal(assertion, deployment.isKeepDOMAssertion() ? getAssertionDocumentFromElement(assertionElement) : null, principalName, principalName, nameFormatString, attributes, friendlyAttributes);
final String sessionIndex = authn == null ? null : authn.getSessionIndex();
final XMLGregorianCalendar sessionNotOnOrAfter = authn == null ? null : authn.getSessionNotOnOrAfter();
SamlSession account = new SamlSession(principal, roles, sessionIndex, sessionNotOnOrAfter);
sessionStore.saveAccount(account);
onCreateSession.onSessionCreated(account);
// redirect to original request, it will be restored
String redirectUri = sessionStore.getRedirectUri();
if (redirectUri != null) {
facade.getResponse().setHeader("Location", redirectUri);
facade.getResponse().setStatus(302);
facade.getResponse().end();
} else {
log.debug("IDP initiated invocation");
}
log.debug("AUTHENTICATED authn");
return AuthOutcome.AUTHENTICATED;
}
use of org.keycloak.dom.saml.v2.assertion.AssertionType in project keycloak by keycloak.
the class SAMLDataMarshaller method serialize.
@Override
public String serialize(Object obj) {
// Lame impl, but hopefully sufficient for now. See if something better is needed...
if (obj.getClass().getName().startsWith("org.keycloak.dom.saml")) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
if (obj instanceof ResponseType) {
ResponseType responseType = (ResponseType) obj;
SAMLResponseWriter samlWriter = new SAMLResponseWriter(StaxUtil.getXMLStreamWriter(bos));
samlWriter.write(responseType);
} else if (obj instanceof AssertionType) {
AssertionType assertion = (AssertionType) obj;
SAMLAssertionWriter samlWriter = new SAMLAssertionWriter(StaxUtil.getXMLStreamWriter(bos));
samlWriter.write(assertion);
} else if (obj instanceof AuthnStatementType) {
AuthnStatementType authnStatement = (AuthnStatementType) obj;
SAMLAssertionWriter samlWriter = new SAMLAssertionWriter(StaxUtil.getXMLStreamWriter(bos));
samlWriter.write(authnStatement, true);
} else if (obj instanceof ArtifactResponseType) {
ArtifactResponseType artifactResponseType = (ArtifactResponseType) obj;
SAMLResponseWriter samlWriter = new SAMLResponseWriter(StaxUtil.getXMLStreamWriter(bos));
samlWriter.write(artifactResponseType);
} else {
throw new IllegalArgumentException("Don't know how to serialize object of type " + obj.getClass().getName());
}
} catch (ProcessingException pe) {
throw new RuntimeException(pe);
}
return new String(bos.toByteArray(), GeneralConstants.SAML_CHARSET);
} else {
return super.serialize(obj);
}
}
use of org.keycloak.dom.saml.v2.assertion.AssertionType in project keycloak by keycloak.
the class SAMLIdentityProvider method authenticationFinished.
@Override
public void authenticationFinished(AuthenticationSessionModel authSession, BrokeredIdentityContext context) {
ResponseType responseType = (ResponseType) context.getContextData().get(SAMLEndpoint.SAML_LOGIN_RESPONSE);
AssertionType assertion = (AssertionType) context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
SubjectType subject = assertion.getSubject();
SubjectType.STSubType subType = subject.getSubType();
if (subType != null) {
NameIDType subjectNameID = (NameIDType) subType.getBaseID();
authSession.setUserSessionNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT_NAMEID, subjectNameID.serializeAsString());
}
AuthnStatementType authn = (AuthnStatementType) context.getContextData().get(SAMLEndpoint.SAML_AUTHN_STATEMENT);
if (authn != null && authn.getSessionIndex() != null) {
authSession.setUserSessionNote(SAMLEndpoint.SAML_FEDERATED_SESSION_INDEX, authn.getSessionIndex());
}
}
use of org.keycloak.dom.saml.v2.assertion.AssertionType in project keycloak by keycloak.
the class SAML2Response method createResponseType.
/**
* Create a ResponseType
*
* <b>NOTE:</b>: The PicketLink STS is used to issue/update the assertion
*
* If you want to control over the assertion being issued, then use
* {@link #createResponseType(String, SPInfoHolder, IDPInfoHolder, IssuerInfoHolder, AssertionType)}
*
* @param ID id of the response
* @param sp holder with the information about the Service Provider
* @param idp holder with the information on the Identity Provider
* @param issuerInfo holder with information on the issuer
*
* @return
*
* @throws ConfigurationException
* @throws ProcessingException
*/
public ResponseType createResponseType(String ID, SPInfoHolder sp, IDPInfoHolder idp, IssuerInfoHolder issuerInfo) throws ProcessingException {
String responseDestinationURI = sp.getResponseDestinationURI();
XMLGregorianCalendar issueInstant = XMLTimeUtil.getIssueInstant();
// Create assertion -> subject
SubjectType subjectType = new SubjectType();
// subject -> nameid
NameIDType nameIDType = new NameIDType();
nameIDType.setFormat(idp.getNameIDFormat() == null ? null : URI.create(idp.getNameIDFormat()));
nameIDType.setValue(idp.getNameIDFormatValue());
SubjectType.STSubType subType = new SubjectType.STSubType();
subType.addBaseID(nameIDType);
subjectType.setSubType(subType);
SubjectConfirmationType subjectConfirmation = new SubjectConfirmationType();
subjectConfirmation.setMethod(idp.getSubjectConfirmationMethod());
SubjectConfirmationDataType subjectConfirmationData = new SubjectConfirmationDataType();
subjectConfirmationData.setInResponseTo(sp.getRequestID());
subjectConfirmationData.setRecipient(responseDestinationURI);
// subjectConfirmationData.setNotBefore(issueInstant);
subjectConfirmationData.setNotOnOrAfter(issueInstant);
subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData);
subjectType.addConfirmation(subjectConfirmation);
AssertionType assertionType;
NameIDType issuerID = issuerInfo.getIssuer();
issueInstant = XMLTimeUtil.getIssueInstant();
ConditionsType conditions = null;
List<StatementAbstractType> statements = new LinkedList<>();
// generate an id for the new assertion.
String assertionID = IDGenerator.create("ID_");
assertionType = SAMLAssertionFactory.createAssertion(assertionID, issuerID, issueInstant, conditions, subjectType, statements);
try {
AssertionUtil.createTimedConditions(assertionType, ASSERTION_VALIDITY, CLOCK_SKEW);
} catch (ConfigurationException e) {
throw logger.processingError(e);
} catch (IssueInstantMissingException e) {
throw logger.processingError(e);
}
ResponseType responseType = createResponseType(ID, issuerInfo, assertionType);
// InResponseTo ID
responseType.setInResponseTo(sp.getRequestID());
// Destination
responseType.setDestination(responseDestinationURI);
return responseType;
}
use of org.keycloak.dom.saml.v2.assertion.AssertionType in project keycloak by keycloak.
the class SAML2LoginResponseBuilder method buildModel.
public ResponseType buildModel() throws ConfigurationException, ProcessingException {
ResponseType responseType = null;
SAML2Response saml2Response = new SAML2Response();
// Create a response type
String id = IDGenerator.create("ID_");
IssuerInfoHolder issuerHolder = new IssuerInfoHolder(issuer);
issuerHolder.setStatusCode(JBossSAMLURIConstants.STATUS_SUCCESS.get());
IDPInfoHolder idp = new IDPInfoHolder();
idp.setNameIDFormatValue(nameId);
idp.setNameIDFormat(nameIdFormat);
SPInfoHolder sp = new SPInfoHolder();
sp.setResponseDestinationURI(destination);
sp.setRequestID(requestID);
sp.setIssuer(requestIssuer);
responseType = saml2Response.createResponseType(id, sp, idp, issuerHolder);
AssertionType assertion = responseType.getAssertions().get(0).getAssertion();
// Add request issuer as the audience restriction
AudienceRestrictionType audience = new AudienceRestrictionType();
audience.addAudience(URI.create(requestIssuer));
assertion.getConditions().addCondition(audience);
// Update Conditions NotOnOrAfter
if (assertionExpiration > 0) {
ConditionsType conditions = assertion.getConditions();
conditions.setNotOnOrAfter(XMLTimeUtil.add(conditions.getNotBefore(), assertionExpiration * 1000L));
}
// Update SubjectConfirmationData NotOnOrAfter
if (subjectExpiration > 0) {
SubjectConfirmationDataType subjectConfirmationData = assertion.getSubject().getConfirmation().get(0).getSubjectConfirmationData();
subjectConfirmationData.setNotOnOrAfter(XMLTimeUtil.add(assertion.getConditions().getNotBefore(), subjectExpiration * 1000L));
}
// Create an AuthnStatementType
if (!disableAuthnStatement) {
String authContextRef = JBossSAMLURIConstants.AC_UNSPECIFIED.get();
if (isNotNull(authMethod))
authContextRef = authMethod;
AuthnStatementType authnStatement = StatementUtil.createAuthnStatement(XMLTimeUtil.getIssueInstant(), authContextRef);
if (sessionExpiration > 0)
authnStatement.setSessionNotOnOrAfter(XMLTimeUtil.add(authnStatement.getAuthnInstant(), sessionExpiration * 1000L));
if (sessionIndex != null)
authnStatement.setSessionIndex(sessionIndex);
else
authnStatement.setSessionIndex(assertion.getID());
assertion.addStatement(authnStatement);
}
if (includeOneTimeUseCondition) {
assertion.getConditions().addCondition(new OneTimeUseType());
}
if (!this.extensions.isEmpty()) {
ExtensionsType extensionsType = new ExtensionsType();
for (NodeGenerator extension : this.extensions) {
extensionsType.addExtension(extension);
}
responseType.setExtensions(extensionsType);
}
return responseType;
}
Aggregations