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:
- 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.
- Configure the Application permission with at least a delegated Microsoft Graph ‘User.Read’ permission and grant Admin Consent on the permission.
- on-prem domain already federated with Azure AD via ADFS Server.
- Testing needs to be done with a domain user account synced to Azure AD.
Performing Token Acquisition
Getting a SAML Assertion from ADFS
- 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.
- Send a Home Realm Discovery request to Azure AD to get the ‘federation_active_auth_url’ value
- 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:
Your PostMan set up should look like the following:
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
- 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
|client_id||your Application ID|
|assertion||base64 encoded SAML Assertion|
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 Version||TokenType Value|
Here is an example of a request for a SAML 2.0 Assertion:
16 Thoughts to “Using PostMan to request an Azure AD token via SAML Assertion Grant flow”
What client-request-id value in the request headers?
This is just a GUID to help identify a particular request event against the Authorization server. You can use any GUID generator to create your own.
Thanks, What value I need to choose for “<o:UsernameToken u:Id=””>
Also I am getting “An error occurred (InvalidIdentityToken)” error message. I verified for extra spaces or characters in my <saml:Assertion> but everything looks clean. I am not sure why my base64 encoded value is not working
The UsernameToken node is part of the WS-Security protocol. I am not sure if the value there really matters. You can probably use your own value or just copy from mine. As far as the error is concerned,
1) Is your domain federated with Azure AD?
2) What is the complete error message you received? This should have both the request ID and timestamp and the error message usually starts with AADSTS…
Also please provide details about client_id in getting JWT token
The client ID there is the Application ID of your application registered in Azure AD. This is mentioned in the pre requisite section.
The link for “SAML Bearer Assertion flow” is leading to a different page. I am wondering if the SAML Assertion flow is no longer supported for Azure Active Directory. So if we use “SAML Bearer Assertion flow” then user consent page will not open?
In my scenario, web application is authenticating the user with OKTA (SSO) and then web application will be making the call to MS Graph API but this call to MS Graph API will go through middle-ware and would not be made directly by the web application. Would “SAML Bearer Assertion flow” work in this scenario?
yes the link unfortunately takes you to a different page. The original page was taken down for content improvement and was not up yet. The SAML Assertion Grant flow would still work for v1 endpoint. For your particular scenario involving Okta as an IDP this may not work since MS Graph can only accept AzureAD-issued token and won’t work with tokens issued from a 3rd party IDP.
Hi, our organization azure ad is configured using WS-Fed, can i use this proccess to get access token
Could you please guide how to get an authentication token for azure ad configured using ws-fed. I need this token without any user interaction by runninfg scripts in back-end.
I tried to hit federation_active_auth_url i am getting this below error
ID3242: The security token could not be authenticated or authorized
Could you please guide me, guess it may be issue with UsernameToken u:Id in request body or client-request-id in header
This particular flow is only meant for Federated scenario where you have an on prem domain being Federated with an Azure AD tenant. I have not seen it used outside of WS Trust for WS Fed so I am not sure if that’s even possible. You may want to open a support case with us to look further.
Yes we have on prem domain being Federated with an Azure AD tenant, could you please guide with the above error.. this is what i found in ping federation logs —> IdP| failure| | Problem encountered during attribute mapping
That error looks to be from ADFS Server. See https://dynamics365authority.com/Blog/ADFS-Error-ID3242-The-security-token-could-not-be-authenticated-or-authorised helps. If not please open a support case.
Is it possible to use a users OIDC token or another authed token instead of their Username and Password, to get a SAML Assertion?
The SAML token in this case is issued by ADFS using WS-Trust protocol. I don’t think WS Trust supports interactive sign in.