SurePassID Identity Provider
SurePassID Identity Provider Capabilities Document
Version 2026.4
Purpose: This document describes the federation capabilities of the SurePassID Identity Provider (IdP), covering the SAML 2.0, OpenID Connect (OIDC), and Entra ID External Authentication Method (EAM) surfaces. It is intended for Service Provider (SP) and Relying Party (RP) test tool developers to understand what features to test and how the IdP behaves in various scenarios.
Scope: Authentication Component vs. Admin Portal
Important: This component is the authentication runtime only. It authenticates users and issues SAML assertions, OIDC tokens, and EAM results. It does not provide screens for defining your federation setup.
All end-user configuration for SAML 2.0, OIDC, and EAM is performed in the SurePassID Admin Portal. This includes creating and managing tenants/domains, registering Service Providers and OIDC clients, enabling the EAM surface, assigning users and applications, uploading or generating signing certificates, and setting conditional-access policies.
The IdP reads that configuration at runtime. If a capability described below appears unavailable, verify the corresponding setting in the Admin Portal first.
Entra ID configuration references
| Topic | Link |
|---|---|
| Set up SurePassID MFA for Entra ID | https://support.surepassid.com/how-to-set-up-surepassid-mfa-for-entra-id |
| What is SurePassID MFA for Microsoft Entra EAM | https://support.surepassid.com/what-is-surepassid-mfa-microsoft-entra-eam |
Deployment availability
The Identity Provider is included in the on-premises, air-gapped, cloud-gapped, and cloud installations, so the capabilities described in this document are available in every deployment model. A standalone Identity Provider installer is also available for large-scale deployments across distributed systems. See the SurePassID Identity Provider User Guide for details.
1. SAML Protocol Support
1.1 Bindings
SP-to-IdP Bindings (AuthnRequest Reception)
| Binding | Supported | Endpoint | Notes |
|---|---|---|---|
| HTTP-Redirect | ✅ Yes | /login/{domain} or /logon/{domain} |
Query string encoded requests |
| HTTP-POST | ✅ Yes | /login/{domain} or /logon/{domain} |
Form POST with SAMLRequest parameter |
| HTTP-Artifact | ❌ No | N/A | Not implemented |
| SOAP | ❌ No | N/A | Not implemented |
Implementation Location:
SSOService.aspx.cs - ReceiveAuthnRequest()
method
// HTTP-POST detection
if (Request.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase))
{
IdentityProvider.ReceiveAuthnRequestByHTTPPost(...);
}
else
{
IdentityProvider.ReceiveAuthnRequestByHTTPRedirect(...);
}IdP-to-SP Bindings (SAML Response Transmission)
| Binding | Supported | Notes |
|---|---|---|
| HTTP-POST | ✅ Yes (Default) | All SAML responses sent via form POST |
| HTTP-Redirect | ❌ No | Responses too large for URL encoding |
| HTTP-Artifact | ❌ No | Not implemented |
Key Limitation: The IdP only sends SAML responses via HTTP-POST binding. The SP's Assertion Consumer Service (ACS) must accept HTTP-POST.
SLO Bindings (Logout)
| Binding | Direction | Supported | Notes |
|---|---|---|---|
| HTTP-POST | SP→IdP | ✅ Yes | LogoutRequest reception |
| HTTP-Redirect | SP→IdP | ✅ Yes | LogoutRequest reception |
| HTTP-POST | IdP→SP | ✅ Yes | LogoutResponse transmission |
| HTTP-Redirect | IdP→SP | ⚠️ Partial | Falls back to HTTP-POST |
Implementation Note: While HTTP-Redirect is accepted for incoming logout requests, the IdP always sends LogoutResponses via HTTP-POST for reliability.
1.2 NameID Formats
| Format | Supported | URI | Trigger/Configuration |
|---|---|---|---|
| Email Address | ✅ Yes | urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress |
SSOSubjectSource = 0 (email) -
Default |
| Unspecified | ✅ Yes | urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified |
SSOSubjectSource = 1 (username) |
| Persistent | ✅ Yes | urn:oasis:names:tc:SAML:2.0:nameid-format:persistent |
SSOSubjectSource = 3 (persistent) |
| Transient | ✅ Yes | urn:oasis:names:tc:SAML:2.0:nameid-format:transient |
SSOSubjectSource = 4 (transient) |
| Kerberos | ❌ No | Not implemented | |
| X509SubjectName | ❌ No | Not implemented | |
| WindowsDomainQualifiedName | ❌ No | Not implemented |
NameID Generation Details
| Source | Value Used | Format Applied |
|---|---|---|
email (0) |
TablePartnerUser.Email |
emailAddress |
username (1) |
TablePartnerUser.LoginName |
unspecified |
userssoname (2) |
TablePartnerUserSsoActivation.SSOName |
emailAddress if contains @, else
unspecified |
persistent (3) |
SHA256 hash of `(PartnerId | PartnerUserId |
transient (4) |
_transient_{GUID} |
transient |
Persistent NameID Characteristics:
- Deterministic: Same user + same SP always produces the same NameID
- Pairwise: Different SPs receive different NameIDs for the same user
- Opaque: Base64-encoded SHA256 hash (URL-safe:
+→-,/→_) - Stable: Survives server restarts (based on database IDs + configured salt)
Default Behavior: If no
SSOSubjectSource is configured, the IdP defaults to
email (emailAddress format).
1.3 Authentication Context Classes
| AuthnContextClassRef | Supported | When Used |
|---|---|---|
urn:oasis:names:tc:SAML:2.0:ac:classes:Password |
✅ Yes | Always - current implementation |
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport |
❌ No | Not differentiated |
urn:oasis:names:tc:SAML:2.0:ac:classes:X509 |
❌ No | Not implemented |
urn:oasis:names:tc:SAML:2.0:ac:classes:Smartcard |
❌ No | Not implemented |
urn:oasis:names:tc:SAML:2.0:ac:classes:Kerberos |
❌ No | Not implemented |
urn:oasis:names:tc:SAML:2.0:ac:classes:MobileTwoFactorUnregistered |
❌ No | Not returned even when MFA used |
Current Limitation: The IdP always returns
Password as the AuthnContextClassRef, regardless of whether
multi-factor authentication (MFA) was performed. The MFA status is
tracked internally but not reflected in the SAML assertion's
AuthnContext.
Implementation Location:
SAML2Util.cs
var authnStatement = new AuthnStatement
{
AuthnContext = new AuthnContext
{
AuthnContextClassRef = new AuthnContextClassRef(SAMLIdentifiers.AuthnContextClasses.Password)
}
};2. SAML Features
2.1 Request Handling
ForceAuthn Handling
| Feature | Supported | Behavior |
|---|---|---|
ForceAuthn="true" |
✅ Yes | Forces re-authentication |
ForceAuthn="false" |
✅ Yes | Uses existing session if valid |
Implementation: When ForceAuthn="true",
the IdP clears the current session and redirects to the login page.
// SSOService.aspx.cs
var requireLocalLogin = IsLocalLoginRequired(authnRequest.ForceAuthn);
if (requireLocalLogin)
{
Session[spSession.SESSION_CONST] = null; // Clear session
Response.Redirect("SSOLogin.aspx", true); // Force login
}IsPassive Handling
| Feature | Supported | Behavior |
|---|---|---|
IsPassive="true" |
⚠️ Partial | Not explicitly handled |
IsPassive="false" |
✅ Yes | Normal behavior |
Current Behavior: The IdP does not currently check
for IsPassive. If no session exists, the user will be
redirected to login regardless of the IsPassive flag. This
may result in protocol violations when IsPassive="true" is
set but no session exists.
Expected Behavior (not implemented): Should return
urn:oasis:names:tc:SAML:2.0:status:NoPassive when
IsPassive="true" and no session exists.
AssertionConsumerServiceURL Validation
| Validation | Implemented | Notes |
|---|---|---|
| Match against registered ACS | ✅ Yes | Compares with SSOAssertionConsumerServiceURL |
| URL case-insensitive comparison | ✅ Yes | Uses StringComparison.OrdinalIgnoreCase |
| Mismatch logging | ✅ Yes | Logs SSOAcsUrlMismatch audit event |
| Mismatch enforcement | ⚠️ Warn only | Uses registered URL but allows request |
Security Behavior: When the ACS URL in the AuthnRequest doesn't match the registered URL:
- The IdP logs a security warning
- The IdP uses the registered URL (not the requested one)
- The request is allowed to proceed (for backward compatibility)
if (!string.Equals(requestedAcsUrl, registeredAcsUrl, StringComparison.OrdinalIgnoreCase))
{
// Log security event
SsoUtil.WriteLogInfo(..., AuditResultCode.SSOAcsUrlMismatch, ...);
// Use registered URL instead
samlResponse.Destination = registeredAcsUrl;
}NameIDPolicy Handling
| Feature | Supported | Behavior |
|---|---|---|
AllowCreate="true" |
✅ Accepted | Parsed but not enforced |
AllowCreate="false" |
⚠️ Ignored | No validation performed |
Format attribute |
⚠️ Ignored | Uses SP app configuration, not request |
SPNameQualifier |
⚠️ Ignored | Uses SP Entity ID from config |
Current Behavior: The IdP parses the
NameIDPolicy element but does not honor the requested
format. The NameID format is determined by the SP application's
SSOSubjectSource configuration, not by the
AuthnRequest.
Test Implication: SPs cannot dynamically request a specific NameID format per request. The format is fixed per SP configuration.
Scoping / ProxyCount
| Feature | Supported |
|---|---|
Scoping element |
❌ No |
ProxyCount |
❌ No |
IDPList |
❌ No |
RequesterID |
❌ No |
The IdP does not support proxy scenarios or SP scoping hints.
2.2 Response Generation
Signature Configuration
| Element | Signed | Algorithm |
|---|---|---|
| SAML Response | ✅ Yes | RSA-SHA1 or RSA-SHA256 (depending on certificate) |
| SAML Assertion | ✅ Yes | RSA-SHA1 or RSA-SHA256 (depending on certificate) |
Both the outer Response and the inner Assertion are signed with the IdP's private key.
Signature Order:
- Assertion is signed first
(
SAMLAssertionSignature.Generate) - Signed assertion is added to Response
- Response is signed (
SAMLMessageSignature.Generate)
Assertion Encryption
| Feature | Supported |
|---|---|
| Encrypted Assertions | ❌ No |
| EncryptedID | ❌ No |
Current Limitation: The IdP does not encrypt assertions. All assertion content is transmitted in cleartext (though signed). Transport-level security (HTTPS) is relied upon for confidentiality.
Assertion Validity Period
| Attribute | Default Value | Configuration |
|---|---|---|
NotBefore |
Current time (UTC) | Not configurable |
NotOnOrAfter |
Current time + validity period | SSOAssertionTimeSpanHHMMSS per SP |
Default Validity: 20 minutes if no
SSOAssertionTimeSpanHHMMSS is configured.
Format: HH:MM:SS or
DD:HH:MM:SS
- Example:
00:20:00= 20 minutes - Example:
01:00:00:00= 1 day
// SAML2Util.cs
private static TimeSpan GetAssertionTimeSpan(string duration)
{
// Returns TimeSpan.FromMinutes(20) if duration is null/empty
// Parses "HH:MM:SS" or "DD:HH:MM:SS" format
}Clock Skew Handling
The IdP does not add clock skew tolerance to NotBefore.
It uses the exact current server time. Clock skew tolerance should be
handled by the SP.
Recommendation: SPs should allow 2-5 minutes of
clock skew when validating NotBefore and
NotOnOrAfter.
2.3 Attribute Statements
Standard Attributes
| Placeholder | SAML Attribute Name | Source |
|---|---|---|
_username |
Configurable | TablePartnerUser.LoginName |
_email or _emailaddress |
Configurable | TablePartnerUser.Email |
_givenname or _gn |
Configurable | TablePartnerUser.FirstName |
_surname or _sn |
Configurable | TablePartnerUser.LastName |
_fullname or _displayname |
Configurable | FirstName + " " + LastName |
_phone |
Configurable | TablePartnerUser.CellPhone |
_fedid |
Configurable | Assertion Subject (NameID value) |
_organization |
Configurable | TablePartner.PartnerName |
_role |
Configurable | "administrator" or "user" |
_adminrole |
Configurable | "Yes" or "No" |
Group Attributes
| Placeholder | SAML Attribute Name | Source | Multiple Values |
|---|---|---|---|
_groups |
groups |
SurePass groups for user | ✅ Yes (XML multi-value) |
_group |
Configurable | Single SurePass group | ✅ Single value |
_ssoroles |
roles |
SSO roles for user | ✅ Yes (XML multi-value) |
_ssorole |
Configurable | Single SSO role | ✅ Single value |
_adgroups |
Configurable | Active Directory groups | Comma-separated string |
Attribute Configuration
Attributes are configured per SP in the
SSOAttributeListValuePairs field as XML:
<AttributeList>
<attributes>
<attr>
<name>email</name>
<value>_email</value>
</attr>
<attr>
<name>firstName</name>
<value>_givenname</value>
</attr>
<attr>
<name>groups</name>
<value>_groups</value>
</attr>
</attributes>
</AttributeList>Attribute Name Formats
| Format | Usage |
|---|---|
urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified |
Default for all attributes |
urn:oasis:names:tc:SAML:2.0:attrname-format:basic |
Used for groups and roles multi-value
attributes |
urn:oasis:names:tc:SAML:2.0:attrname-format:uri |
Not used |
Note: The attribute Name is set from
the configuration, and FriendlyName is set to the same
value.
Automatic Attribute Mapping from SP Metadata
When importing SP metadata, the IdP automatically maps requested attributes to SurePassId placeholders based on:
| Source Type | Example | Description |
|---|---|---|
| LDAP OIDs | 2.5.4.42, urn:oid:2.5.4.42 |
Standard LDAP attribute OIDs |
| WS-Federation Claims | http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress |
Microsoft identity claims |
| MACE URNs | urn:mace:dir:attribute-def:mail |
Education/research federation attributes |
| Friendly Names | email, firstName, groups |
Human-readable attribute names |
Common OID Mappings:
| OID | Placeholder | Description |
|---|---|---|
0.9.2342.19200300.100.1.3 |
_email |
|
2.5.4.42 |
_givenname |
givenName |
2.5.4.4 |
_surname |
surname (sn) |
2.5.4.3 |
_fullname |
commonName (cn) |
0.9.2342.19200300.100.1.1 |
_username |
uid |
2.5.4.20 |
_phone |
telephoneNumber |
1.2.840.113556.1.2.102 |
_groups |
memberOf (AD) |
2.5.4.10 |
_organization |
organizationName |
Implementation Location:
SurePassClassLib\Utility\Saml2Util.cs -
MapAttributeToPlaceholder() method
3. Single Logout (SLO)
3.1 SP-Initiated SLO
| Feature | Supported | Notes |
|---|---|---|
| Receive LogoutRequest | ✅ Yes | HTTP-POST and HTTP-Redirect |
| Process SessionIndex | ✅ Yes | Looks up session in cache |
| Send LogoutResponse | ✅ Yes | HTTP-POST only |
| Multiple SessionIndexes | ✅ Yes | Processes all in request |
Endpoint: /SAML/SLOService.aspx
SLO Processing Flow
- Receive LogoutRequest (POST or Redirect)
- Validate Request ID (replay attack check)
- Validate Destination (optional, logs if mismatch)
- Lookup Session by SessionIndex in cache
- Validate Signature (if required by SP config)
- Remove Session from IdP cache
- Terminate Local Session
(
FormsAuthentication.SignOut()) - Send LogoutResponse with
Successstatus
3.2 IdP-Initiated SLO
| Feature | Supported | Notes |
|---|---|---|
| Send LogoutRequest to SPs | ❌ Not yet | Planned for future release |
| Session cleanup on IdP logout | ✅ Yes | Clears all sessions for user |
Current Behavior: When a user logs out from the IdP
directly (via /SAML/Logout.aspx):
- The IdP session is terminated
- All SAML session records are removed from cache
- No LogoutRequests are sent to SPs
This means SPs will not be notified when a user logs out from the IdP. The SP sessions will remain active until they expire or the user initiates logout from the SP.
3.3 Partial Logout Handling
The IdP does not implement partial logout scenarios. If session lookup fails or an SP is unreachable:
- The IdP proceeds with local logout
- Returns
Successstatus in LogoutResponse - Does not attempt to contact other SPs
3.4 LogoutResponse Status Codes
| Status Code | When Returned |
|---|---|
urn:oasis:names:tc:SAML:2.0:status:Success |
Logout processed successfully |
urn:oasis:names:tc:SAML:2.0:status:Requester |
Never (not implemented) |
urn:oasis:names:tc:SAML:2.0:status:Responder |
Never (not implemented) |
urn:oasis:names:tc:SAML:2.0:status:PartialLogout |
Never (not implemented) |
Current Limitation: The IdP always returns
Success, even if:
- The session was not found
- The session had already expired
- Internal errors occurred
3.5 SLO Configuration Per SP
| Configuration | Column | Purpose |
|---|---|---|
| SP Logout URL | SSOSPLogoutURL |
Where to send LogoutResponse |
| Logout Binding | SSOSPLogoutBinding |
HTTP-POST or HTTP-Redirect |
| Require Signed Requests | SSORequireSignedLogoutRequests |
Enforce signature on LogoutRequest |
| Sign Responses | SSOSignLogoutResponses |
Sign LogoutResponse sent to SP |
4. IdP-Initiated SSO
4.1 Support Status
| Feature | Supported | Endpoint |
|---|---|---|
| IdP-Initiated (Unsolicited) SSO | ✅ Yes | /SPLauncher.aspx?sid={appId} |
| SP Selection | ✅ Yes | Via sid parameter (SSO App ID) |
| Pre-configured RelayState | ✅ Yes | From SP app configuration |
4.2 Initiation Modes
Configured per SP via SSOAllowableInitiation:
| Value | Mode | Behavior |
|---|---|---|
0 |
Both | SP-initiated and IdP-initiated allowed |
1 |
IdP Only | Only IdP-initiated allowed |
2 |
SP Only | Only SP-initiated allowed |
3 |
IdP + SP Launch | IdP-initiated redirects to SP login first |
4.3 IdP-Initiated Flow
- User authenticates to IdP (login page)
- User selects application from portal
- IdP calls
SPLauncher.aspx?sid={appId} - IdP generates SAML Response (no
InResponseTo) - IdP POSTs response to SP's ACS URL
RelayStatefrom SP configuration is included
4.4 RelayState Handling
| Scenario | RelayState Source |
|---|---|
| SP-initiated | From AuthnRequest (echoed back) |
| IdP-initiated | From SP config (SSORelayState column) |
| No RelayState configured | Empty string |
Implementation:
// SPLauncher.aspx.cs
if (!partnerSsoApps.SSORelayState.IsNullOrEmpty())
{
relayState = partnerSsoApps.SSORelayState;
}
SAML2Util.SendSaml2Assertion(conn, partnerSsoApps, partnerUser, null, relayState, this);4.5 IdP-Initiated Response Differences
| Element | SP-Initiated | IdP-Initiated |
|---|---|---|
InResponseTo |
AuthnRequest ID | Absent |
SubjectConfirmationData/@InResponseTo |
AuthnRequest ID | Absent |
RelayState |
From request | From SP config |
5. Artifact Resolution
| Feature | Supported |
|---|---|
| Artifact Binding | ❌ No |
| ArtifactResolutionService | ❌ No |
| SOAP Binding | ❌ No |
The IdP does not implement the SAML 2.0 Artifact Resolution Protocol. All responses are sent directly via HTTP-POST.
6. Metadata
6.1 Metadata Endpoint
| Feature | Supported | Details |
|---|---|---|
| Metadata Endpoint | ✅ Yes | /meta/{domain} |
| Dynamic Generation | ✅ Yes | Generated per request |
| Caching | ❌ No | Not cached |
URL Pattern:
https://{idp-host}/meta/{domain-name}
Example: https://sso.example.com/meta/acme
6.2 Metadata Elements
<?xml version="1.0" ?>
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
entityID="https://sso.example.com/{sha1-hash-of-domain}/">
<IDPSSODescriptor
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"
WantAuthnRequestsSigned="true">
<KeyDescriptor use="signing">
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>{base64-cert}</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</KeyDescriptor>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified</NameIDFormat>
<SingleSignOnService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="https://sso.example.com/login/{domain}" />
<SingleSignOnService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="https://sso.example.com/login/{domain}" />
<SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="https://sso.example.com/SAML/SLOService.aspx" />
<SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="https://sso.example.com/SAML/SLOService.aspx" />
</IDPSSODescriptor>
<ContactPerson contactType="technical">
<SurName>Support</SurName>
<EmailAddress>support@surepassid.com</EmailAddress>
</ContactPerson>
</EntityDescriptor>6.3 Entity ID Format
The IdP Entity ID is generated as:
{IdP-Root-URL}/{SHA1-Hash-of-Domain}/
Example: https://sso.example.com/a1b2c3d4e5f6.../
This hash-based Entity ID:
- Is unique per tenant/domain
- Doesn't expose the domain name
- Is consistent across requests
7. Error Handling
7.1 SAML Error Status Codes
| Status Code | When Returned | Trigger |
|---|---|---|
urn:oasis:names:tc:SAML:2.0:status:Success |
✅ | Successful authentication |
urn:oasis:names:tc:SAML:2.0:status:Requester |
⚠️ Limited | Invalid request format |
urn:oasis:names:tc:SAML:2.0:status:Responder |
⚠️ Limited | Internal IdP errors |
urn:oasis:names:tc:SAML:2.0:status:AuthnFailed |
❌ Not used | Login failures redirect to login page instead |
urn:oasis:names:tc:SAML:2.0:status:NoPassive |
❌ Not implemented | Should be returned for IsPassive failures |
urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy |
❌ Not implemented | NameIDPolicy not validated |
urn:oasis:names:tc:SAML:2.0:status:RequestDenied |
❌ Not used | Policy failures show error page |
7.2 Error Behavior
Important: The IdP generally does not send SAML error responses. Instead:
| Error Scenario | Behavior |
|---|---|
| Invalid SP Issuer | Error page displayed at IdP |
| Authentication failed | Redirect to login page with error message |
| Policy violation | Error page displayed at IdP |
| Invalid signature | Error page displayed at IdP |
| Replay attack | Error page displayed at IdP |
| Missing ACS URL | Exception thrown |
This means SPs will typically see:
- User remains at IdP (no redirect back)
- Session timeout eventually occurs
- No SAML Response received
7.3 Audit Codes
Internal audit codes used for logging (not exposed in SAML responses):
| Code | Constant | Description |
|---|---|---|
| 9140 | SSOAuthnRequestSignatureInvalid |
AuthnRequest signature failed verification |
| 9141 | SSOAuthnRequestSignatureRequired |
Signature required but not present |
| 9144 | SSOLogoutSignatureRequired |
Logout signature required but missing |
| 9145 | SSOLogoutSignatureInvalid |
Logout signature verification failed |
| - | SSOReplayAttackDetected |
Request ID already used |
| - | SSOAcsUrlMismatch |
ACS URL doesn't match registered |
| - | SSOLogoutDestinationMismatch |
LogoutRequest destination mismatch |
| - | SSOInternalError |
General internal error |
| - | SSOCertificateError |
Certificate loading/signing error |
8. Security & Validation
8.1 AuthnRequest Signature Validation
| Feature | Status | Configuration |
|---|---|---|
| Signature Detection | ✅ Yes | Automatic (checks for ds:Signature) |
| Signature Verification | ✅ Yes | Using SP's registered certificate |
| Require Signed Requests | ⚠️ Metadata only | WantAuthnRequestsSigned="true" in metadata |
Current Behavior:
- If signature is present and invalid → Request rejected
- If signature is present and valid → Request processed
- If signature is absent → Request processed (warning logged)
Note: The
WantAuthnRequestsSigned="true" in metadata is advisory. The
IdP does not currently enforce this at runtime per SP. A future
enhancement could add per-SP SSORequireSignedAuthnRequests
configuration.
8.2 Certificate Requirements for SP Registration
| Certificate Type | Required | Purpose |
|---|---|---|
| SP Signing Certificate | Optional | Verify AuthnRequest/LogoutRequest signatures |
| SP Encryption Certificate | ❌ No | Not used (no assertion encryption) |
| IdP Signing Certificate | ✅ Yes | Sign SAML Responses and Assertions |
SP Registration: SPs can be registered without providing a certificate. If no certificate is provided:
- AuthnRequest signatures will not be validated
- LogoutRequest signatures will not be validated
8.3 Certificate Rollover
| Feature | Supported |
|---|---|
| Multiple SP Certificates | ❌ No |
| IdP Certificate Rollover | Manual process |
| Metadata Auto-Refresh | ❌ No |
Certificate Rollover Process:
- Generate new IdP certificate
- Upload to IdP configuration
- Republish metadata
- SPs must manually re-import metadata
8.4 Replay Attack Prevention
| Feature | Implementation | Duration |
|---|---|---|
| Request ID Tracking | ✅ Yes | 5 minutes (configurable) |
| In-Memory Cache | ✅ Yes | Default |
| SQL Server Cache | ✅ Yes | Optional |
Request ID Cache Behavior:
public static bool TryAddRequestId(string requestId)
{
// Returns true if new request (allowed)
// Returns false if duplicate within expiration window (rejected)
}Cache Expiration: Request IDs are tracked for 5
minutes by default. After expiration, the same ID can be reused.
Configure via SamlCache.RequestIdExpirationMinutes.
Note: This same request ID cache is also used by the EAM authorization endpoint for request object
jtireplay protection, soSamlCache.RequestIdExpirationMinutessets the replay window for both SAML and EAM. See Section 13.
8.5 InResponseTo Validation
| Feature | Implementation |
|---|---|
| Include InResponseTo | ✅ Yes (SP-initiated) |
| Validate InResponseTo | N/A (IdP is the responder) |
| IdP-Initiated (no InResponseTo) | ✅ Supported |
The IdP includes InResponseTo in:
samlp:Response/@InResponseTosaml:SubjectConfirmationData/@InResponseTo
9. Configuration Options
9.1 SP-Specific Settings (PartnerSSOApps Table)
| Setting | Column | Default | Description |
|---|---|---|---|
| SP Entity ID | SSOSPIssuer |
Required | SP's Entity ID / Issuer |
| ACS URL | SSOAssertionConsumerServiceURL |
Required | Assertion Consumer Service URL |
| IdP Issuer | SSOIdPIssuer |
Required | IdP's Entity ID for this SP |
| Audience URI | SSOAudienceURI |
Optional | Audience restriction (defaults to SP Issuer) |
| Subject Source | SSOSubjectSource |
0 (email) | NameID generation source |
| Assertion Validity | SSOAssertionTimeSpanHHMMSS |
00:20:00 | Assertion lifetime |
| Attributes | SSOAttributeListValuePairs |
None | XML attribute configuration |
| RelayState | SSORelayState |
Empty | IdP-initiated RelayState |
| Initiation Mode | SSOAllowableInitiation |
0 (both) | Who can initiate SSO |
| SP Login URL | SSOSPLoginURL |
Optional | For IdP+SPLaunch mode |
| SP Logout URL | SSOSPLogoutURL |
Optional | SLO endpoint |
| Logout Binding | SSOSPLogoutBinding |
HTTP-POST | SLO binding type |
| Require Signed Logout | SSORequireSignedLogoutRequests |
false | Enforce logout signatures |
| Sign Logout Responses | SSOSignLogoutResponses |
true | Sign LogoutResponses |
9.2 Global Settings (web.config / appSettings)
| Setting | Key | Default | Description |
|---|---|---|---|
| Cache Provider | SamlCache.Provider |
InMemory | "InMemory" or "SqlServer" |
| Request ID Expiration | SamlCache.RequestIdExpirationMinutes |
5 | Replay attack window |
| Session Expiration | SamlCache.SessionExpirationHours |
8 | SLO session tracking |
| Persistent NameID Salt | Saml.PersistentNameIdSalt |
System.Salt | Secret for persistent NameIDs |
| Trace Enabled | Server.TraceOn |
false | Enable diagnostic logging |
| Trace Path | Server.TracePath |
App_Data\Trace | Log file location |
Note: The
SamlCache.*settings apply only to the SAML request ID and SAML session caches (and, for the request ID cache, to EAM replay checks). They do not configure the OIDC session cache, which is in-memory only. See Section 13.
9.3 Feature Flags
| Feature | Controlled By | Description |
|---|---|---|
| Remove SSO Group Prefix | Saml2.RemoveSsoGroupPrefix |
Strip "sso_" prefix from groups |
| Remove SSO Role Prefix | Saml2.RemoveSsoRolePrefix |
Strip "primary_" prefix from roles |
10. Known Edge Cases & Limitations
10.1 Compatibility Notes
| SP Type | Known Issues |
|---|---|
| Salesforce | Uses StockAppId detection for special handling |
| Generic SAML SPs | May require specific attribute mapping |
| AWS | Works with standard configuration |
10.2 Character Encoding
| Scenario | Behavior |
|---|---|
| Unicode in NameID | ✅ Supported (UTF-8) |
| Unicode in Attributes | ✅ Supported (UTF-8) |
| Special characters in RelayState | HTML-encoded |
| XML special characters | Properly escaped |
10.3 URL Length Limitations
| Binding | Limit | Notes |
|---|---|---|
| HTTP-Redirect (AuthnRequest) | ~2000 characters | Browser-dependent |
| HTTP-POST (Response) | No practical limit | Always used for responses |
10.4 Session Management
| Scenario | Behavior |
|---|---|
| Multiple SPs per user | Each SP gets separate session tracked |
| Session timeout | Forms auth timeout (configurable) |
| Browser tab isolation | Shared session across tabs |
| Multiple browsers | Separate sessions per browser |
10.5 Partially Implemented Features
| Feature | Status | Notes |
|---|---|---|
IsPassive |
⚠️ Not honored | Always prompts for auth if needed |
NameIDPolicy/@Format |
⚠️ Ignored | Uses SP config instead |
| IdP-initiated SLO propagation | ⚠️ Not implemented | Sessions cleared but SPs not notified |
| Assertion encryption | ❌ Not implemented | Relies on TLS for confidentiality |
| SAML error responses | ⚠️ Limited | Usually shows error page instead |
10.6 Multi-Tenancy Considerations
| Feature | Behavior |
|---|---|
| Domain-based routing | /login/{domain} routes to correct tenant |
| Entity ID uniqueness | Hash of domain ensures uniqueness |
| Certificate per tenant | Each tenant has own signing certificate |
| SP registration | SPs are registered per tenant |
10.7 Known Test Gaps
The following scenarios may need additional testing:
Large Assertion Handling
- Many attributes
- Many group memberships
- Very long attribute values
Clock Skew Scenarios
- Server clock significantly ahead/behind
- Assertion validity edge cases
Concurrent Request Handling
- Same request ID from different IPs
- Rapid successive requests
Character Encoding Edge Cases
- Non-ASCII domain names
- Unicode normalization in NameIDs
Appendix A: Test Checklist for SP Test Tool
A.1 Core SSO Tests
A.2 NameID Tests
A.3 Attribute Tests
A.4 SLO Tests
A.5 Security Tests
A.6 Error Handling Tests
11. OpenID Connect (OIDC) Capabilities
The IdP exposes a general-purpose, multi-tenant OpenID Connect
Provider under oidc/{domain}/*. Clients are registered in
the SurePassID Admin Portal; nothing below is
configured in this component.
11.1 OIDC Endpoints
| Purpose | URL Pattern |
|---|---|
| Discovery | /oidc/{domain}/.well-known/openid-configuration |
| JWKS | /oidc/{domain}/jwks |
| Authorization | /oidc/{domain}/authorize |
| Token | /oidc/{domain}/token |
| UserInfo | /oidc/{domain}/userinfo |
| Logout (RP-initiated) | /oidc/{domain}/logout |
| Consent (internal, post-MFA) | /oidc/{domain}/consent |
| Callback (internal, post-MFA) | /oidc/{domain}/callback |
11.2 Supported Protocol Features
As advertised by the discovery document:
| Capability | Supported Values |
|---|---|
| Response types | code |
| Response modes | query |
| Grant types | authorization_code, refresh_token |
| Scopes | openid, profile, email,
phone, offline_access |
| PKCE code challenge methods | S256 |
| ID token signing algorithms | RS256 |
| Token endpoint auth methods | client_secret_post, client_secret_basic,
none |
| Subject types | public |
| Request object signing | RS256 (request and
request_uri supported) |
| Claims parameter | Supported |
| Logout | Front-channel and back-channel, both session-aware |
Supported claims: sub,
iss, aud, exp, iat,
auth_time, nonce, acr,
amr, azp, at_hash,
c_hash, sid, name,
given_name, family_name,
preferred_username, email,
email_verified, phone_number,
phone_number_verified.
Key constraint: Authorization Code flow with PKCE is the only supported flow. Implicit and hybrid flows are not offered.
11.3 Tenant Gating
The OIDC surface is gated on the tenant's AllowSSO
setting. A disabled or misconfigured tenant returns no discovery
metadata and issues no tokens, so endpoint URLs and signing certificates
are never leaked.
12. Entra ID External Authentication Method (EAM) Capabilities
The EAM surface is an MFA-only OIDC profile consumed
by Microsoft Entra ID under eam/{domain}/*. Entra ID
performs primary authentication and delegates the second factor to
SurePassID.
12.1 EAM Endpoints
| Purpose | URL Pattern |
|---|---|
| Discovery | /eam/{domain}/.well-known/openid-configuration |
| JWKS | /eam/{domain}/jwks |
| Authorization | /eam/{domain}/authorize |
12.2 Supported Protocol Features
| Capability | Supported Values |
|---|---|
| Response types | id_token |
| Response modes | form_post |
| Scopes | openid |
| ID token signing algorithms | RS256 |
| Subject types | public |
| Request object signing | RS256 (request parameter supported) |
Supported claims: sub,
iss, aud, exp, iat,
nonce, acr, amr.
The IdP accepts the user identity either from a signed request object
or via id_token_hint parameter mode, and returns a signed
id_token by form_post asserting that MFA was
completed. acr and amr communicate which
authentication methods were used.
12.3 Entra ID Setup
EAM registration on the Entra side, and the matching tenant configuration on the SurePassID side, are both performed outside this component:
- Set up SurePassID MFA for Entra ID: https://support.surepassid.com/how-to-set-up-surepassid-mfa-for-entra-id
- What is SurePassID MFA for Microsoft Entra EAM: https://support.surepassid.com/what-is-surepassid-mfa-microsoft-entra-eam
13. Cache and Session State Topology
The three protocol surfaces do not share a single cache. Despite the
SamlCache.* configuration prefix, each protocol uses a
different combination of the two underlying caches, which matters when
planning multi-node deployments.
13.1 Cache Usage Per Protocol
| Protocol | Request ID (replay) store | Session store |
|---|---|---|
| SAML 2.0 | SamlRequestIdCache |
SamlRequestIdCache sessions |
| Entra ID EAM | SamlRequestIdCache (shared with SAML) |
Not used |
| OpenID Connect | Not used | OidcSessionCache (separate) |
EAM reuses the SAML request ID cache solely for
replay protection, rejecting a request object whose jti has
already been seen. This provides parity with the SAML AuthnRequest
replay check. EAM does not create or track sessions in the SAML session
cache.
OIDC uses an entirely independent
OidcSessionCache that tracks relying party participants per
session (sid) for back-channel and front-channel logout. It
has no dependency on the SAML caches, and the two are initialized
separately at application startup because OIDC Single Logout and SAML
SLO track session state independently.
13.2 Backing Store and Configuration
| Cache | Backing store | Configurable via |
|---|---|---|
SamlRequestIdCache (request IDs) |
In-memory, or SQL Server table when SamlCache.Provider
is SqlServer |
SamlCache.Provider,
SamlCache.RequestIdExpirationMinutes |
SamlRequestIdCache (sessions) |
In-memory, or SQL Server table when SamlCache.Provider
is SqlServer |
SamlCache.Provider,
SamlCache.SessionExpirationHours |
OidcSessionCache |
In-memory only; no SQL provider | Not configurable; fixed 8-hour session expiration |
13.3 Multi-Node Deployment Considerations
These behaviors are important for load-balanced, distributed, and standalone large-scale deployments:
| Consideration | Impact |
|---|---|
SamlCache.Provider=SqlServer does not apply to
OIDC |
SAML request IDs and sessions become shared across nodes, but OIDC session state remains per-process. |
| OIDC logout on a farm | Without sticky sessions, an OIDC logout request handled by a different node than the one that registered the relying party may not find all participants, so some logout notifications can be missed. |
| EAM replay window is inherited | SamlCache.RequestIdExpirationMinutes governs the EAM
jti replay window. If an Entra request object remains valid
longer than this window, the cache entry can expire before the request
object does. |
| Single-node deployments | All caches are in-process and consistent; none of the above apply. |
For load-balanced deployments, either enable sticky sessions so that OIDC logout requests return to the originating node, or confirm that the deployment topology tolerates per-node OIDC session state.
Appendix B: Quick Reference - Endpoint URLs
SAML 2.0
| Purpose | URL Pattern | Method |
|---|---|---|
| SSO Login | /login/{domain} |
GET (Redirect) or POST |
| SSO Login (Legacy) | /logon/{domain} |
GET (Redirect) or POST |
| Single Logout | /SAML/SLOService.aspx |
GET or POST |
| Metadata | /meta/{domain} |
GET |
| IdP-Initiated Launch | /SPLauncher.aspx?sid={appId} |
GET |
| User Logout | /SAML/Logout.aspx |
GET |
OpenID Connect
| Purpose | URL Pattern | Method |
|---|---|---|
| Discovery | /oidc/{domain}/.well-known/openid-configuration |
GET |
| JWKS | /oidc/{domain}/jwks |
GET |
| Authorization | /oidc/{domain}/authorize |
GET |
| Token | /oidc/{domain}/token |
POST |
| UserInfo | /oidc/{domain}/userinfo |
GET |
| Logout | /oidc/{domain}/logout |
GET |
Entra ID EAM
| Purpose | URL Pattern | Method |
|---|---|---|
| Discovery | /eam/{domain}/.well-known/openid-configuration |
GET |
| JWKS | /eam/{domain}/jwks |
GET |
| Authorization | /eam/{domain}/authorize |
GET or POST |
Document History
| Version | Date | Changes |
|---|---|---|
| 2025.4 | January 2025 | Initial comprehensive document |
| 2026.4 | September 15, 2026 | Rebranded to the SurePassID Identity Provider; added OIDC and EAM capability coverage, Admin Portal configuration scope, and per-protocol cache topology |
This document is intended for technical teams developing Service Provider and Relying Party test tools for the SurePassID Identity Provider. All tenant, application, and protocol configuration is performed in the SurePassID Admin Portal.
© 2013–2026 SurePassID. All rights reserved. Protected by patents pending. SurePassID, the SurePassID logo and design, and Secure SSO are registered trademarks or trademarks of SurePassID, Corp. in the United States and/or other jurisdictions. All other marks and names mentioned herein may be trademarks of their respective companies.
SurePassID 360 Central Avenue #800 St. Petersburg, FL 33701 USA +1 (888) 200-8144 surepassid.com