Receiving error AADSTS7500514: A supported type of SAML response was not found when authenticating to Azure AD with a federated account

Customers can get the following error when authenticating to Azure Active Directory with a federated account using MSAL (or now deprecated ADAL) Authentication library.

{
     error: "invalid_request",
     error_description: "AADSTS7500514: A supported type of SAML response was not found. The supported response types are 'Response' (in XML namespace 'urn:oasis:names:tc:SAML:2.0:protocol') or 'Assertion' (in XML namespace 'urn:oasis:names:tc:SAML:2.0:assertion').
     ....
     error_uri: "https://login.microsoftonline.com/error?code=7500514"
}

The error is typically seen in the following environment:

  • A federated account using PingFederate as the Identity Provider (IDP) is used for authentication
  • The IDP is configured to issue a SAML 1.1 token (via WS-Trust protocol).
  • The application uses one of the following API:
    • MSAL’s AcquireTokenByUserNamePassword
    • ADAL’s AcquireToken(string resource, string clientId, UserCredential userCredential) overload method is used
    • any PowerShell module that uses ADAL or MSAL’s above methods for authentication

Why is this error happening when I am using ADAL or MSAL’s API?

In order to understand this error, we need to understand a little bit about how the API works when passing in a username (User Principal Name (UPN)) and password. Since ADAL library is becoming deprecated, we will discuss this in terms of MSAL library (the recommended authentication library over ADAL). The above MSAL API has an internal heuristics to determine if the user account is managed (cloud account) or federated and will take different code paths (OAuth2 grant flows) to authenticate silently to Azure AD. For managed accounts, MSAL uses Resource Owner Password Credentials Grant (ROPC) flow, while for federated accounts, it uses SAML Assertion Grant flow for authentication. If you notice, there are two steps involved in the SAML Assertion Grant flow:

  1. The client application authenticates to the federated IDP (typically using WS-Trust protocol) to obtain a SAML token
  2. the client then uses the obtained SAML token to get an OAuth2 JWT token from Azure AD

The problem typically happens in step 1 where the client application (MSAL in this case) needs to parse the SAML response from the IDP to determine the SAML version. Historically, both ADAL and MSAL were developed to support how ADFS works in conjunction with Azure AD for federated accounts, so it expects certain attribute values present in the SAML response to determine the version of the SAML token. The SAML token version shows up in a couple of places: <saml:Assertion> node and <TokenType> node. Below is ADFS Response from the usernamemixed endpoint:

  1. SAML Assertion: major version = 1 and minor version = 1
  2. TokenType: urn:oasis:names:tc:SAML:1.0:assertion

Compare the same request when PingFederate is an IDP:

Note that Ping returns a different TokenType value: http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1 for the same SAML 1.1 token.

For SAML 1.1 token, MSAL does not support any TokenType value other than urn:oasis:names:tc:SAML:1.0:assertion (what ADFS uses), so when an IDP returns a different value, MSAL incorrectly thinks the SAML token version is 2.0. See https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/1871 for more info.

In step 2 of the SAML Assertion Grant flow, the value of the ‘grant_type’ parameter are different for different SAML versions. They are listed below:

urn:ietf:params:oauth:grant-type:saml2-bearer – for SAML2.0 token

urn:ietf:params:oauth:grant-type:saml1_1-bearer – for SAML1.1 token

In this case with PingFederate account, MSAL uses the wrong ‘grant_type’ parameter due to the above logic, leading to the error since there is a version mismatch between the ‘grant_type’ parameter and the assertion (containing the actual SAML token) parameter:

For comparison, here is the same token request when ADFS is the IDP:

Ok so I understand the problem. What should I do to resolve this?

The problem is typically due to a misconfiguration on the PingFederate side for Azure AD and Office 365 apps. PingFederate has the following recommended documentation for creating a connection to Azure AD:

Creating a connection to Azure Active Directory
Configuring WS-Trust STS

Pay close attention to step 2d from the first doc for configuring WS-Trust setting:

And from the second documentation, select SAML 1.1 for Office 365 as the Default Token Type

Note: setting the above value for Default Token Type ensures Ping sends back the same TokenType value as ADFS (aka urn:oasis:names:tc:SAML:1.0:assertion)

Consider opening a support case with PingFederate should you require more guidance on the above documentation.

Reference

For information on how to use PostMan to perform SAML Assertion Grant flow, refer to this blog.

Using PostMan to request an Azure AD token via SAML Assertion Grant flow

