I have my own ADFS deployed online.
I made it trust some SPs like SAMLtest.id During the configuration of this trust I only filled in two things each time:
And that's all. No SP metadata file, just these two pieces of information. Then it works, SAMLtest.id SP is trusted by my ADFS, I can perform an SSO authentication. The same thing is working with some internal SPs.
Then each SP trust my ADFS IdP from its metadata file.
But now we're developing a SP based on the SAML Crewjam library, and a strange behaviour happens. In order to perform the trust we give also give to the ADFS the ACS and the identifier, but apparently it also needs to verify the SAML signature because an error occurs when I try to perform an SSO authentication:
MSIS0037: No signature verification certificate found for issuer 'https://<my_sp>/self-service/methods/saml/acs'
The error message is pretty clear, so I add the certificate used by the SP to sign the SAML request and now it work, I can perform the SSO connexion.
That's what I don't understand: why some SPs are trusted by my ADFS without needing to add the signature verification certificate while others need it?
Here's the SAML request of SAMLtest.id (that works without the signature verification certificate):
<samlp:AuthnRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
AssertionConsumerServiceURL="https://samltest.id/Shibboleth.sso/SAML2/POST"
Destination="https://<my_adfs_idp>/adfs/ls/"
ID="_22d23a57f0d6359675246083cc8faf2e"
IssueInstant="2022-02-22T13:45:40Z"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Version="2.0">
<saml:Issuer
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://samltest.id/saml/sp
</saml:Issuer>
<samlp:NameIDPolicy AllowCreate="1" />
</samlp:AuthnRequest>
Here's the SAML request of our custom SP based on Crewjam (that won't work without the signature verification certificate):
<samlp:AuthnRequest
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
ID="id-97c753d96c1a9bcabcb4931465d9b7dcb9e35e21"
Version="2.0"
IssueInstant="2022-02-22T10:42:53.434Z"
Destination="https://<my_adfs_idp>/adfs/ls/"
AssertionConsumerServiceURL="https://<my_sp>/self-service/methods/saml/acs"
ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
>
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://<my_sp>/self-service/methods/saml/acs</saml:Issuer>
<samlp:NameIDPolicy AllowCreate="true" />
</samlp:AuthnRequest>
Edit1:
Here's some additional information obtained via Get-AdfsRelyingPartyTrust.
For SAMLtestid:
AllowedAuthenticationClassReferences : {}
EncryptionCertificateRevocationCheck : CheckChainExcludeRoot
PublishedThroughProxy : False
SigningCertificateRevocationCheck : CheckChainExcludeRoot
WSFedEndpoint :
AdditionalWSFedEndpoint : {}
ClaimsProviderName : {}
ClaimsAccepted : {}
EncryptClaims : True
Enabled : True
EncryptionCertificate :
Identifier : {https://samltest.id/saml/sp}
NotBeforeSkew : 0
EnableJWT : False
AlwaysRequireAuthentication : False
Notes :
OrganizationInfo :
ObjectIdentifier : 29c4b776-ff8f-ec11-8e3f-fd3950cefa56
ProxyEndpointMappings : {}
ProxyTrustedEndpoints : {}
ProtocolProfile : WsFed-SAML
RequestSigningCertificate : {}
EncryptedNameIdRequired : False
SignedSamlRequestsRequired : False
SamlEndpoints : {Microsoft.IdentityServer.Management.Resources.SamlEndpoint}
SamlResponseSignature : AssertionOnly
SignatureAlgorithm : http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
TokenLifetime : 0
AllowedClientTypes : Public, Confidential
IssueOAuthRefreshTokensTo : AllDevices
RefreshTokenProtectionEnabled : True
RequestMFAFromClaimsProviders : False
ScopeGroupId :
ScopeGroupIdentifier :
DeviceAuthenticationMethod :
Name : SAML Test ID
AutoUpdateEnabled : False
MonitoringEnabled : False
MetadataUrl :
ConflictWithPublishedPolicy : False
IssuanceAuthorizationRules :
IssuanceTransformRules : @RuleTemplate = "LdapClaims"
@RuleName = "Send LDAP Attributes as Claims"
c:[Type ==
"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname",
Issuer == "AD AUTHORITY"]
=> issue(store = "Active Directory", types =
("http://schemas.xmlsoap.org/claims/Group",
"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/name",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"), query =
";title,mail,givenName,displayName,sn,sAMAccountName;{0}", param = c.Value);
DelegationAuthorizationRules :
LastPublishedPolicyCheckSuccessful :
LastUpdateTime : 1/1/1900 1:00:00 AM
LastMonitoredTime : 1/1/1900 1:00:00 AM
ImpersonationAuthorizationRules :
AdditionalAuthenticationRules :
AccessControlPolicyName : Permit everyone
AccessControlPolicyParameters :
ResultantPolicy : RequireFreshAuthentication:False
IssuanceAuthorizationRules:
{
Permit everyone
}
For my SP based on Crewjam (before I add the certificate):
AllowedAuthenticationClassReferences : {}
EncryptionCertificateRevocationCheck : CheckChainExcludeRoot
PublishedThroughProxy : False
SigningCertificateRevocationCheck : CheckChainExcludeRoot
WSFedEndpoint :
AdditionalWSFedEndpoint : {}
ClaimsProviderName : {}
ClaimsAccepted : {}
EncryptClaims : True
Enabled : True
EncryptionCertificate :
Identifier : {https://samltest.id/saml/sp}
NotBeforeSkew : 0
EnableJWT : False
AlwaysRequireAuthentication : False
Notes :
OrganizationInfo :
ObjectIdentifier : 29c4b776-ff8f-ec11-8e3f-fd3950cefa56
ProxyEndpointMappings : {}
ProxyTrustedEndpoints : {}
ProtocolProfile : WsFed-SAML
RequestSigningCertificate : {}
EncryptedNameIdRequired : False
SignedSamlRequestsRequired : False
SamlEndpoints : {Microsoft.IdentityServer.Management.Resources.SamlEndpoint}
SamlResponseSignature : AssertionOnly
SignatureAlgorithm : http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
TokenLifetime : 0
AllowedClientTypes : Public, Confidential
IssueOAuthRefreshTokensTo : AllDevices
RefreshTokenProtectionEnabled : True
RequestMFAFromClaimsProviders : False
ScopeGroupId :
ScopeGroupIdentifier :
DeviceAuthenticationMethod :
Name : SAML Test ID
AutoUpdateEnabled : False
MonitoringEnabled : False
MetadataUrl :
ConflictWithPublishedPolicy : False
IssuanceAuthorizationRules :
IssuanceTransformRules : @RuleTemplate = "LdapClaims"
@RuleName = "Send LDAP Attributes as Claims"
c:[Type ==
"http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname",
Issuer == "AD AUTHORITY"]
=> issue(store = "Active Directory", types =
("http://schemas.xmlsoap.org/claims/Group",
"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/name",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn"), query =
";title,mail,givenName,displayName,sn,sAMAccountName;{0}", param = c.Value);
DelegationAuthorizationRules :
LastPublishedPolicyCheckSuccessful :
LastUpdateTime : 1/1/1900 1:00:00 AM
LastMonitoredTime : 1/1/1900 1:00:00 AM
ImpersonationAuthorizationRules :
AdditionalAuthenticationRules :
AccessControlPolicyName : Permit everyone
AccessControlPolicyParameters :
ResultantPolicy : RequireFreshAuthentication:False
IssuanceAuthorizationRules:
{
Permit everyone
}
As you can see nothing's different between these two configurations except for the Identifier, ObjectIdentifier and the Name.
The SignedSamlRequestsRequired is False in both cases.
Edit2:
Here's the ADFS IdP metadata file given to the SPs. As an ADFS metadata file is pretty huge, here's a simplified version leading exactly to the same result (certificates hidden for greater clarity):
<?xml version="1.0"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" validUntil="2022-02-24T13:41:36Z" cacheDuration="PT1646142096S" entityID="http://<my_adfs_idp>/adfs/services/trust">
<md:IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://<my_adfs_idp>/adfs/ls/"/>
</md:IDPSSODescriptor>
</md:EntityDescriptor>
Here's the SP metadata file (certificates hidden as well for the same reason), but not given to the ADFS IdP as it takes only the ACS and Identifier values (and sometimes the signature verification certificate, that's my issue):
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" validUntil="2022-02-26T10:50:18.198Z" entityID="https://<my_sp>/self-service/methods/saml/acs">
<SPSSODescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" validUntil="2022-02-26T10:50:18.198103727Z" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol" AuthnRequestsSigned="true" WantAssertionsSigned="true">
<KeyDescriptor use="encryption">
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Certificate xmlns="http://www.w3.org/2000/09/xmldsig#">...</X509Certificate>
</X509Data>
</KeyInfo>
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"></EncryptionMethod>
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes192-cbc"></EncryptionMethod>
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"></EncryptionMethod>
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"></EncryptionMethod>
</KeyDescriptor>
<KeyDescriptor use="signing">
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Certificate xmlns="http://www.w3.org/2000/09/xmldsig#">...</X509Certificate>
</X509Data>
</KeyInfo>
</KeyDescriptor>
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://<my_sp>:4455/saml/slo" ResponseLocation="https://<my_sp>:4455/saml/slo"></SingleLogoutService>
<AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://<my_sp>/self-service/methods/saml/acs" index="1"></AssertionConsumerService>
<AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="https://<my_sp>/self-service/methods/saml/acs" index="2"></AssertionConsumerService>
</SPSSODescriptor>
</EntityDescriptor>
Can you check the HTTP headers for the two requests? Signatures on a SAML Auth Request usually come in the form of an HTTP parameter, not as part of the request XML. I expect your first item will have those parameters and the second will not.
Even if you configure ADFS to not make signed requests required, it's been my experience that if the request has a signature on it, ADFS will try to verify it anyway - and in this case can't since you don't have the relevant RP cert installed.