use of org.opensaml.saml.saml2.core.AttributeStatement in project cas by apereo.
the class AbstractSaml20ObjectBuilder method newAttributeStatement.
/**
* New attribute statement.
*
* @param attributes the attributes
* @param attributeFriendlyNames the attribute friendly names
* @param configuredNameFormats the configured name formats
* @param defaultNameFormat the default name format
* @return the attribute statement
*/
public AttributeStatement newAttributeStatement(final Map<String, Object> attributes, final Map<String, String> attributeFriendlyNames, final Map<String, String> configuredNameFormats, final String defaultNameFormat) {
final AttributeStatement attrStatement = newSamlObject(AttributeStatement.class);
for (final Map.Entry<String, Object> e : attributes.entrySet()) {
if (e.getValue() instanceof Collection<?> && ((Collection<?>) e.getValue()).isEmpty()) {
LOGGER.info("Skipping attribute [{}] because it does not have any values.", e.getKey());
continue;
}
final String friendlyName = attributeFriendlyNames.getOrDefault(e.getKey(), null);
final Attribute attribute = newAttribute(friendlyName, e, configuredNameFormats, defaultNameFormat);
attrStatement.getAttributes().add(attribute);
}
return attrStatement;
}
use of org.opensaml.saml.saml2.core.AttributeStatement in project verify-hub by alphagov.
the class EidasAttributeStatementAssertionValidator method validateAttributes.
private void validateAttributes(Assertion assertion) {
final List<AttributeStatement> attributeStatements = assertion.getAttributeStatements();
if (attributeStatements.isEmpty()) {
SamlValidationSpecificationFailure failure = SamlTransformationErrorFactory.mdsStatementMissing();
throw new SamlTransformationErrorException(failure.getErrorMessage(), failure.getLogLevel());
}
if (attributeStatements.size() > 1) {
SamlValidationSpecificationFailure failure = SamlTransformationErrorFactory.mdsMultipleStatements();
throw new SamlTransformationErrorException(failure.getErrorMessage(), failure.getLogLevel());
}
final List<Attribute> attributes = attributeStatements.get(0).getAttributes();
if (attributes.isEmpty()) {
SamlValidationSpecificationFailure failure = attributeStatementEmpty(assertion.getID());
throw new SamlTransformationErrorException(failure.getErrorMessage(), failure.getLogLevel());
}
Set<String> attributeNames = attributes.stream().map(Attribute::getName).collect(Collectors.toSet());
if (!attributeNames.containsAll(MANDATORY_ATTRIBUTES.keySet())) {
throw new SamlTransformationErrorException(String.format("Mandatory attributes not provided. Expected %s but got %s", MANDATORY_ATTRIBUTES.values().stream().collect(Collectors.joining(",")), attributes.stream().map(Attribute::getFriendlyName).collect(Collectors.joining(","))), Level.ERROR);
}
for (Attribute attribute : attributes) {
final String attributeName = attribute.getName();
if (!VALID_EIDAS_ATTRIBUTE_NAMES.contains(attributeName)) {
SamlValidationSpecificationFailure failure = SamlTransformationErrorFactory.mdsAttributeNotRecognised(attributeName);
throw new SamlTransformationErrorException(failure.getErrorMessage(), failure.getLogLevel());
}
if (attribute.getAttributeValues().isEmpty()) {
SamlValidationSpecificationFailure failure = SamlTransformationErrorFactory.emptyAttribute(attributeName);
throw new SamlTransformationErrorException(failure.getErrorMessage(), failure.getLogLevel());
}
if (!VALID_TYPE_FOR_ATTRIBUTE.get(attributeName).equals(attribute.getAttributeValues().get(0).getSchemaType())) {
final QName schemaType = attribute.getAttributeValues().get(0).getSchemaType();
SamlValidationSpecificationFailure failure = SamlTransformationErrorFactory.attributeWithIncorrectType(attributeName, VALID_TYPE_FOR_ATTRIBUTE.get(attributeName), schemaType);
throw new SamlTransformationErrorException(failure.getErrorMessage(), failure.getLogLevel());
}
if (!VALID_ATTRIBUTE_NAME_FORMATS.contains(attribute.getNameFormat())) {
SamlTransformationErrorManager.warn(invalidAttributeNameFormat(attribute.getNameFormat()));
}
}
}
use of org.opensaml.saml.saml2.core.AttributeStatement in project pac4j by pac4j.
the class SAML2DefaultResponseValidator method buildSAML2Credentials.
protected final SAML2Credentials buildSAML2Credentials(final SAML2MessageContext context) {
final NameID nameId = context.getSAMLSubjectNameIdentifierContext().getSAML2SubjectNameID();
final Assertion subjectAssertion = context.getSubjectAssertion();
final String sessionIndex = getSessionIndex(subjectAssertion);
final String issuerEntityId = subjectAssertion.getIssuer().getValue();
List<AuthnStatement> authnStatements = subjectAssertion.getAuthnStatements();
List<String> authnContexts = new ArrayList<String>();
for (AuthnStatement authnStatement : authnStatements) {
authnContexts.add(authnStatement.getAuthnContext().getAuthnContextClassRef().getAuthnContextClassRef());
}
final List<Attribute> attributes = new ArrayList<Attribute>();
for (final AttributeStatement attributeStatement : subjectAssertion.getAttributeStatements()) {
for (final Attribute attribute : attributeStatement.getAttributes()) {
attributes.add(attribute);
}
if (!attributeStatement.getEncryptedAttributes().isEmpty()) {
if (decrypter == null) {
logger.warn("Encrypted attributes returned, but no keystore was provided.");
} else {
for (final EncryptedAttribute encryptedAttribute : attributeStatement.getEncryptedAttributes()) {
try {
attributes.add(decrypter.decrypt(encryptedAttribute));
} catch (final DecryptionException e) {
logger.warn("Decryption of attribute failed, continue with the next one", e);
}
}
}
}
}
return new SAML2Credentials(nameId, issuerEntityId, attributes, subjectAssertion.getConditions(), sessionIndex, authnContexts);
}
use of org.opensaml.saml.saml2.core.AttributeStatement in project syncope by apache.
the class SAML2SPLogic method validateLoginResponse.
@PreAuthorize("hasRole('" + StandardEntitlement.ANONYMOUS + "')")
public SAML2LoginResponseTO validateLoginResponse(final SAML2ReceivedResponseTO response) {
check();
// 1. first checks for the provided relay state
if (response.getRelayState() == null) {
throw new IllegalArgumentException("No Relay State was provided");
}
Boolean useDeflateEncoding = false;
String requestId = null;
if (!IDP_INITIATED_RELAY_STATE.equals(response.getRelayState())) {
JwsJwtCompactConsumer relayState = new JwsJwtCompactConsumer(response.getRelayState());
if (!relayState.verifySignatureWith(jwsSignatureVerifier)) {
throw new IllegalArgumentException("Invalid signature found in Relay State");
}
useDeflateEncoding = Boolean.valueOf(relayState.getJwtClaims().getClaim(JWT_CLAIM_IDP_DEFLATE).toString());
requestId = relayState.getJwtClaims().getSubject();
Long expiryTime = relayState.getJwtClaims().getExpiryTime();
if (expiryTime == null || (expiryTime * 1000L) < new Date().getTime()) {
throw new IllegalArgumentException("Relay State is expired");
}
}
// 2. parse the provided SAML response
if (response.getSamlResponse() == null) {
throw new IllegalArgumentException("No SAML Response was provided");
}
Response samlResponse;
try {
XMLObject responseObject = saml2rw.read(useDeflateEncoding, response.getSamlResponse());
if (!(responseObject instanceof Response)) {
throw new IllegalArgumentException("Expected " + Response.class.getName() + ", got " + responseObject.getClass().getName());
}
samlResponse = (Response) responseObject;
} catch (Exception e) {
LOG.error("While parsing AuthnResponse", e);
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
sce.getElements().add(e.getMessage());
throw sce;
}
// 3. validate the SAML response and, if needed, decrypt the provided assertion(s)
if (samlResponse.getIssuer() == null || samlResponse.getIssuer().getValue() == null) {
throw new IllegalArgumentException("The SAML Response must contain an Issuer");
}
final SAML2IdPEntity idp = getIdP(samlResponse.getIssuer().getValue());
if (idp.getConnObjectKeyItem() == null) {
throw new IllegalArgumentException("No mapping provided for SAML 2.0 IdP '" + idp.getId() + "'");
}
if (IDP_INITIATED_RELAY_STATE.equals(response.getRelayState()) && !idp.isSupportUnsolicited()) {
throw new IllegalArgumentException("An unsolicited request is not allowed for idp: " + idp.getId());
}
SSOValidatorResponse validatorResponse = null;
try {
validatorResponse = saml2rw.validate(samlResponse, idp, getAssertionConsumerURL(response.getSpEntityID(), response.getUrlContext()), requestId, response.getSpEntityID());
} catch (Exception e) {
LOG.error("While validating AuthnResponse", e);
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
sce.getElements().add(e.getMessage());
throw sce;
}
// 4. prepare the result: find matching user (if any) and return the received attributes
final SAML2LoginResponseTO responseTO = new SAML2LoginResponseTO();
responseTO.setIdp(idp.getId());
responseTO.setSloSupported(idp.getSLOLocation(idp.getBindingType()) != null);
Assertion assertion = validatorResponse.getOpensamlAssertion();
NameID nameID = assertion.getSubject().getNameID();
if (nameID == null) {
throw new IllegalArgumentException("NameID not found");
}
String keyValue = null;
if (StringUtils.isNotBlank(nameID.getValue()) && idp.getConnObjectKeyItem().getExtAttrName().equals("NameID")) {
keyValue = nameID.getValue();
}
if (assertion.getConditions().getNotOnOrAfter() != null) {
responseTO.setNotOnOrAfter(assertion.getConditions().getNotOnOrAfter().toDate());
}
assertion.getAuthnStatements().forEach(authnStmt -> {
responseTO.setSessionIndex(authnStmt.getSessionIndex());
responseTO.setAuthInstant(authnStmt.getAuthnInstant().toDate());
if (authnStmt.getSessionNotOnOrAfter() != null) {
responseTO.setNotOnOrAfter(authnStmt.getSessionNotOnOrAfter().toDate());
}
});
for (AttributeStatement attrStmt : assertion.getAttributeStatements()) {
for (Attribute attr : attrStmt.getAttributes()) {
if (!attr.getAttributeValues().isEmpty()) {
String attrName = attr.getFriendlyName() == null ? attr.getName() : attr.getFriendlyName();
if (attrName.equals(idp.getConnObjectKeyItem().getExtAttrName())) {
if (attr.getAttributeValues().get(0) instanceof XSString) {
keyValue = ((XSString) attr.getAttributeValues().get(0)).getValue();
} else if (attr.getAttributeValues().get(0) instanceof XSAny) {
keyValue = ((XSAny) attr.getAttributeValues().get(0)).getTextContent();
}
}
AttrTO attrTO = new AttrTO();
attrTO.setSchema(attrName);
attr.getAttributeValues().stream().filter(value -> value.getDOM() != null).forEachOrdered(value -> {
attrTO.getValues().add(value.getDOM().getTextContent());
});
responseTO.getAttrs().add(attrTO);
}
}
}
final List<String> matchingUsers = keyValue == null ? Collections.<String>emptyList() : userManager.findMatchingUser(keyValue, idp.getKey());
LOG.debug("Found {} matching users for {}", matchingUsers.size(), keyValue);
String username;
if (matchingUsers.isEmpty()) {
if (idp.isCreateUnmatching()) {
LOG.debug("No user matching {}, about to create", keyValue);
username = AuthContextUtils.execWithAuthContext(AuthContextUtils.getDomain(), () -> userManager.create(idp, responseTO, nameID.getValue()));
} else if (idp.isSelfRegUnmatching()) {
responseTO.setNameID(nameID.getValue());
UserTO userTO = new UserTO();
userManager.fill(idp.getKey(), responseTO, userTO);
responseTO.getAttrs().clear();
responseTO.getAttrs().addAll(userTO.getPlainAttrs());
responseTO.getAttrs().addAll(userTO.getVirAttrs());
if (StringUtils.isNotBlank(userTO.getUsername())) {
responseTO.setUsername(userTO.getUsername());
}
responseTO.setSelfReg(true);
return responseTO;
} else {
throw new NotFoundException("User matching the provided value " + keyValue);
}
} else if (matchingUsers.size() > 1) {
throw new IllegalArgumentException("Several users match the provided value " + keyValue);
} else {
if (idp.isUpdateMatching()) {
LOG.debug("About to update {} for {}", matchingUsers.get(0), keyValue);
username = AuthContextUtils.execWithAuthContext(AuthContextUtils.getDomain(), () -> userManager.update(matchingUsers.get(0), idp, responseTO));
} else {
username = matchingUsers.get(0);
}
}
responseTO.setUsername(username);
responseTO.setNameID(nameID.getValue());
// 5. generate JWT for further access
Map<String, Object> claims = new HashMap<>();
claims.put(JWT_CLAIM_IDP_ENTITYID, idp.getId());
claims.put(JWT_CLAIM_NAMEID_FORMAT, nameID.getFormat());
claims.put(JWT_CLAIM_NAMEID_VALUE, nameID.getValue());
claims.put(JWT_CLAIM_SESSIONINDEX, responseTO.getSessionIndex());
byte[] authorities = null;
try {
authorities = ENCRYPTOR.encode(POJOHelper.serialize(authDataAccessor.getAuthorities(responseTO.getUsername())), CipherAlgorithm.AES).getBytes();
} catch (Exception e) {
LOG.error("Could not fetch authorities", e);
}
Pair<String, Date> accessTokenInfo = accessTokenDataBinder.create(responseTO.getUsername(), claims, authorities, true);
responseTO.setAccessToken(accessTokenInfo.getLeft());
responseTO.setAccessTokenExpiryTime(accessTokenInfo.getRight());
return responseTO;
}
use of org.opensaml.saml.saml2.core.AttributeStatement in project cas by apereo.
the class WsFederationHelper method createCredentialFromToken.
/**
* createCredentialFromToken converts a SAML 1.1 assertion to a WSFederationCredential.
*
* @param assertion the provided assertion
* @return an equivalent credential.
*/
public WsFederationCredential createCredentialFromToken(final Assertion assertion) {
val retrievedOn = ZonedDateTime.now(clock);
LOGGER.trace("Retrieved on [{}]", retrievedOn);
val credential = new WsFederationCredential();
credential.setRetrievedOn(retrievedOn);
credential.setId(assertion.getID());
credential.setIssuer(assertion.getIssuer());
credential.setIssuedOn(DateTimeUtils.zonedDateTimeOf(assertion.getIssueInstant()));
val conditions = assertion.getConditions();
if (conditions != null) {
credential.setNotBefore(DateTimeUtils.zonedDateTimeOf(conditions.getNotBefore()));
credential.setNotOnOrAfter(DateTimeUtils.zonedDateTimeOf(conditions.getNotOnOrAfter()));
if (!conditions.getAudienceRestrictionConditions().isEmpty()) {
credential.setAudience(conditions.getAudienceRestrictionConditions().get(0).getAudiences().get(0).getURI());
}
}
if (!assertion.getAuthenticationStatements().isEmpty()) {
credential.setAuthenticationMethod(assertion.getAuthenticationStatements().get(0).getAuthenticationMethod());
}
val attributes = new HashMap<String, List<Object>>();
assertion.getAttributeStatements().stream().flatMap(attributeStatement -> attributeStatement.getAttributes().stream()).forEach(item -> {
LOGGER.trace("Processed attribute: [{}]", item.getAttributeName());
final List<Object> itemList = item.getAttributeValues().stream().map(xmlObject -> ((XSAny) xmlObject).getTextContent()).collect(Collectors.toList());
if (!itemList.isEmpty()) {
attributes.put(item.getAttributeName(), itemList);
}
});
credential.setAttributes(attributes);
LOGGER.debug("WsFederation Credential retrieved as: [{}]", credential);
return credential;
}
Aggregations