Koen
Koenthis hour

Custom SAML Attributes

Hi all I’m working on integrating Duo as a SAML app with Zitadel, but I’ve run into an issue with attribute mappings. Right now, Zitadel’s SAML attributes are fixed (email, firstName, etc.), but Duo requires custom/renamed attributes for the integration to work. Specifically, Duo expects the following mapping:
| Default Attribute | SAML IdP |
| ------------------------- | ---------------- |
| <Username> | Username |
| <Email Address> | Email |
| <Display Name> | DisplayName |
| <First Name> | FirstName |
| <Last Name> | LastName |
| <Entra Federated User ID> | EntraImmutableID |
| Default Attribute | SAML IdP |
| ------------------------- | ---------------- |
| <Username> | Username |
| <Email Address> | Email |
| <Display Name> | DisplayName |
| <First Name> | FirstName |
| <Last Name> | LastName |
| <Entra Federated User ID> | EntraImmutableID |
Is there currently a way to customize or rename SAML attributes in Zitadel? If not, is this something that’s planned, or would I need to request it as a feature? Thanks in advance!
9 Replies
Ask Inkeep
Ask Inkeepthis hour
Hi @Koen, I'm an AI assistant for ZITADEL. While a team member reviews this question, I'll see if I can find relevant sources for your question. Answer You can add custom attributes to the SAML response in ZITADEL using Actions (JavaScript code hooks) . The function api.v1.attributes.setCustomAttribute allows you to set arbitrary attributes in the SAML response, including renaming or adding new ones to match what Duo expects. For example, you can map ZITADEL user fields or metadata to custom SAML attribute names like "Username", "DisplayName", or "EntraImmutableID" as required by Duo (1) (2) . Example (from ZITADEL docs) :
function setCustomAttribute(ctx, api) {
const user = ctx.v1.getUser()
api.v1.attributes.setCustomAttribute('Username', '', user.preferredUsername)
api.v1.attributes.setCustomAttribute('DisplayName', '', user.displayName)
// Add more mappings as needed, e.g.:
// api.v1.attributes.setCustomAttribute('EntraImmutableID', '', user.<yourField>)
}
function setCustomAttribute(ctx, api) {
const user = ctx.v1.getUser()
api.v1.attributes.setCustomAttribute('Username', '', user.preferredUsername)
api.v1.attributes.setCustomAttribute('DisplayName', '', user.displayName)
// Add more mappings as needed, e.g.:
// api.v1.attributes.setCustomAttribute('EntraImmutableID', '', user.<yourField>)
}
(1) , (2) For more details, see: - Code examples for Actions - SAML Endpoints in ZITADEL ​ To learn more, see the sources I considered: [1] Code examples [2] SAML Endpoints in ZITADEL ​ Feel free to tag @Ask Inkeep with additional questions.
Koen
KoenOPthis hour
@Ask Inkeep please write the entire function using the example from the docs based on the table i provided before. The EntraImmutableID is not required as that is only for Azure.
Ask Inkeep
Ask Inkeepthis hour
Thanks for the follow-up, @Koen. I'll get back to you soon. Answer You can use a ZITADEL Action to set custom SAML attributes in the SAML response. Below is an example function that maps ZITADEL user fields to your required SAML attribute names based on your table (excluding EntraImmutableID) :
/**
* Map ZITADEL user fields to custom SAML attribute names for Duo integration.
* Flow: Complement SAMLResponse, Trigger: Pre SAMLResponse creation
*
* @param ctx
* @param api
*/
function setCustomAttributesForDuo(ctx, api) {
const user = ctx.v1.getUser() ;
// Username
api.v1.attributes.setCustomAttribute('Username', '', user.preferredUsername) ;
// Email Address
api.v1.attributes.setCustomAttribute('Email', '', user.email) ;
// Display Name
api.v1.attributes.setCustomAttribute('DisplayName', '', user.displayName) ;
// First Name
api.v1.attributes.setCustomAttribute('FirstName', '', user.firstName) ;
// Last Name
api.v1.attributes.setCustomAttribute('LastName', '', user.lastName) ;
}
/**
* Map ZITADEL user fields to custom SAML attribute names for Duo integration.
* Flow: Complement SAMLResponse, Trigger: Pre SAMLResponse creation
*
* @param ctx
* @param api
*/
function setCustomAttributesForDuo(ctx, api) {
const user = ctx.v1.getUser() ;
// Username
api.v1.attributes.setCustomAttribute('Username', '', user.preferredUsername) ;
// Email Address
api.v1.attributes.setCustomAttribute('Email', '', user.email) ;
// Display Name
api.v1.attributes.setCustomAttribute('DisplayName', '', user.displayName) ;
// First Name
api.v1.attributes.setCustomAttribute('FirstName', '', user.firstName) ;
// Last Name
api.v1.attributes.setCustomAttribute('LastName', '', user.lastName) ;
}
(1) , (3) ​ To learn more, see the sources I considered: [1] Code examples ​ Feel free to tag @Ask Inkeep with additional questions.
Koen
KoenOPthis hour
@Ask Inkeep that did not work. I might have misconfigured my SAML, what is the "Identity Provider ID (EntityId)" and where can I find it for the applications? I only see the following URL's: - SAML Cert - SSO - SLO
Ask Inkeep
Ask Inkeepthis hour
Thanks for the follow-up, @Koen. I'll get back to you soon. Answer The "Identity Provider ID (EntityID) " in SAML for ZITADEL refers to a unique identifier string for the IdP, sometimes also called the issuer. In ZITADEL, this is found in the SAML metadata for your instance. The EntityID is typically the URL of the metadata endpoint, such as:
https://<your-zitadel-domain>/saml/v2/metadata
https://<your-zitadel-domain>/saml/v2/metadata
This EntityID is the same for all SAML applications within the same ZITADEL instance, as ZITADEL currently publishes instance-wide metadata and endpoints for SAML. The SAML Cert, SSO, and SLO URLs you see are also part of this metadata, but the EntityID is specifically the metadata URL itself (1) (2) . ​ To learn more, see the sources I considered: [1] Authenticate users with SAML [2] Support multiple SAML IdP profiles per instance (unique EntityID and endpoints per org/app) ​ Feel free to tag @Ask Inkeep with additional questions.
Koen
KoenOP23h ago
yea so that did not work either. i want to setup a saml APP, not a saml IdP profile but a saml application to login via zitadel instead of logging in to zitadel
Ask Inkeep
Ask Inkeep23h ago
Thanks for the follow-up, @Koen. I'll get back to you soon. Answer You want to set up a SAML application (Service Provider) in ZITADEL so users can log in to your app via ZITADEL (i.e., ZITADEL acts as the SAML IdP) . In ZITADEL, you create a SAML application by adding a new application of type "SAML" in your project. After selecting "SAML" as the application type, ZITADEL will present you with SAML-specific configuration, including the option to provide or download metadata. The SAML endpoints (including SSO, SLO, and the metadata URL) are provided for your ZITADEL instance and are used by your SAML Service Provider to trust ZITADEL as its IdP. The EntityID for ZITADEL as an IdP is typically the metadata URL, for example:
https://<your-zitadel-domain>/saml/v2/metadata
https://<your-zitadel-domain>/saml/v2/metadata
This EntityID and the endpoints are instance-wide—meaning all SAML applications behind the same ZITADEL instance share the same EntityID and endpoints (1) (2) (3) (4) . To set up your SAML app: 1. Go to your ZITADEL project, add a new application, and choose "SAML" as the type. 2. Configure the SAML settings. You can supply your SP's metadata or manually enter ACS and other details. 3. Use the provided ZITADEL metadata URL as your IdP EntityID in your SAML Service Provider configuration. 4. Download or reference the ZITADEL SAML certificate, SSO, and SLO URLs as needed in your SP. Custom attribute mapping for SAML assertions is limited. While you can add some custom attributes via Actions, the ability to fully rename or remap SAML attributes is not fully documented for SAML application (SP) flows (2) (3) (5) . ​ To learn more, see the sources I considered: [1] Authenticate users with SAML [2] ZITADEL Applications [3] Support multiple SAML IdP profiles per instance (unique EntityID and endpoints per org/app) [4] SAML Service Provider Metadata [5] Zitadel as SAML IdP: Allow to configure NameID value. Currently it is set to username. ​ Feel free to tag @Ask Inkeep with additional questions.
Koen
KoenOP23h ago
@Ask Inkeep so i have set it as follows on Duo Security: - Entity ID: https://sso.zitadel.instance/saml/v2/metadata - Single Sign-On URL: https://sso.zitadel.instance/saml/v2/SSO - Single logout URL: https://sso.zitadel.instance/saml/v2/SLO - Certificate: <uploaded .crt file> but i keep getting "Internal server error" on duo's side (and no it is not a service issue at duo as the other (entra) idp does work. But the azure IdP has a url in the entity ID that also has a sort of application ID from azure in that url)
Ask Inkeep
Ask Inkeep23h ago
Thanks for the follow-up, @Koen. I'll get back to you soon. Answer I wasn't able to find a direct answer, here are some relevant sources: 1. Authenticate users with SAML :
Explains that ZITADEL's SAML EntityID is typically the metadata URL and covers how SAML endpoints (EntityID, SSO, SLO) are structured in ZITADEL. 2. SAML Endpoints in ZITADEL :
Describes the SAML endpoints, required parameters, and general SAML integration details for ZITADEL. Feel free to tag @Ask Inkeep with additional questions.

Did you find this page helpful?