Enterprise IT organizations have seen enough half-baked SSO integrations to have a standard set of requirements. When they evaluate a new SaaS product that claims to support SSO, they will ask about attribute mapping, provisioning, logout, and certificate management. If you cannot answer these questions with working features rather than promises, the deal gets blocked at the IT review stage regardless of what the business buyer wants. Here is the complete list of what they check and what your implementation needs to deliver.
1. SAML 2.0 and OIDC support
Enterprise organizations standardize on either SAML or OIDC. Larger enterprises with legacy identity infrastructure (Ping Identity, CA SiteMinder, ADFS) will require SAML 2.0. Newer organizations on Okta, Azure AD, or Google Workspace often prefer OIDC. You need both. Do not assume one is sufficient.
2. SP metadata URL
IT administrators configure SSO by exchanging metadata between their IdP and your service. Your service provider metadata must be available at a stable URL and include your entity ID, ACS URL, and signing certificate. If this URL changes or does not exist, they cannot configure the integration automatically.
<!-- Example SP metadata (SAML 2.0) -->
<EntityDescriptor
entityID="https://app.yourproduct.com/saml/metadata"
xmlns="urn:oasis:names:tc:SAML:2.0:metadata">
<SPSSODescriptor
AuthnRequestsSigned="true"
WantAssertionsSigned="true"
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor use="signing">
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIICxDCCAaygAwIBAgI...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</KeyDescriptor>
<AssertionConsumerService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="https://app.yourproduct.com/saml/acs"
index="1" isDefault="true"/>
</SPSSODescriptor>
</EntityDescriptor>
3. Attribute mapping configuration
Every IdP sends user attributes under different claim names. Okta might send email as email; Azure AD might send it as http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress. IT administrators need to be able to map their IdP's attribute names to your application's expected fields without writing code.
// Configurable attribute mapping stored per SSO connection
interface SsoAttributeMapping {
connection_id: string;
email: string; // e.g., "email" or the full URI
first_name: string; // e.g., "firstName" or "given_name"
last_name: string;
display_name?: string;
department?: string;
groups?: string; // attribute containing group membership
}
function extractUserFromSamlAssertion(
attributes: Record<string, string[]>,
mapping: SsoAttributeMapping
): SsoUser {
return {
email: attributes[mapping.email]?.[0],
firstName: attributes[mapping.first_name]?.[0],
lastName: attributes[mapping.last_name]?.[0],
displayName: mapping.display_name
? attributes[mapping.display_name]?.[0]
: undefined,
groups: mapping.groups
? (attributes[mapping.groups] ?? [])
: []
};
}
4. Just-in-time provisioning
JIT provisioning creates user accounts automatically on first SSO login, without requiring pre-provisioning through your UI. IT wants to be able to assign users to your application in their IdP and have those users automatically get accounts on their first login. The alternative — manually pre-creating users in your dashboard — does not scale and creates synchronization nightmares.
5. SCIM provisioning
JIT provisioning handles first login but not deprovisioning. When an employee is terminated, IT needs to be able to remove their access from your application the moment their IdP account is disabled. SCIM (System for Cross-domain Identity Management) is the standard protocol for this. You need to implement the SCIM 2.0 user and group endpoints so that the IdP can push user lifecycle events to your application.
// SCIM 2.0 user update endpoint (handles deprovisioning)
app.patch('/scim/v2/Users/:id', async (req, res) => {
const { Operations } = req.body;
for (const op of Operations) {
if (op.op === 'Replace' && op.path === 'active' && op.value === false) {
// User is being deprovisioned in the IdP
await db.users.update(
{ scim_id: req.params.id },
{
sso_disabled: true,
sso_disabled_at: new Date(),
// Revoke all active sessions
}
);
await revokeAllUserSessions(req.params.id);
}
}
const user = await db.users.findByScimId(req.params.id);
res.json(toScimUser(user));
});
6. Group-to-role mapping
Organizations manage access through groups in their IdP (AD groups, Okta groups). They need to map those groups to roles in your application. When a user's group membership changes in the IdP, their permissions in your application should update on the next login (or immediately via SCIM).
7. Single logout (SLO)
When a user signs out of the IdP (or is forcibly signed out by IT), that logout must propagate to your application. SAML SLO and OIDC front-channel/back-channel logout cover this. If your application maintains sessions that persist after the IdP session is terminated, terminated employees can continue to access your application until their session expires — this is a frequent compliance finding.
8. Session duration alignment
IT needs to be able to set maximum session durations that align with their security policy. Most enterprise security policies mandate re-authentication after 8–12 hours. Your application must respect the session duration communicated in the SAML assertion or OIDC token, and must not allow sessions to persist beyond the IdP's configured limit.
9. Certificate rotation without downtime
SAML signing certificates expire. IdPs rotate them, sometimes with little notice. Your integration must support importing a new IdP certificate while still accepting assertions signed with the old certificate during the transition period. This is typically handled by allowing multiple active IdP certificates.
// Multiple IdP certificates for zero-downtime rotation
async function validateSamlAssertion(
assertionXml: string,
connectionId: string
): Promise<void> {
const connection = await db.ssoConnections.findById(connectionId);
const certificates = connection.idp_certificates; // array, supports multiple
let lastError: Error | null = null;
for (const cert of certificates) {
try {
await saml.validateSignature(assertionXml, cert);
return; // validation succeeded with this cert
} catch (err) {
lastError = err as Error;
}
}
throw new Error(`SAML signature validation failed: ${lastError?.message}`);
}
10–15. Additional checklist items
- 10. IP allowlisting: some organizations require that SSO authentication only be accepted from specific IP ranges. Your integration should support IP-based access control per SSO connection.
- 11. Audit log of SSO events: every SSO login, provisioning event, and SLO must appear in an audit log that IT can access or export to their SIEM.
- 12. Fallback authentication: IT needs to know what happens when the IdP is unavailable. Can admins still log in with a password? Is there a break-glass procedure?
- 13. Multiple IdP connections: enterprises with subsidiaries or acquisitions may have multiple identity providers. Your application should support multiple SSO connections for a single organization with routing based on email domain.
- 14. Domain verification: before enabling SSO for a domain, you should require proof of ownership (DNS TXT record or file upload). Without this, anyone can claim to be an SSO connection for google.com.
- 15. Test mode without breaking production: IT needs to test the SSO configuration before enabling it for all users. Provide a test flow that lets administrators verify the configuration without locking out existing users.