Azure Active Directory (Azure AD) supports an OAuth2 Extension Grant called “SAML Bearer Assertion flow” which allows an application to request an JWT OAuth2 token from Azure AD by providing a SAML Assertion (Token) acquired during an authentication process to a different Authorization Server. As you can imagine in order for this token exchange mechanism to happen, a trust relation between Azure AD and that Authorization Server must have already been established via a process called Federation. A common scenario is a hybrid environment where Active Directory Federation Server (ADFS) is used to federate between an Active Directory on-prem domain with Azure AD.

In this blog post I’ll show how to use Postman to request a SAML token (or SAML Assertion) from ADFS server using WS-Trust protocol and then use that SAML token to exchange for an OAuth2 JWT token from Azure AD. There are a few pre-requisites:

  1. Create an App Registration in Azure AD. For this demo I create a single tenant application and set the default client type to be public by selecting ‘Yes’. If you set ‘No’ on the Default client type, you will also need to provide a secret later on when exchanging a SAML Assertion for the OAuth2 JWT token.
  1. Configure the Application permission with at least a delegated Microsoft Graph ‘User.Read’ permission and grant Admin Consent on the permission.
  2. on-prem domain already federated with Azure AD via ADFS Server.
  3. Testing needs to be done with a domain user account synced to Azure AD.

Performing Token Acquisition

Getting a SAML Assertion from ADFS

  1. The first step in using SAML Assertion Grant flow is to get a SAML Assertion from ADFS (or whoever your Federation IDP is).This is typically done via WS-Trust protocol. There are a couple of ways to find the correct endpoint to send the WS-Trust request to.
    1. Send a Home Realm Discovery request to Azure AD to get the ‘federation_active_auth_url’ value
    2. GET https://login.microsoftonline.com/common/userrealm/user@contoso.com?api-version=1.0
      or
    3. Find the usernamemixed endpoint from ADFS’s Tools Management Console

Note: There are a couple of usernamemixed endpoints, use the WS-Trust 2005 type.

Send the POST request to the federation_active_auth_url (aka usernamemixed endpoint) with the following parameter in PostMan:

As noted, you need to supply your own parameters (username, password, and ADFS usernamemixed URL) in the request on line 25,29, and 30:

[gist id=”31594d7f0e64586b78e4c13c71e9f94a” file=”WSTrustBody.xml”]

Your PostMan set up should look like the following:

HTTP Headers

And if everything goes right you should get a SAML Response from the ADFS Server like the following.

Note: In this case ADFS returns a SAML 1.1 token as indicated in the highlighted Assertion (MajorVersion = 1, MinorVersion = 1)

Exchanging a SAML Token for JWT Token

  1. The second step in the SAML Assertion Grant flow is to exchange the SAML Assertion acquired from ADFS Server for a JWT OAuth2 token from Azure AD.

In PostMan change the response view from the last step to Raw View and search for the substring <saml:Assertion …>….</saml:Assertion>


Copy the entire Assertion substring including the node name and paste it into a Base64 encoder of your choice. I use this online tool to do the encoding. We need to base64-encode this SAML Assertion


Copy out the base64-encoded output. This will be used for the next PostMan request.

Note: It is very important that there should not be any spaces between the different nodes in this Assertion substring when doing the encoding since having the spaces can change the encoded output and can cause unexpected error such as ‘AADSTS50006: Signature verification failed because of an invalid signature’ in the following token exchange step.

Use PostMan to perform the following request:

POST https://login.microsoftonline.com/<tenant name>.onmicrosoft.com/oauth2/v2.0/token

POST Body:

grant_typeurn:ietf:params:oauth:grant-type:saml1_1-bearer
client_idyour Application ID
assertionbase64 encoded SAML Assertion
scopehttps://graph.microsoft.com/.default

And you should get a JWT token from this grant:

Note: I set the grant_type parameter to be “urn:ietf:params:oauth:grant-type:saml1_1-bearer” because this is a SAML 1.1 token/Assertion. If the Authorization server returns a SAML 2.0 token (Version attribute in the Assertion element is “2.0”), the grant_type parameter should be set to “urn:ietf:params:oauth:grant-type:saml2-bearer”.

By default, ADFS Server returns a SAML 1.1 token. To specify the version of the returned SAML token, you can use the TokenType element with the value in the following table in the WS-Trust request body.

SAML Token VersionTokenType Value
1.1 Tokenhttp://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1
2.0 Tokenhttp://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0

source: https://www.oasis-open.org/committees/download.php/16768/wss-v1.1-spec-os-SAMLTokenProfile.pdf

Here is an example of a request for a SAML 2.0 Assertion: