How to Configure Windows Server for SAML/SSO Integration on Windows Server 2025

Security Assertion Markup Language (SAML) 2.0 is the foundation of federated single sign-on (SSO) for thousands of enterprise web applications — from Salesforce and ServiceNow to AWS and GitHub Enterprise. Active Directory Federation Services (AD FS), bundled with Windows Server, transforms your on-premises Active Directory into a fully capable SAML 2.0 Identity Provider (IdP), enabling users to authenticate once against AD and gain access to cloud applications without entering additional credentials. On Windows Server 2025, AD FS has been updated with improved token encryption, enhanced OAuth 2.0 support, and more granular claim rule authoring. This guide covers the complete SAML SSO configuration process — from understanding the SAML protocol flow to configuring AD FS relying party trusts, mapping attributes, testing claims, and troubleshooting common failures.

Prerequisites

  • Windows Server 2025 with Active Directory Domain Services installed
  • AD FS role installed and a working AD FS farm (at minimum one primary AD FS server)
  • A publicly trusted SSL/TLS certificate for your AD FS federation service name (e.g., adfs.progressiverobot.com)
  • DNS records pointing the AD FS service name to your server or load balancer
  • Domain Administrator and AD FS service account credentials
  • Access to the service provider application (e.g., Salesforce admin console, AWS IAM) to configure the SAML SP side
  • MSOnline or Microsoft.Graph PowerShell modules (optional, for hybrid scenarios)

Step 1: Understand the SAML 2.0 Protocol Flow

Before diving into configuration, it is important to understand the roles involved. The Identity Provider (IdP) is AD FS — it authenticates the user against Active Directory and issues a digitally signed SAML assertion. The Service Provider (SP) is the third-party application (e.g., Salesforce) — it receives the assertion and grants access based on the claims within it. A SAML assertion is an XML document containing the user’s identity attributes (NameID, email, group memberships) and a digital signature that the SP validates against the IdP’s signing certificate.

The typical SP-initiated flow is: user visits the app → app redirects to AD FS with a SAML AuthnRequest → AD FS authenticates the user → AD FS posts a SAML Response to the app’s Assertion Consumer Service (ACS) URL → app validates the signature and grants access.

# Verify AD FS service is running
Get-Service -Name adfssrv | Select-Object Name, Status, StartType

# Check AD FS configuration
Get-AdfsProperties | Select-Object HostName, HttpsPort, FederationServiceName

# View AD FS federation metadata URL (provide this to SPs)
$adfsFqdn = (Get-AdfsProperties).FederationServiceName
Write-Host "Federation Metadata URL: https://$adfsFqdn/FederationMetadata/2007-06/FederationMetadata.xml"

# Confirm SSL certificate binding
netsh http show sslcert ipport=0.0.0.0:443 | Select-String "Certificate Hash"

Step 2: Add a Relying Party Trust for a SAML Application

A Relying Party Trust (RPT) in AD FS represents the SAML SP application. You can create it by importing the application’s SAML metadata URL (the easiest method) or by manually specifying parameters. Most enterprise SaaS applications publish a SAML metadata XML file containing their ACS URL, Entity ID, and certificate — use this when available.

# Method 1: Import relying party trust from a SAML metadata URL (preferred)
$metadataUrl = "https://yourapp.salesforce.com/serviceprovider/metadata"
$rpName      = "Salesforce Production"

Add-AdfsRelyingPartyTrust `
    -Name $rpName `
    -MetadataUrl $metadataUrl `
    -AutoUpdateEnabled $true `
    -MonitoringEnabled $true `
    -Enabled $true

# Method 2: Add manually (when no metadata URL is available)
Add-AdfsRelyingPartyTrust `
    -Name "AWS IAM Identity Center" `
    -Identifier "urn:amazon:webservices" `
    -SamlEndpoint @(
        New-AdfsSamlEndpoint -Protocol "SAMLAssertionConsumer" `
            -Uri "https://signin.aws.amazon.com/saml" `
            -Binding "POST" -Index 0 -IsDefault $true
    ) `
    -IssuanceAuthorizationRules '=> issue(Type = "http://schemas.microsoft.com/authorization/claims/permit", Value = "true");' `
    -Enabled $true

# Verify trust was created
Get-AdfsRelyingPartyTrust -Name $rpName | Select-Object Name, Identifier, Enabled

Step 3: Configure Claim Rules for the Relying Party

Claim rules define which attributes AD FS includes in the SAML assertion sent to the SP. At minimum, you must configure a NameID claim — the primary user identifier the SP uses. Most applications also require the user’s email address and optionally their group memberships or department.

$rpName = "Salesforce Production"

# Rule 1: Send email address as NameID (UPN-formatted email)
$nameIdRule = @'
@RuleTemplate = "MapClaims"
@RuleName = "Send UPN as NameID"
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"]
 => issue(Type = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
          Issuer = c.Issuer,
          OriginalIssuer = c.OriginalIssuer,
          Value = c.Value,
          ValueType = c.ValueType,
          Properties["http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/format"] =
              "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress");
'@

# Rule 2: Send AD email attribute as email claim
$emailRule = @'
@RuleTemplate = "LdapClaims"
@RuleName = "Send LDAP Email"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname",
   Issuer == "AD AUTHORITY"]
 => issue(store = "Active Directory",
          types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
                   "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname",
                   "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"),
          query = ";mail,givenName,sn;{0}", param = c.Value);
'@

# Rule 3: Send group memberships (for app-level access control)
$groupRule = @'
@RuleTemplate = "EmitGroupClaims"
@RuleName = "Send Groups as Role"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid",
   Value == "S-1-5-21-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-1234", Issuer == "AD AUTHORITY"]
 => issue(Type = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role",
          Value = "SalesforceStandardUser",
          Issuer = c.Issuer,
          OriginalIssuer = c.OriginalIssuer,
          ValueType = c.ValueType);
'@

# Apply all rules to the relying party
Set-AdfsRelyingPartyTrust -TargetName $rpName `
    -IssuanceTransformRules ($nameIdRule + $emailRule + $groupRule)

# Verify rules
(Get-AdfsRelyingPartyTrust -Name $rpName).IssuanceTransformRules

Step 4: Configure the Service Provider to Trust AD FS

On the SP side (e.g., Salesforce, AWS, or any SAML-enabled app), you must register AD FS as the trusted IdP. Provide the SP administrator with your AD FS federation metadata XML URL. Alternatively, download the metadata file and upload it to the SP’s SAML configuration console.

# Download AD FS federation metadata for offline upload to SP
$adfsFqdn = (Get-AdfsProperties).FederationServiceName
$metadataUrl = "https://$adfsFqdn/FederationMetadata/2007-06/FederationMetadata.xml"
Invoke-WebRequest -Uri $metadataUrl -OutFile "C:TempADFSMetadata.xml"

# Export the AD FS token-signing certificate (DER format) for SP trust store
$signingCert = (Get-AdfsCertificate -CertificateType "Token-Signing" |
    Where-Object { $_.IsPrimary -eq $true }).Certificate

$certPath = "C:Tempadfs-signing.cer"
[System.IO.File]::WriteAllBytes($certPath, $signingCert.Export("Cert"))
Write-Host "Token-signing certificate exported to: $certPath"
Write-Host "Certificate Thumbprint: $($signingCert.Thumbprint)"
Write-Host "Certificate Expiry: $($signingCert.NotAfter)"

Step 5: Configure SAML Attribute Mapping with Transform Claim Rules

Some SPs expect claims in non-standard formats or with custom attribute names. AD FS transform claim rules allow you to rename, reformat, or derive attribute values before they are included in the SAML assertion.

$rpName = "AWS IAM Identity Center"

# Transform rule: map AD department to a custom AWS role attribute
$transformRule = @'
@RuleName = "Map Department to AWS Role"
c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]
 => issue(Type = "https://aws.amazon.com/SAML/Attributes/Role",
          Value = "arn:aws:iam::123456789012:role/ADFS-Admins,arn:aws:iam::123456789012:saml-provider/ADFS");
'@

# Issuance authorization: only users in specific group can access the SP
$authRule = @'
@RuleTemplate = "Authorization"
@RuleName = "Permit AWS Users Group"
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid",
   Value =~ "^S-1-5-21-"]
 => issue(Type = "http://schemas.microsoft.com/authorization/claims/permit", Value = "true");
'@

Set-AdfsRelyingPartyTrust -TargetName $rpName `
    -IssuanceTransformRules $transformRule `
    -IssuanceAuthorizationRules $authRule

# List all relying party trusts and their enabled state
Get-AdfsRelyingPartyTrust | Select-Object Name, Enabled, Identifier | Format-Table -AutoSize

Step 6: Test with the AD FS Claims Rules Analyzer

AD FS includes a built-in diagnostic tool you can use from the AD FS Management console: navigate to Diagnostics → Test Endpoint. From PowerShell, you can simulate claim issuance to validate the output before deploying to production users.

# Test claim issuance for a specific user against a relying party
$rpName   = "Salesforce Production"
$testUser = "[email protected]"

# Get the claims the user would receive (simulated)
$claims = Get-AdfsClaimsProviderTrust | ForEach-Object {
    Test-AdfsTrust -ClaimsProviderTrustIdentifier $_.Identifier `
        -RelyingPartyTrustIdentifier (Get-AdfsRelyingPartyTrust -Name $rpName).Identifier
}

