Which authentication providers do you support?
We support OpenIddict. You will need to install our framework-specific package.
What version of the package should I use?
- I am a SAML Service Provider: I want to allow users to log in using an external SAML Identity Provider:
- Use Rsk.Saml
- I am a SAML Identity Provider: I want to allow users in external systems to log in using my user store:
- I am using OpenIddict
- Use Rsk.Saml.OpenIddict
Can I integrate the Rsk.Saml component in a .NET Framework application?
Our SAML component only supports ASP.NET Core applications. This means that you cannot use our component directly inside your .NET Framework application.
However, if your .NET Framework application uses OpenIddict for sign-in, you can use our component to federate with an external SAML identity provider. This is because all the SAML interactions would occur in the OpenIddict codebase.
Do you have any samples available?
We have a GitHub repository with several different use cases.
Can I see your source code?
Rock Solid Knowledge's SAML component is closed source, and it is a violation of our EULA to decompile our source code. However, you can purchase our source code. For pricing, please get in touch with us at sales@openiddictcomponents.com.
How can I view a SAML message?
See our Troubleshooting documentation.
How can I retrieve my metadata document?
If you are acting as the SAML Identity Provider, you can retrieve your metadata by visiting the path /saml/metadata
.
If you are acting as the SAML Service Provider, you can retrieve your metadata by visiting the path configured in your ServiceProviderOptions.MetadataPath
.
The default value for MetadataPath
configuration option is /saml
.
Please be aware that if you are acting as both a SAML Service Provider and a SAML Identity Provider, you will have two separate metadata documents for both sides of the SAML protocol.
If you are integrating with multiple external identity providers, you will have a unique metadata path, and hence metadata document, per identity provider. You can read more on this in our Federating with Multiple External Providers documentation.
The SAML signature is valid but uses an untrusted key
When our component receives a signed SAML message, it will first validate the signature in the message using the key configured for the IdP or SP. If signature validation fails, it will attempt to validate the signature using the key embedded in the SAML message itself. If validation succeeds using the embedded key, the key is marked as untrusted, and the overall validation will fail.
To resolve this, check that you have imported the correct public key from your partner's metadata file. If you are using the correct key, you will need to contact your partner to find out why they are advertising the wrong key in their metadata file.
How do I map between Identity provider and SAML Claims?
See our IdP Claims Mapping and Assertion Attributes documentation.
When acting as a Service Provider, you can provision additional claims that may be needed by using a callback method, which is triggered after authentication. Check out the authorization controller in this sample.
The IssueInstant is too old to trust or the IssueInstant is in the future
To account for differences in server times or other factors, the options class contains a setting called TimeComparisonTolerance
. This setting will allow a SAML message's IssueInstant validation to succeed if the time is still within range of the additional tolerance. Microsoft uses a default setting of 300 seconds, but we recommend using the lowest possible value.
Unrecognized SAML service provider - cannot find Client/SP configuration
When acting as an Identity Provider, each Service Provider requires an OpenIddict Client object and a matching Service Provider object.
The Client's ClientId must match the EntityId of the Service Provider and vice versa.
Client is not configured for SAML2P
The OpenIddict Client object is not configured for SAML. The ProtocolType
of the Client must be "saml2p". The constant OpenIddictConstants.ProtocolTypes.Saml2p
can also be used.
Invalid ACS URL requested or Unable to determine correct ACS endpoint
The component cannot find a corresponding Assertion Consumer Service (ACS) endpoint on the ServiceProvider
object for the authentication request. Ensure that the AssertionConsumerServices
collection contains an endpoint of the correct binding, location and index for the request. The Service Provider metadata should provide details for all its ACS Endpoints that need to be configured.
How do I use SAML in a mobile app or SPA?
We do not recommend using SAML directly in either mobile or Single Page Applications (SPA). Since SAML was not designed for these public application types, you may experience compatibility and security issues.
We recommend using OpenID Connect in mobile applications and SPAs. This protocol was designed with these application types in mind and works alongside OAuth, allowing for API authorization.
Using an OpenID Provider such as OpenIddict, you can use both OpenID Connect and our SAML component. This will allow you to authenticate users, no matter the type of the requesting application, and/or support server-side applications that use SAML.
You can read more on this in our article Why You Wouldn’t Use SAML in a SPA and Mobile App.
What are requestId and logoutId parameters?
The requestId and logoutId query string parameters are automatically included in the URL when the SAML login process errors or during user interaction at the SLO (logout) endpoint.
The request ID allows you to retrieve information about the current SAML request by passing it to the ISamlInteractionService
, such as the ID of the requesting application.
The logout ID allows you to complete single logout for the current session using the ISamlInteractionService.GetSamlSignOutFrameUrl
method.
You can change the requestId query string key to something else by setting the RequestIdParameter
property on your SamlUserInteractionOptions
.
How do I change the NameId?
See our Configuring NameId documentation.
Invalid SAML message issuer
This error is thrown when there is a mismatch found between the configured EntityId of the partner Identity Provider (IdP) and the issuer specified in the SAML message sent by the IdP. Please check that the IdP EntityId specified in your Saml2pAuthenticationOptions.IdentityProviderOptions
configuration matches the EntityId specified in the IdP metadata.
If you are federating with multiple identity providers, the callback paths used for each IdP must be unique. Read more on this in our Federating With Multiple External Providers documentation.
IdP Metadata is Unsigned Error ("No signature element could be found in the metadata document's parent node")
Various elements in a metadata document can be digitally signed, as indicated by the element's inclusion of a signature
node. A digital signature is used to validate the integrity of the metadata document. A digital signature is optional and may not be present in the metadata document.
By default, our SAML component requires the metadata document to be digitally signed, and an error will be thrown if a signature node is missing. However, you can override this behavior by setting the option RequireValidMetadataSignature
to be false, which will allow signature validation errors to be ignored.
Missing SAML message destination
A SAML message can optionally contain a destination
attribute, which is a URI reference indicating the address to which the message has been sent. This is useful to prevent malicious forwarding of requests to unintended endpoints.
By default, our SAML component requires the destination
attribute to be present in SAML messages and will throw an error if it is missing; however, you can override this behavior by setting the option RequireSamlMessageDestination
to be false.
Invalid SAML message destination
A SAML message can contain the destination address to which the message has been sent. The incoming message validation will fail if the destination value does not match your configuration.
If you are acting as the SAML service provider, the authentication response message should be sent to your AssertionConsumerService
endpoint (CallbackPath
config option), and a logout request/response should be sent to your SingleLogoutService
endpoint (SignedOutCallbackPath
config option).
If you are acting as the SAML identity provider, the authentication request should be sent to your SingleSignOnService
endpoint (/saml/sso
), and a logout request/response should be sent to your SingleLogoutService
endpoint (/saml/slo
).
If your partner provider is sending an incorrect message destination, it may be that they have misconfigured your details on their end. We recommend sending them your metadata document and ensuring that they have your correct details.
If the difference in the destination value is HTTP vs HTTPS, check out the FAQ "My application is running on HTTPS, but the SAML component is seeing HTTP".
My application is running on HTTPS, but the SAML component is seeing HTTP
You may observe this issue through various errors, such as:
- The incoming message validation fails due to an invalid destination
- The generated metadata contains endpoints with HTTP instead of HTTPS
If you are running your SAML implementation behind a load balancer or a proxy, this issue is usually due to misconfiguration. It could be that the load balancer is not setting the Forwarded Headers, or your application is not listening to them properly.
We determine the application path using the HttpContext
object.
This means that our component will correctly use the path you have configured for your application.
We recommend checking the Microsoft documentation on configuring your ASP.NET Core application to work with proxy servers and load balancers.
SAMLResponse contains incorrect audience restriction
This error is thrown when the AudienceRestriction
value in the received assertion does not match your service provider Entity ID (unique identifier).
The received AudienceRestriction
should exactly match the value you have specified in the configuration option ServiceProviderOptions.EntityId
.
It may be that the Identity Provider has misconfigured your Entity ID on their end. We recommend sending them your metadata document and ensuring that they have your correct details.
If you are using Azure AD, please note that they prefix your entity ID with spn:
if your entity ID is not a URI.
We expect an exact string match to the entity ID value, as the SAML specification does not specify any prefixes.
This means that our SAML response validation will fail if there is an spn:
prefix in the AudienceRestriction
value.
You can get around this issue by prefixing your Entity ID value (ServiceProviderOptions.EntityId
) to match the convention used by Azure AD.
SamlAssertion must have at least one statement
This error is thrown when there are no other attributes for the user except Name ID (unique identifier) in the SAML assertion.
If you are the identity provider generating the failing assertion, you can resolve this issue by adding some other claims for the user, such as family name, given name, and email. You should then start generating SAML tokens successfully.
If the user already has other claims and you are not getting the claims you expect, check that the requesting Client has the correct requested scopes and that those scopes contain the desired claims.
Please ensure that the client has access to the openid
and profile
scopes, as well as any other scopes that it requires.
The email
claim is not included in the profile
scope.
You must add the email IdentityResource and enable your Client access to the email
scope.
Check out our Claims Mapping and Assertion Attributes documentation for more details.
If you are the service provider that is receiving the failing assertion, we recommend contacting your identity provider to add additional claims for the user.
Sign in request has expired
Our SAML service provider throws this error when the correlation cookie is not present or cannot be read.
The correlation cookie is used to remember information about the initial SAML request. When you issue a SAML request, the service provider creates a correlation cookie that contains information about the request, such as the request ID, relay state, and authentication properties. This cookie is consumed when the response is received.
There are a few reasons why the correlation cookie may not be present when the response is received:
- The login process at the identity provider took some time to complete, and your service provider no longer trusts it. We set the correlation cookie expiration to 15 minutes by default. Generally, 15 minutes is enough time to complete any extended 2-factor authentication that might be involved during a log-on process. However, you can change the expiration using the
CorrelationCookie.Expiration
property onSaml2pAuthenticationOptions
. - Browsers are taking the initiative to block third-party cookies. When affected by this, your browser will not attach the cookies to cross-origin requests. Check out our Same Site Cookie Changes documentation for more details.
- The correlation cookie may be overwritten. This usually happens during development if you run multiple instances of our service provider component on localhost, just on different ports. The cookie from one instance will be overwritten by the other. To resolve this, change the
CorrelationCookie.Name
on theSaml2pAuthenticationOptions
If you are unable to resolve the error using the above fixes, we recommend doing some investigation to determine the lifetime of the cookie. When you start the SAML request, your application should create a correlation cookie, and the cookie should be present in the HTTP request when you receive the SAML response.
No authenticated user error during logout
This error is thrown by the SAML SP when generating a logout request to send to the external IdP.
It means that the user is not currently signed in, or the given SignOutScheme
is not the main authentication cookie that the user is signed into.
Please check out the SP SLO documentation for more detail.
Requested logout for incorrect user
The SAML logout request contains the unique identifier of the user who is being logged out. This allows the IdP or SP to confirm that they are logging out the correct user. For instance, if a logout request is received for Bob, but Alice is currently logged in, the IdP or SP would deny the request.
If you are acting as the SP, please ensure that you have configured the correct NameIdClaimType
. This claim type is searched for in the SignOutScheme
and used to validate the incoming logout request. Read more on this in the SP SLO documentation.
If you are acting as the IdP, please be aware that OpenIddict uses the "sub" claim as the unique identifier of the user. So OpenIddict will query for the current user based on the sub claim. For example, even if you have configured to send email as the NameID in assertion, OpenIddict itself still uses the sub claim as the unique identifier. Due to this limitation, the service provider must send the sub claim as the NameID in the logout request. Hence, you need to ensure that you are sending the sub claim to the service provider if you are not already and ask the service provider to send it in the logout request. Check out the Claims Mapping and Assertion Attributes for more details on how to add additional user attributes to the assertion.
If this is not possible, you can look into implementing the ISamlNameIdService
interface. The IsCurrentUser
function determines whether the logout request is made for the correct user.
Can I change the SAML namespace prefix, e.g. saml2p to samlp?
We don't support changing the namespace prefix. The SAML specification does not enforce any prefixes, and the chosen XML namespace prefix should not affect a SAML implementation.
The general XML parsing rules apply to namespace prefixes, where the prefix is defined in the XML entity enclosing the use of that namespace. Hence, the prefix can be any arbitrary value, as the XML parsers will parse the namespace declaration.
If your provider is enforcing a specific namespace declaration, it indicates that they may not be parsing XML correctly.