Get OAuth Access Token with SAML Assertion
Contents
Get OAuth Access Token with SAML Assertion#
An access token is a security token that is issued by an authorization server as part of an OAuth 2.0 flow. Access tokens contain information about the client, who requests the token, and the OAuth protected resource (the API) the token is intended for (its audience).
The Microsoft identity platform (Azure AD) supports the OAuth 2.0 SAML bearer assertion flow which allows a user to use an existing trust relationship and request an OAuth access token using a SAML assertion. The SAML assertion is posted to the OAuth token endpoint. The endpoint processes the assertion and issues an access token based on prior approval of the OAuth protected application.
The client isn’t required to have or store a refresh token, nor is the client secret required to be passed to the token endpoint.
This type of flow supports users authenticating with identity providers such as Active Directory Federation Services (ADFS)
to Azure Active Directory. The SAML assertion obtained from ADFS can be used in an OAuth flow to authenticate the user.
In this document, we are going to use an existing SAML token to exchange it for an OAuth access token from Azure active directory (Azure AD).
Table of Contents#
Preconditions#
Input:
SAML Token
Azure AD Application ID: The ID of the application (
appId
) to request the OAuth token (e.g Public Azure AD Application =1b730954-1685-4b74-9bfd-dac224a7b894
).Scope: A space-separated list of scopes, or permissions, that the app requires (e.g. Microsoft Graph =
"https://graph.microsoft.com/.default
).Client secret (optional):
If your app is a public client, then
the client_secret
cannot be included. If the app is a confidential client (Your own app), then it must be included in the OAuth HTTP request.
Simulation Steps#
Encode SAML token#
Open a PowerShell console and run the following command to base64 encode a SAML token to later use it in an OAuth HTTP request:
$encodedSamlToken = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($SamlToken))
Create OAuth HTTP POST request#
HTTP header#
You can, for example, set the user Agent to look like Microsoft Outlook
or other known applications.
$headers = @{
"Content-Type" = "application/x-www-form-urlencoded"
"User-Agent" = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; Tablet PC 2.0; Microsoft Outlook 16.0.4266)"
}
$headers
HTTP body#
Use the following parameters:
Parameter |
Required/Optional |
Description |
---|---|---|
client_id |
required |
ID of application to request OAuth access token |
grant_type |
required |
Must be |
assertion |
required |
The base64 encoded SAML token |
scope |
required |
A space-separated list of scopes, or permissions, that the app requires |
client_secret |
optional |
If your app is a public client (Azure AD PowerShell Application), then |
Scope
For this example, we can use the Microsoft Graph API in the scope. Feel free to change this value depending on the use case.
$scope = "https://graph.microsoft.com/.default"
Client ID
We can request an OAuth access token leveraging the public
Azure Active Directory PowerShell application (Cliend ID = 1b730954-1685-4b74-9bfd-dac224a7b894
).
$ClientID = "1b730954-1685-4b74-9bfd-dac224a7b894"
If you want to use an application that you registered yourself, set the variable $ClientID
to the ID of your application. Remember that you must
use the application secret parameter in the HTTP body
too when you use a confidential application.
Body
$body = @{
"client_id"=$ClientId
"grant_type"="urn:ietf:params:oauth:grant-type:saml1_1-bearer"
"assertion"=$encodedSamlToken
"scope"=$scope
}
$body
if you are using a client secret, then add it to the $body
variable with the following commands:
$secret = 'xxxxxx'
$body['client_secret'] = $secret
Send HTTP POST request to the Microsoft identity platform token endpoint#
Send the OAuth token request to the OAuth 2.0 (v2) token endpoint: https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token
$TenantId = 'YOUR-TENANT-ID'
$TokenUrl = "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token"
$params = @{
"Method"="Post"
"Uri"=$TokenUrl
"Body"=$body
"Headers"=$headers
}
$results = $(Invoke-RestMethod @params)
$results
Get OAuth Access Token from Results#
$OAuthAccessToken = $results.access_token
$OAuthAccessToken
You can inspect your token here: jwt.ms: Welcome!
Output#
OAuth Access Token
Use the variable
$OAuthAccessToken
to call the API defined in thescope
parameter of the HTTP body.