Skip to content

Commit

Permalink
add support for AttributeNameFormat config
Browse files Browse the repository at this point in the history
  • Loading branch information
DilshanSenarath committed Jan 7, 2025
1 parent 363bd82 commit ae75bd4
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@
<xs:element minOccurs="0" name="doValidateSignatureInRequests" type="xs:boolean"/>
<xs:element minOccurs="0" name="enableAttributeProfile" type="xs:boolean"/>
<xs:element minOccurs="0" name="enableAttributesByDefault" type="xs:boolean"/>
<xs:element minOccurs="0" name="attributeNameFormat" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="enableSAML2ArtifactBinding" type="xs:boolean"/>
<xs:element minOccurs="0" name="frontChannelLogoutBinding" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="idPInitSLOEnabled" type="xs:boolean"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ public class SAMLSSOConstants {

public static final String NAME_ID_POLICY_ENTITY = "urn:oasis:names:tc:SAML:2.0:nameid-format:entity";
public static final String SUBJECT_CONFIRM_BEARER = "urn:oasis:names:tc:SAML:2.0:cm:bearer";
/**
* This constant is deprecated and will be removed in future versions.
* Use {@link NameFormat#BASIC} instead.
*
* @deprecated Replaced by {@link NameFormat#BASIC}.
*/
@Deprecated
public static final String NAME_FORMAT_BASIC = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic";
public static final String SAML_ASSERTION_URN = "urn:oasis:names:tc:SAML:2.0:assertion";
public static final String NAMEID_FORMAT_PERSISTENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent";
Expand Down Expand Up @@ -120,6 +127,27 @@ public class SAMLSSOConstants {
private SAMLSSOConstants() {
}

/**
* Supported name formats for attributes in SAML assertion.
*/
public enum NameFormat {

BASIC("urn:oasis:names:tc:SAML:2.0:attrname-format:basic"),
URI("urn:oasis:names:tc:SAML:2.0:attrname-format:uri");

private final String uri;

NameFormat(String uri) {

this.uri = uri;
}

@Override
public String toString() {

return this.uri;
}
}

public enum QueryParameter {

Expand Down Expand Up @@ -286,6 +314,7 @@ public static class Notification {
public static final String ERROR_RETRIEVE_SP_CONFIG = "Error occurred while loading Service Provider " +
"configurations";
public static final String EXCEPTION_STATUS_ARTIFACT_RESOLVE = "Error while resolving SAML artifact";
public static final String INVALID_NAME_FORMAT = "The provided NameFormat '%s' is invalid";

private Notification() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.wso2.carbon.identity.sp.metadata.saml2.exception.InvalidMetadataException;
import org.wso2.carbon.identity.sp.metadata.saml2.util.Parser;
import org.wso2.carbon.identity.sso.saml.Error;
import org.wso2.carbon.identity.sso.saml.SAMLSSOConstants;
import org.wso2.carbon.identity.sso.saml.SSOServiceProviderConfigManager;
import org.wso2.carbon.identity.sso.saml.dto.SAMLSSOServiceProviderDTO;
import org.wso2.carbon.identity.sso.saml.dto.SAMLSSOServiceProviderInfoDTO;
Expand Down Expand Up @@ -509,13 +510,25 @@ private SAMLSSOServiceProviderDO createSAMLSSOServiceProviderDO(SAMLSSOServicePr
serviceProviderDO.setAttributeConsumingServiceIndex(Integer.toString(IdentityUtil.getRandomInteger()));
}
serviceProviderDO.setEnableAttributesByDefault(serviceProviderDTO.isEnableAttributesByDefault());
if (StringUtils.isNotBlank(serviceProviderDTO.getAttributeNameFormat())) {
if (SAMLSSOUtil.validateAttributeNameFormat(serviceProviderDTO.getAttributeNameFormat())) {
serviceProviderDO.setAttributeNameFormat(serviceProviderDTO.getAttributeNameFormat());
} else {
throw new IdentitySAML2ClientException(
String.format(SAMLSSOConstants.Notification.INVALID_NAME_FORMAT,
serviceProviderDTO.getAttributeNameFormat()));
}
} else {
serviceProviderDO.setAttributeNameFormat(SAMLSSOConstants.NameFormat.BASIC.toString());
}
} else {
serviceProviderDO.setAttributeConsumingServiceIndex("");
if (serviceProviderDO.isEnableAttributesByDefault()) {
log.warn("Enable Attribute Profile must be selected to activate it by default. " +
"EnableAttributesByDefault will be disabled.");
}
serviceProviderDO.setEnableAttributesByDefault(false);
serviceProviderDO.setAttributeNameFormat(SAMLSSOConstants.NameFormat.BASIC.toString());
}

if (serviceProviderDTO.getRequestedAudiences() != null && serviceProviderDTO.getRequestedAudiences().length != 0) {
Expand Down Expand Up @@ -600,6 +613,7 @@ private SAMLSSOServiceProviderDTO createSAMLSSOServiceProviderDTO(SAMLSSOService
serviceProviderDTO.setSupportedAssertionQueryRequestTypes(serviceProviderDO
.getSupportedAssertionQueryRequestTypes());
serviceProviderDTO.setEnableAttributesByDefault(serviceProviderDO.isEnableAttributesByDefault());
serviceProviderDTO.setAttributeNameFormat(serviceProviderDO.getAttributeNameFormat());
serviceProviderDTO.setEnableSAML2ArtifactBinding(serviceProviderDO.isEnableSAML2ArtifactBinding());
serviceProviderDTO.setDoValidateSignatureInArtifactResolve(serviceProviderDO
.isDoValidateSignatureInArtifactResolve());
Expand Down Expand Up @@ -689,6 +703,7 @@ public SAMLSSOServiceProviderInfoDTO getServiceProviders() throws IdentityExcept
providerDTO.setRequestedAudiences(providerDO.getRequestedAudiences());
providerDTO.setRequestedRecipients(providerDO.getRequestedRecipients());
providerDTO.setEnableAttributesByDefault(providerDO.isEnableAttributesByDefault());
providerDTO.setAttributeNameFormat(providerDO.getAttributeNameFormat());
providerDTO.setNameIdClaimUri(providerDO.getNameIdClaimUri());
providerDTO.setNameIDFormat(providerDO.getNameIDFormat());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,35 @@ protected void addAttributeStatements(SAMLSSOAuthnReqDTO authReqDTO, Assertion s
// Exception is ignored without including the IDP session key in the AttributeStatement.
}
if (claims != null && !claims.isEmpty()) {
AttributeStatement attrStmt = buildAttributeStatement(claims);
AttributeStatement attrStmt = buildAttributeStatement(authReqDTO, claims);
if (attrStmt != null) {
samlAssertion.getAttributeStatements().add(attrStmt);
}
}
}

/**
* Construct the attribute statement for the SAML assertion considering configured NameFormat.
*
* @param authReqDTO - Data related to SAML SSO authentication requests and service provider configurations.
* @param claims - Authenticated user claims.
* @return AttributeStatement related to the SAML Auth request.
*/
protected AttributeStatement buildAttributeStatement(SAMLSSOAuthnReqDTO authReqDTO, Map<String, String> claims) {

AttributeStatement attributeStatement = buildAttributeStatement(claims);

if (authReqDTO.getAttributeNameFormat() != null &&
!StringUtils.equals(SAMLSSOConstants.NameFormat.BASIC.toString(),
authReqDTO.getAttributeNameFormat())) {
for (Attribute attribute : attributeStatement.getAttributes()) {
attribute.setNameFormat(authReqDTO.getAttributeNameFormat());
}
}

return attributeStatement;
}

/**
* Add Authn Statement to the Assertion
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public class SAMLSSOAuthnReqDTO implements Serializable {
private String[] requestedClaims;
private String[] requestedAudiences;
private String[] requestedRecipients;
private String attributeNameFormat;
private boolean doSingleLogout;
private boolean doFrontChannelLogout;
private String frontChannelLogoutBinding;
Expand Down Expand Up @@ -371,6 +372,16 @@ public void setRequestedRecipients(String[] requestedRecipients) {
}
}

public String getAttributeNameFormat() {

return this.attributeNameFormat;
}

public void setAttributeNameFormat(String attributeNameFormat) {

this.attributeNameFormat = attributeNameFormat;
}

public boolean isStratosDeployment() {
return isStratosDeployment;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public class SAMLSSOServiceProviderDTO extends InboundConfigurationProtocol impl
@XmlElement(name = "requestedRecipient")
private String[] requestedRecipients;
private boolean enableAttributeProfile;
private String attributeNameFormat;
private boolean isAssertionQueryRequestProfileEnabled;
private String supportedAssertionQueryRequestTypes;
private boolean enableAttributesByDefault;
Expand Down Expand Up @@ -537,4 +538,14 @@ public void setAuditLogData(String auditLogData) {

this.auditLogData = auditLogData;
}

public void setAttributeNameFormat(String attributeNameFormat) {

this.attributeNameFormat = attributeNameFormat;
}

public String getAttributeNameFormat() {

return attributeNameFormat;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ private void populateServiceProviderConfigs(SAMLSSOServiceProviderDO ssoIdpConfi
authnReqDTO.setRequestedClaims(ssoIdpConfigs.getRequestedClaims());
authnReqDTO.setRequestedAudiences(ssoIdpConfigs.getRequestedAudiences());
authnReqDTO.setRequestedRecipients(ssoIdpConfigs.getRequestedRecipients());
authnReqDTO.setAttributeNameFormat(ssoIdpConfigs.getAttributeNameFormat());
authnReqDTO.setDoEnableEncryptedAssertion(ssoIdpConfigs.isDoEnableEncryptedAssertion());
authnReqDTO.setIdPInitSLOEnabled(ssoIdpConfigs.isIdPInitSLOEnabled());
authnReqDTO.setAssertionConsumerURLs(ssoIdpConfigs.getAssertionConsumerUrls());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ private void populateServiceProviderConfigs(SAMLSSOServiceProviderDO ssoIdpConfi
authnReqDTO.setRequestedClaims(ssoIdpConfigs.getRequestedClaims());
authnReqDTO.setRequestedAudiences(ssoIdpConfigs.getRequestedAudiences());
authnReqDTO.setRequestedRecipients(ssoIdpConfigs.getRequestedRecipients());
authnReqDTO.setAttributeNameFormat(ssoIdpConfigs.getAttributeNameFormat());
authnReqDTO.setDoEnableEncryptedAssertion(ssoIdpConfigs.isDoEnableEncryptedAssertion());
authnReqDTO.setDoValidateSignatureInRequests(ssoIdpConfigs.isDoValidateSignatureInRequests());
authnReqDTO.setIdPInitSLOEnabled(ssoIdpConfigs.isIdPInitSLOEnabled());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;

import static org.wso2.carbon.identity.sso.saml.SAMLSSOConstants.NameFormat;
import static org.wso2.carbon.identity.sso.saml.SAMLSSOConstants.SAML_REQUEST;

public class SAMLSSOUtil {
Expand Down Expand Up @@ -2775,4 +2776,21 @@ public static boolean separateMultiAttributesFromIdPEnabled() {
return true;
}
}

/**
* Validate that the given attribute name format is a valid value.
*
* @param attributeNameFormat - Attribute name format value that requires validation.
* @return A boolean result indicating whether the provided name format is valid.
*/
public static boolean validateAttributeNameFormat(String attributeNameFormat) {

for (NameFormat nameFormat : NameFormat.values()) {
if (StringUtils.equals(nameFormat.toString(), attributeNameFormat)) {
return true;
}
}

return false;
}
}
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@
<properties>
<carbon.kernel.version>4.9.23</carbon.kernel.version>
<carbon.kernel.feature.version>4.9.0</carbon.kernel.feature.version>
<carbon.identity.framework.version>7.0.105</carbon.identity.framework.version>
<carbon.identity.framework.version>7.7.81</carbon.identity.framework.version>
<carbon.identity.framework.imp.pkg.version.range>[5.25.260, 8.0.0)
</carbon.identity.framework.imp.pkg.version.range>
<carbon.identity.organization.management.core.version>1.0.0</carbon.identity.organization.management.core.version>
Expand Down

0 comments on commit ae75bd4

Please sign in to comment.