This guide is written by the team that builds Casdoor and describes the standards as published (listed under Sources), with notes on how Casdoor implements them as of November 2, 2026. Spotted a mistake? Tell us.
SAML attribute mapping is the translation layer between the identity provider and the application. The identity provider knows the user's email, name, groups and department; the application expects those values under specific names and formats. When the mapping is wrong, authentication can succeed and the user still arrives with no email, no role, or a different identifier on every login.
This is one of the most common reasons a SAML integration "works in the test tool but fails in the app". The assertion is valid; the attributes are not what the service provider expects.
What is in a SAML assertion
A SAML response contains an assertion with three parts:
- Subject and NameID. The identifier the service provider uses for the user.
- AttributeStatement. One or more attributes, each with a name, a name format and one or more values.
- Conditions and AuthnStatement. Validity window, audience and session information.
A single attribute looks like this in XML: an Attribute element with a Name and NameFormat, containing one or more AttributeValue elements. The values can be strings, but they can also be lists: group memberships and roles are commonly multi-valued.
NameID formats
The NameID is not just "the username". SAML defines several formats, and the service provider usually only accepts one of them:
| Format | What it contains | When to use |
|---|---|---|
| persistent | An opaque, stable identifier for the user and SP pair | Default for most SaaS apps; does not leak the email |
| transient | A one-time identifier | Flows where the SP should not correlate sessions |
| emailAddress | The user's email address | Apps that treat email as the login name |
| unspecified | Any string chosen by the IdP | Common in older apps; the SP must know what to expect |
| entity | A SAML entity identifier | Rare outside federation metadata |
| kerberos | A Kerberos principal | Windows-integrated environments |
| Windows domain qualified name | DOMAIN\user | Legacy Windows apps |
| X509 subject | A certificate subject DN | Certificate-based environments |
If the service provider expects a persistent identifier but the IdP sends the email address, the user's account may break when the email changes. If the SP expects an email but receives an opaque ID, the user may be created with a blank username. Check the NameID format before you debug anything else.
Attribute names are not standard
SAML standardizes the envelope, not the vocabulary. The same concept arrives under different names:
| Concept | Microsoft Entra ID | Okta | Common shorthand |
|---|---|---|---|
| http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress | user.email | email, mail | |
| First name | http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname | user.firstName | firstName, givenName |
| Last name | http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname | user.lastName | lastName, sn |
| Display name | http://schemas.microsoft.com/identity/claims/displayname | user.displayName | displayName, cn |
| Groups | http://schemas.microsoft.com/ws/2008/06/identity/claims/groups | user.groups | groups, memberOf |
| User principal name | http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn | user.login | upn, samAccountName |
The service provider's mapping is the authority. If it asks for "mail", send "mail"; do not assume it will also look at "emailaddress". Many integrations fail because the IdP sends a perfectly valid attribute under a name the SP does not read.
A typical mapping
For a business application, the minimum useful set is usually:
- NameID: email or a persistent ID, in the format the SP requires.
- Email: the address the app uses for notifications and account matching.
- First and last name: for display and personalization.
- Groups or roles: for authorization, if the app does not manage roles itself.
- Department or tenant: for multi-tenant apps that route users by organization.
Keep the mapping small. Every attribute you send is data you have to protect, and every extra attribute is another thing that can change under you.
Multi-valued attributes and groups
Groups are where mapping gets interesting. A user can be in dozens of groups, and the application often needs only the ones that grant access.
- Send only the groups the application understands, not every group in the directory.
- Decide whether the app expects group names, group IDs or full DNs, and map accordingly.
- Watch the size limit. Microsoft Entra ID can emit a group overage claim when the group list is too large for the assertion, and the application has to handle that separately.
- Case and whitespace matter. "Engineering" and "engineering" are different strings to most apps.
- If the app supports role mapping, map groups to roles at the IdP rather than teaching the app every group name.
Mapping in Casdoor
Casdoor sends three attributes by default: Email, DisplayName and Name. If the service provider needs a different set, add rows to the application's SAML attributes table. Each row has a name, a name format and a value, and the value can use user variables such as the user's name, display name, email, ID, phone, roles, permissions and groups.
For example, an application that expects a role attribute can map it to the user's roles, and an application that expects a specific claim URI can use that URI as the attribute name. Casdoor also lets you disable the default attributes entirely when a service provider validates the response strictly and only needs the NameID.
See the Casdoor SAML IdP documentation for the exact variables and an example response.
Troubleshooting checklist
When the login succeeds but the app has the wrong user data, check these in order:
- NameID format. Does the SP expect persistent, emailAddress or unspecified? Does the assertion match?
- Attribute name. Compare the SP's expected name with the exact Name in the assertion, including case and URI.
- Attribute release. Is the IdP actually sending the attribute, or is it hidden by a conditional release policy?
- NameFormat. Some SPs require urn:oasis:names:tc:SAML:2.0:attrname-format:basic or :uri, and reject :unspecified.
- Multi-valued values. Is the app reading the first value, all values, or failing on an array?
- Groups overage. If the user is in many groups, check whether the IdP replaced the list with an overage claim.
- Encoding. XML-escaped characters, URL encoding and whitespace can all change the value the app receives.
- Clock skew. A response outside its validity window is rejected before attributes are read.
FAQ
What is the difference between NameID and an attribute? NameID identifies the user for the session. Attributes carry additional profile data such as email, name and groups. Some apps use only the NameID; others require both.
Should I send the email as NameID? Only if the service provider expects it. Email changes can break the account link. A persistent identifier is safer when the app supports it.
Why does the app show a blank name after SSO? The assertion probably carries the attribute under a different name or NameFormat than the app expects. Compare the raw SAML response with the app's mapping.
Can I map groups to roles in SAML? Yes, if the service provider supports it. Send the group or role values the app expects, and keep the list limited to what the app uses.
If you need an identity provider that can serve SAML to many applications with per-application attribute mapping, Casdoor is open source and can also run as a managed instance from $6.67/month billed yearly. See the SAML setup guide and SAML assertions for the next steps.
Sources
- OASIS SAML 2.0 Core specification
- Microsoft Entra SAML token claims reference
- Okta SAML application setup
- Casdoor SAML IdP documentation
- Casdoor SAML provider documentation
Product names are trademarks of their respective owners.