use of org.keycloak.dom.saml.v2.assertion.AttributeStatementType 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.AttributeStatementType in project keycloak by keycloak.
the class SAMLLoginResponseHandlingTest method testNilAttributeValueAttribute.
@Test
public void testNilAttributeValueAttribute() {
beginAuthenticationAndLogin(employee2ServletPage, SamlClient.Binding.POST).processSamlResponse(// Update response with Nil attribute
SamlClient.Binding.POST).transformObject(ob -> {
assertThat(ob, Matchers.isSamlResponse(JBossSAMLURIConstants.STATUS_SUCCESS));
ResponseType resp = (ResponseType) ob;
Set<StatementAbstractType> statements = resp.getAssertions().get(0).getAssertion().getStatements();
AttributeStatementType attributeType = (AttributeStatementType) statements.stream().filter(statement -> statement instanceof AttributeStatementType).findFirst().orElse(new AttributeStatementType());
AttributeType attr = new AttributeType("attribute-with-null-attribute-value");
attr.addAttributeValue(null);
attributeType.addAttribute(new AttributeStatementType.ASTChoiceType(attr));
resp.getAssertions().get(0).getAssertion().addStatement(attributeType);
return ob;
}).build().navigateTo(employee2ServletPage.getUriBuilder().clone().path("getAttributes").build()).execute(response -> {
Assert.assertThat(response, statusCodeIsHC(Response.Status.OK));
Assert.assertThat(response, bodyHC(containsString("attribute-with-null-attribute-value: <br />")));
});
}
use of org.keycloak.dom.saml.v2.assertion.AttributeStatementType in project keycloak by keycloak.
the class GroupMembershipMapper method transformAttributeStatement.
@Override
public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, AuthenticatedClientSessionModel clientSession) {
String single = mappingModel.getConfig().get(SINGLE_GROUP_ATTRIBUTE);
boolean singleAttribute = Boolean.parseBoolean(single);
boolean fullPath = useFullPath(mappingModel);
final AtomicReference<AttributeType> singleAttributeType = new AtomicReference<>(null);
userSession.getUser().getGroupsStream().forEach(group -> {
String groupName;
if (fullPath) {
groupName = ModelToRepresentation.buildGroupPath(group);
} else {
groupName = group.getName();
}
AttributeType attributeType;
if (singleAttribute) {
if (singleAttributeType.get() == null) {
singleAttributeType.set(AttributeStatementHelper.createAttributeType(mappingModel));
attributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(singleAttributeType.get()));
}
attributeType = singleAttributeType.get();
} else {
attributeType = AttributeStatementHelper.createAttributeType(mappingModel);
attributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attributeType));
}
attributeType.addAttributeValue(groupName);
});
}
use of org.keycloak.dom.saml.v2.assertion.AttributeStatementType in project keycloak by keycloak.
the class RoleListMapper method mapRoles.
@Override
public void mapRoles(AttributeStatementType roleAttributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionContext clientSessionCtx) {
String single = mappingModel.getConfig().get(SINGLE_ROLE_ATTRIBUTE);
boolean singleAttribute = Boolean.parseBoolean(single);
List<SamlProtocol.ProtocolMapperProcessor<SAMLRoleNameMapper>> roleNameMappers = new LinkedList<>();
AtomicReference<AttributeType> singleAttributeType = new AtomicReference<>(null);
ProtocolMapperUtils.getSortedProtocolMappers(session, clientSessionCtx).forEach(entry -> {
ProtocolMapperModel mapping = entry.getKey();
ProtocolMapper mapper = entry.getValue();
if (mapper instanceof SAMLRoleNameMapper) {
roleNameMappers.add(new SamlProtocol.ProtocolMapperProcessor<>((SAMLRoleNameMapper) mapper, mapping));
}
if (mapper instanceof HardcodedRole) {
AttributeType attributeType;
if (singleAttribute) {
if (singleAttributeType.get() == null) {
singleAttributeType.set(AttributeStatementHelper.createAttributeType(mappingModel));
roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(singleAttributeType.get()));
}
attributeType = singleAttributeType.get();
} else {
attributeType = AttributeStatementHelper.createAttributeType(mappingModel);
roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attributeType));
}
attributeType.addAttributeValue(mapping.getConfig().get(HardcodedRole.ROLE_ATTRIBUTE));
}
});
List<String> allRoleNames = clientSessionCtx.getRolesStream().map(roleModel -> roleNameMappers.stream().map(entry -> entry.mapper.mapName(entry.model, roleModel)).filter(Objects::nonNull).findFirst().orElse(roleModel.getName())).collect(Collectors.toList());
for (String roleName : allRoleNames) {
AttributeType attributeType;
if (singleAttribute) {
if (singleAttributeType.get() == null) {
singleAttributeType.set(AttributeStatementHelper.createAttributeType(mappingModel));
roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(singleAttributeType.get()));
}
attributeType = singleAttributeType.get();
} else {
attributeType = AttributeStatementHelper.createAttributeType(mappingModel);
roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attributeType));
}
attributeType.addAttributeValue(roleName);
}
}
use of org.keycloak.dom.saml.v2.assertion.AttributeStatementType in project keycloak by keycloak.
the class AttributeStatementHelper method addAttribute.
public static void addAttribute(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, String attributeValue) {
AttributeType attribute = createAttributeType(mappingModel);
attribute.addAttributeValue(attributeValue);
attributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attribute));
}
Aggregations