# Check AD FS event logs for claim issuance and errors
Get-WinEvent -LogName "AD FS/Admin" -MaxEvents 50 |
    Where-Object { $_.Id -in @(299, 324, 364, 411, 412) } |
    Select-Object TimeCreated, Id, Message |
    Format-List

# EventID 364 = Relying party not found / access denied
# EventID 411 = Token validation failed
# EventID 412 = SAML request parsing error
# EventID 299 = Token successfully issued

# Enable verbose AD FS tracing for deep diagnostics
Set-AdfsProperties -LogLevel @("FailureAudits","SuccessAudits","Information","Verbose")

Step 7: Understand SAML vs OIDC/OAuth 2.0

While SAML 2.0 remains the dominant SSO protocol for enterprise SaaS applications, newer applications increasingly prefer OpenID Connect (OIDC) over OAuth 2.0. AD FS on Windows Server 2025 supports both protocols. OIDC uses JSON Web Tokens (JWT) instead of XML assertions, which are simpler for mobile and single-page applications. When adding new applications, choose SAML for legacy enterprise apps and OIDC for modern apps and APIs.

# Add an OIDC/OAuth2 application group in AD FS (modern apps)
$appGroupName = "ModernWebApp"
Add-AdfsApplicationGroup -Name $appGroupName -Description "OIDC applications"

# Add a web API resource within the group
Add-AdfsWebApiApplication -ApplicationGroupIdentifier $appGroupName `
    -Name "ModernWebApp API" `
    -Identifier "https://api.progressiverobot.com" `
    -AccessControlPolicyName "Permit Everyone"

# Add a native client (public client) for PKCE flows
Add-AdfsNativeClientApplication -ApplicationGroupIdentifier $appGroupName `
    -Name "ModernWebApp Client" `
    -Identifier "native-client-id-001" `
    -RedirectUri "https://app.progressiverobot.com/callback"

# For SAML: list all relying parties using SAML protocol
Get-AdfsRelyingPartyTrust |
    Where-Object { $_.SamlEndpoints.Count -gt 0 } |
    Select-Object Name, @{N="ACS";E={$_.SamlEndpoints[0].Location}}

Conclusion

Configuring Windows Server 2025 as a SAML IdP through AD FS gives your organization a powerful, on-premises-controlled single sign-on hub that can federate identity to virtually any SAML 2.0-compatible application. By carefully defining relying party trusts, crafting precise claim rules, and validating output with the AD FS diagnostic tools and event logs, you can ensure that users receive exactly the right attributes in their assertions while access control remains enforced at the AD FS layer. As your application landscape evolves, AD FS’s support for both SAML 2.0 and OIDC/OAuth 2.0 means you are not locked into a single protocol — you can serve legacy enterprise applications and modern cloud-native apps from the same federation infrastructure. Monitor EventID 364 and related audit events proactively to catch trust misconfigurations before users are affected.