Last active
December 20, 2022 10:43
-
-
Save doeringp/20c6508cd088aaa86ffab4f7e9640380 to your computer and use it in GitHub Desktop.
Get an access token from a OpenID Connect Provider with username and password or client credentials only.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Get an access token from an OpenID Connect Provider using the passwort grant type | |
or the client credentials grant type (without user context). | |
First, you need an client id and client secret. | |
The Password Grant Type enables the OpenID Connect client to send a username and password directly | |
to the OpenID Authority to obtain an access token for the user without user interaction. | |
The Client Credentials Grant Type enables the client to get an access token with | |
his Client ID and Secret without user interaction (no user context). | |
IMPORTANT: This script should be used only for development and testing. | |
.PARAMETER OpenIdAuthority | |
OpenId Authority. | |
.PARAMETER ClientId | |
Client Id which must be registered before. | |
.PARAMETER ClientSecret | |
Client secret to authenticate the client. | |
.PARAMETER Scopes | |
Scopes which should be contained in the access token. | |
.PARAMETER User | |
Username to obtain an access token for. | |
.PARAMETER Password | |
Password of the user. | |
.PARAMETER Clip | |
Add the resulting Authorization header to the clipboard. | |
#> | |
Param( | |
[Parameter(Mandatory=$true)] [string] $OpenIdAuthority, | |
[Parameter(Mandatory=$true)] [string] $ClientId, | |
[Parameter(Mandatory=$true)] [string] $ClientSecret, | |
[string] $Scopes = "openid profile role", | |
[string] $User, | |
[string] $Password, | |
[switch] $Clip | |
) | |
$TempFolder = [System.IO.Path]::GetTempPath() | |
$NugetBin = "$TempFolder/nuget.exe" | |
$IdentityModelDll = "$TempFolder\IdentityModel.3.0.0\lib\net452\IdentityModel.dll" | |
$NewtonSoftJsonDll = "$TempFolder\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll" | |
if (-not $(Test-Path $IdentityModelDll)) | |
{ | |
Write-Host "Downloading IdentityModel from NuGet..." | |
Invoke-WebRequest https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -OutFile $NugetBin | |
. $NugetBin install IdentityModel -Version 3.0.0 -OutputDirectory $TempFolder | |
} | |
if (-not $(Test-Path $IdentityModelDll)) { | |
Write-Error "Unable to load IdentityModel from NuGet." | |
exit 1 | |
} | |
Add-Type -AssemblyName System.Web | |
Add-Type -Path $IdentityModelDll | |
Add-Type -Path $NewtonSoftJsonDll | |
function GetAccessToken($authority, $clientId, $clientSecret, $user, $password) { | |
$discoClient = New-Object IdentityModel.Client.DiscoveryClient $authority | |
$discoClient.Policy.RequireHttps = $false | |
$disco = $discoClient.GetAsync().Result | |
# Client id and secret MUST be encoded using the "application/x-www-form-urlencoded" | |
# encoding algorithm to use them as username and password with HTTP Basic Authentication. | |
# See https://github.com/IdentityServer/IdentityServer4/issues/2086 | |
$clientId = [System.Web.HttpUtility]::UrlEncode($clientId) | |
$clientSecret = [System.Web.HttpUtility]::UrlEncode($clientSecret) | |
$tokenClient = New-Object IdentityModel.Client.TokenClient $disco.TokenEndpoint, $clientId, $clientSecret | |
if ($User) | |
{ | |
$tokenResponse = [IdentityModel.Client.TokenClientExtensions]::RequestResourceOwnerPasswordAsync( | |
$tokenClient, $User, $Password, $Scopes).Result | |
} | |
else | |
{ | |
$tokenResponse = [IdentityModel.Client.TokenClientExtensions]::RequestClientCredentialsAsync( | |
$tokenClient, $Scopes).Result | |
} | |
if ($tokenResponse.IsError) { | |
Write-Error "Unable to obtain an access token from $authority. Error: $($tokenResponse.Error)" | |
} | |
return $tokenResponse.AccessToken | |
} | |
if ($User) | |
{ | |
Write-Host "Acquiring an access token for client ""$ClientId"" and user ""$User"" using a password..." | |
} | |
else | |
{ | |
Write-Host "Acquiring an access token for client ""$ClientId"" using client credentials..." | |
} | |
$accessToken = GetAccessToken $OpenIdAuthority $ClientId $ClientSecret $User $Password | |
if ($Clip) | |
{ | |
Write-Host "`nAuthorization Header Value:" | |
Write-Host "Bearer $accessToken" | |
"Bearer $accessToken" | clip | |
Write-Host "`nThe access token has been copied to your clipboard." | |
} | |
else | |
{ | |
Write-Host "Tip: You can use the option -Clip to save the Authorization header directly to the clipboard." | |
Write-Output $accessToken | |
} |
thx for sharing :)
The way for the good old Windows PowerShell:
Invoke-RestMethod -Method 'POST' -Uri 'https://<authority>/connect/token' `
-Headers @{"Content-Type" = "application/x-www-form-urlencoded"} `
-Body ("grant_type=client_credentials" +
"&client_id=<client_id>" +
"&client_secret=<client_secret>" +
"&scope=api1")
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Requesting an access token can also easily be done using CURL and the Token endpoint of your OpenID Provider directly.
Password Grant Type:
Client Credentials Grant Type:
If you want to copy the access token directly to your clipboard pipe the result to:
This only works using PowerShell, WSL (with the "jq" tool installed).