https://github.com/alflokken/PSAuthClient
PowerShell OAuth2.0/OpenID Connect (OIDC) Client.
https://github.com/alflokken/PSAuthClient
authentication authorization oauth2 oidc openidconnect powershell
Last synced: 2 months ago
JSON representation
PowerShell OAuth2.0/OpenID Connect (OIDC) Client.
- Host: GitHub
- URL: https://github.com/alflokken/PSAuthClient
- Owner: alflokken
- License: mit
- Created: 2024-02-03T13:32:59.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-06-29T19:33:32.000Z (3 months ago)
- Last Synced: 2025-06-29T19:34:15.411Z (3 months ago)
- Topics: authentication, authorization, oauth2, oidc, openidconnect, powershell
- Language: PowerShell
- Homepage:
- Size: 380 KB
- Stars: 100
- Watchers: 5
- Forks: 12
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- jimsghstars - alflokken/PSAuthClient - PowerShell OAuth2.0/OpenID Connect (OIDC) Client. (PowerShell)
README
# PSAuthClient
PSAuthClient is a flexible PowerShell OAuth2.0/OpenID Connect (OIDC) Client.
* Support for a [wide range of grants](#examples-of-openid-connect-oidc-and-oauth20-grants).
* Uses [WebView2](https://learn.microsoft.com/en-us/microsoft-edge/webview2/) to support modern web experiences where interaction is required.
* Includes [useful tools](#Tools) for decoding tokens and validating JWT signatures.
# Table of Contents
- [Install](#install)
- [Quick Start](#quick-start)
- [Documentation](#documentation)
- [Utilities included](#example-usage-of-additional-tools)
- [OIDC and OAuth2.0 Grant Examples](#examples-of-different-openid-connect-oidc-and-oauth20-grants)
- [Issues and Contributions](#issues-and-contributions)# Install
Either install the module from PSGallery `Install-Module PSAuthClient -Scope:CurrentUser` or [download](https://github.com/alflokken/PSAuthClient/releases) and unzip to ‘$home\Documents\WindowsPowerShell\Modules’.## Quick Start
Check out my blog post on getting started with PSAuthClient.
* Using [OAuth2](https://alflokken.github.io/posts/powershell-oauth2-authentication/) with Spotify as the OAuth2.0 provider.
* Using [OpenID Connect (OIDC)](https://alflokken.github.io/posts/powershell-oidc-authentication/) with Microsoft Graph as the OIDC provider.# Documentation
See links for function documentation, usage and examples.
| Function | Description |
| -------- | ----------- |
| [Invoke-OAuth2AuthorizationEndpoint](/docs/Invoke-OAuth2AuthorizationEndpoint.md) | Launches an embedded WebView2 browser to perform the OAuth2.0/OIDC Authorization Code flow. Supports modern authentication features (SSO, Windows Hello, FIDO2). |
| [Invoke-OAuth2DeviceAuthorizationEndpoint](/docs/Invoke-OAuth2DeviceAuthorizationEndpoint.md) | Initiates the Device Code flow by retrieving a user and device verification code from the authorization server that can be used to request tokens from the token endpoint. |
| [Invoke-OAuth2TokenEndpoint](docs/Invoke-OAuth2TokenEndpoint.md) | Requests security tokens using various grant types: authorization code, device code, refresh token, client credentials, or JWT assertions.|
| [Get-OidcConfigurationMetadata](docs/Get-OidcDiscoveryMetadata.md) | Retrieves OpenID Connect Discovery metadata (`.well-known/openid-configuration`). |
| [ConvertFrom-JsonWebToken](docs/ConvertFrom-JsonWebToken.md) | Decodes a JWT and returns a PowerShell object. |
| [Test-JsonWebTokenSignature](docs/Test-JsonWebTokenSignature.md) | Attempts to verify the JWT signature using the issuer’s published signing keys (via discovery metadata) or provided certificate/secret. |
| [New-PkceChallenge](docs/New-PkceChallenge.md) | Generates a PKCE `code_verifier` and `code_challenge` pair for Authorization Code flows. |
| [New-Oauth2JwtAssertion](docs/New-Oauth2JwtAssertion.md) | Builds and signs a JWT assertion using either a client certificate or HMAC secret, suitable for `private_key_jwt` or `client_secret_jwt` authentication methods.|
| [Clear-WebView2Cache](docs/Clear-WebView2Cache.md) | Deletes the WebView2 User Data Folder to clear cached sessions and cookies. |
## Example usage of additional tools
OIDC Discovery
Retrieve OpenID Connect Discovery metadata.
```powershell
Get-OidcDiscoveryMetadata "https://login.microsoftonline.com/common"token_endpoint : https://login.microsoftonline.com/common/oauth2/token
token_endpoint_auth_methods_supported : {client_secret_post, private_key_jwt, client_secret_basic}
jwks_uri : https://login.microsoftonline.com/common/discovery/keys
response_modes_supported : {query, fragment, form_post}
subject_types_supported : {pairwise}
id_token_signing_alg_values_supported : {RS256}
response_types_supported : {code, id_token, code id_token, token id_token}
scopes_supported : {openid}
issuer : https://sts.windows.net/{tenantid}/
microsoft_multi_refresh_token : True
authorization_endpoint : https://login.microsoftonline.com/common/oauth2/authorize
device_authorization_endpoint : https://login.microsoftonline.com/common/oauth2/devicecode
http_logout_supported : True
frontchannel_logout_supported : True
end_session_endpoint : https://login.microsoftonline.com/common/oauth2/logout
claims_supported : {sub, iss, cloud_instance_name, cloud_instance_host_name}
check_session_iframe : https://login.microsoftonline.com/common/oauth2/checksession
userinfo_endpoint : https://login.microsoftonline.com/common/openid/userinfo
kerberos_endpoint : https://login.microsoftonline.com/common/kerberos
tenant_region_scope :
cloud_instance_name : microsoftonline.com
cloud_graph_host_name : graph.windows.net
msgraph_host : graph.microsoft.com
rbac_url : https://pas.windows.net```
Decode JWT
Convert (decode) a JSON Web Token (JWT) to a PowerShell object.
```powershell
PS> ConvertFrom-JsonWebToken "ew0KICAidHlwIjogIkpXVCIsDQogICJhbGciOiAiUlMyNTYiDQp9.ew0KICAi..."header : @{typ=JWT; alg=RS256}
exp : 1706784929
echo : Hello World!
nbf : 1706784629
sub : PSAuthClient
iss : https://example.org
jti : 27913c80-40d1-46a3-89d5-d3fb9f0d1e4e
iat : 1706784629
aud : PSAuthClient
signature : OHIxRGxuaXVLTjh4eXhRZ0VWYmZ3SHNlQ29iOUFBUVRMK1dqWUpWMEVXMD0```
Validate JWT Signature
Attempt to validate the signature of a JSON Web Token (JWT) by using the issuer discovery metadata to get the signing certificate. (If no signing certificate or secret was provided.)
```powershell
PS> Test-JsonWebTokenSignature -jwtInput $jwt
True
```Build JWT Assertions
Create and sign JWT Assertions using either a client_certificate (x509certificate2 or RSA Private key) or client_secret (for HMAC-based signature).
```powershell
PS> New-Oauth2JwtAssertion -issuer "test" -subject "test1" -audience "test2" -jwtId "123" -customClaims @{ claim1 = "test" } -client_secret "secret"client_assertion_jwt ew0KICAiYWxnIjogIlJTMjU2IiwNCiAgInR5cCI6ICJKV1QiDQp9.ew0KICAianRp...
client_assertion_type urn:ietf:params:oauth:client-assertion-type:jwt-bearer
header @{alg=RS256; typ=JWT}
payload @{jti=123; claim1=test; aud=test2; exp=1706793151; nbf=170679285...}
```Generate a PKCE Challenge
Generate code_verifier and code_challenge for PKCE (authorization code flow).
```powershell
PS> New-PkceChallengecode_verifier Vpq2YXOsD~1DRM-jBPR6bt8R-3dWQAHNLVLUIDxh7SkWpOT3A0grpenqKne5rAHcVKsTi-ya8-lGBxJ0NS7zavdcFbfdN0yFQ5kYOFbWBh3
code_challenge TW-3r-6mxRWjhkkxmYOabLlwIQ0JkQ0ndxzOSLJvCoU
code_challenge_method S256
```## Examples of different OpenID Connect (OIDC) and OAuth2.0 Grants
OpenID Connect is an extension of OAuth2 that adds an identity layer to the authorization framework. This allows a client to verify the identity of the user and obtain basic profile information. OIDC grants contains 'openid' scope and the identity provider will return a 'id_token' with user information (claims).
Parameters that are used (and modified) throughout the examples below.
```powershell
$authorization_endpoint = "https://login.microsoftonline.com/example.org/oauth2/v2.0/authorize"
$token_endpoint = "https://login.microsoftonline.com/example.org/oauth2/v2.0/token"$splat = @{
client_id = "5eda97cf-2963-41e9-bea0-b6ba2bbf8f99"
scope = "user.read openid offline_access"
redirect_uri = "https://login.microsoftonline.com/common/oauth2/nativeclient"
customParameters = @{
prompt = "none"
}
}
```
Authorization Code Grant with Proof Key for Code Exchange (PKCE)
Example
```powershell
$code = Invoke-OAuth2AuthorizationEndpoint -uri $authorization_endpoint @splatclient_id 5eda97cf-2963-41e9-bea0-b6ba2bbf8f99
code_verifier ig0Sly4Kdjc_e77Zsp5..PKi.TbqzSNz_CEKsamyPRI5~uRr4_
nonce o180HoFS2k5y0gj.spbYos.IPUS8-SqSf4cx0Z7x
redirect_uri https://login.microsoftonline.com/common/oauth2/nativeclient
code 0.AUcAjvFfm8BTokWLwpwMj2CyxiGBP5hz2ZpErJuc3chlhOUNAVw.AgABAAIAAAA...$token = Invoke-OAuth2TokenEndpoint -uri $token_endpoint @code
token_type : Bearer
scope : User.Read profile openid email
expires_in : 5340
ext_expires_in : 5340
access_token : eyJ0eXAiOiJKV1QiLCJub25jZSI6IlhFMjJvBXRyVDBkQ1Z1cG7zbEFJQk1kU1RxLS5xQUppS3Fpbr...
refresh_token : 0.AUcAjvFfm8BTokWLwpwMj2CyxiGBP5hz2ZpErJuc3chlhOUNAVw.AgABAAEAAAAmoFfGtYxvRrNr...
id_token : eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImtXYmthYTZxczh3c1RuQndpaU5ZT2hIYm...
expiry_datetime : 31.01.2024 14:11:08```
Authorization Code Grant
Example
```powershell
$code = Invoke-OAuth2AuthorizationEndpoint -uri $authorization_endpoint @splat -usePkce:$falsenonce UYhqAG~GLvZqGj4hnlTkYFJY9LVcS9TrWiq.8n8Vu
redirect_uri https://login.microsoftonline.com/common/oauth2/nativeclient
client_id 5eda97cf-2963-41e9-bea0-b6ba2bbf8f99
code 0.AUcAjvFfm8BTokWLwpwMj2CyxiGBP5hz2ZpErJuc3chlhOUNAVw.AgABAAmoFfG...$token = Invoke-OAuth2TokenEndpoint -uri $token_endpoint @code
token_type : Bearer
scope : User.Read profile openid email
expires_in : 3848
ext_expires_in : 3848
access_token : eyJ0eXAiOiJKV1QiLCJub62jZSI6ImhDRkwxMjVHdE85SmNqS0NWMFZQLWxTd2Z0Zm12LXFsV2VDR0...
refresh_token : 0.AUcAjvFfm8BTokWLwpwMkJCyxiGBP5hz2ZpErJuc3chlhOUNAVw.AgABAAEAAAAmoFfGtYxjHyNf...
id_token : eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImtXYmthYTZxczh3c1RuQndpaU547ZT2hI...
expiry_datetime : 31.01.2024 14:05:18
```Authorization Code Grant with Client Authentication (secret)
Example
```powershell
$splat.redirect_uri = "https://localhost/web"
$code = Invoke-OAuth2AuthorizationEndpoint -uri $authorization_endpoint @splatclient_id 5eda97cf-2963-41e9-bea0-b6ba2bbf8f99
code_verifier jWe-ecfnqZ.weAxbb-qHiZ3oe7LZ-tEyWq~7UB9RcNfZn65Xq2zPO7-8rv-5tp24p...
nonce HRBD6BuH9PQM2_Kmuqj6KTranVVcuL80fsEpll-9nppaZp0H3CQaYhaqQ2VqUV8
redirect_uri https://localhost/web
code 0.AUcAjvFfm8BTokWLwpwMj2CyxiGBP5hz2ZpErJuc3chlhOUNAVw.AgABAAIAAAm...$token = Invoke-OAuth2TokenEndpoint -uri $token_endpoint @code -client_secret $client_secret
token_type : Bearer
scope : User.Read profile openid email
expires_in : 4069
ext_expires_in : 4069
access_token : eyJ0eXAiOiJKG1QqLCJub25jZSI5IllOTzdpTmdXZnMtSmSSY1hpZk45bTdoa2E0WnNpWFY5ckswen...
refresh_token : 0.AUcAjvFfmC9TokWLwpwMj2CyxiGBP5hz2ZpRrJuc3chlhOUGAVw.AgABAAEAAAAmoFfGtYxvRrNf...
id_token : eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImtXYmthYTZxczh3c1RuQndpaU5ZT2hIYm...
expiry_datetime : 31.01.2024 14:28:58
```Refresh Token Grant
Example
```powershell
$token = Invoke-OAuth2TokenEndpoint -uri $token_endpoint -refresh_token $token.refresh_token -client_id $splat.client_id -scope $splat.scope -nonce $code.noncetoken_type : Bearer
scope : User.Read profile openid email
expires_in : 3951
ext_expires_in : 3951
access_token : eyJ0eXAiOiJKR1QiLCJsf52jZSI6IjdCbkI2VDc5OGJZVlh3ZHdIRWVOMGducUVKQVBEUnBPcTZhMm...
refresh_token : 0.AUcAjvFfm1BTokWLkjrMj3CyxiGBP5hz4ZpErJuc3chlhOUNAVw.AgABAAEAAAAmoFfGtDxvRrNa...
id_token : eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImtXYmthYTZxczh3c1RuQndsapaU5ZT2hI...
expiry_datetime : 31.01.2024 14:16:56
```Client Credentials Grant (client_secret_basic)
Example
```powershell
$splat.Remove("customParameters")
$splat.scope = ".default"
$token = Invoke-OAuth2TokenEndpoint -uri $token_endpoint @splat -client_secret (Invoke-Cache -keyName "PSC_Test-ClientSecret") -client_auth_method client_secret_basictoken_type : Bearer
expires_in : 3599
ext_expires_in : 3599
access_token : eyJ0eXAiOiJKV1DiLCJub25jZSI3IjUtQjB0bXBSNHhzYWtJSW8wOFY5ejFGVGRTWDF5blZfalNVX2...
expiry_datetime : 31.01.2024 14:14:06
```Client Credentials Grant (client_secret_post)
```powershell
$token = Invoke-OAuth2TokenEndpoint -uri $token_endpoint @splat -client_secret (Invoke-Cache -keyName "PSC_Test-ClientSecret" -asSecureString)token_type : Bearer
expires_in : 3599
ext_expires_in : 3599
access_token : eyJ0eXAiOiJKV1QiGCJub25jZSI3ImtIeW5MWTNyUjdja0lZd1RTQWVSRi1yRnVYYUx0Y6VaU11NEF...
expiry_datetime : 31.01.2024 14:16:10
```Client Credentials Grant (client_secret_jwt)
Example
```powershell
# Microsoft Graph DOES NOT support client_secret_jwt, but if they did, this is how you would do it.
$token = Invoke-OAuth2TokenEndpoint -uri $token_endpoint @splat -client_secret $client_secret -client_auth_method "client_secret_jwt"error error_description
----- -----------------
invalid_client AADSTS5002723: Invalid JWT token. No certificate SHA-1 thumbprint, certificate SH...```
Client Credentials Grant certificate (private_key_jwt)
Example
```powershell
$token = Invoke-OAuth2TokenEndpoint -uri $token_endpoint @splat -client_certificate "Cert:\CurrentUser\My\8ade399dddc5973e04e34ac19fe8f8759ba059b8"token_type : Bearer
expires_in : 3599
ext_expires_in : 3599
access_token : eyJ0eXAiOiJKV1QiLCJub21jZSI2InpBUjQ6UTBRc7dzYkcxOVJibQ032s2UUxrckZUcm9BYmwgdh0...
expiry_datetime : 31.01.2024 14:20:03```
Implicit Grant (OAuth2.0)
Example
```powershell
$splat.redirect_uri = "https://localhost/spa"
$splat.scope = "User.Read"
$token = Invoke-OAuth2AuthorizationEndpoint -uri $authorization_endpoint @splat -response_type "token" -usePkce:$falseexpires_in 4371
expiry_datetime 31.01.2024 14:39:19
scope User.Read profile openid email
session_state 5c044a56-543e-4bcc-a94f-d411ddec5a87
access_token eyJ0eXAiOiJKV1QiLCJkj76jZSI6InlaZzBmU1NGV1M1UmllaFRHc01jMWJkSFNIZ...
token_type Bearer
```Implicit Grant (OIDC)
Example
```powershell
$token = Invoke-OAuth2AuthorizationEndpoint -uri $authorization_endpoint @splat -response_type "token id_token" -usePkce:$falsenonce NtKwrnSuV7xQQiya.jNXF940RQkS0OMlTcQDCOOgJay8a2qi0.MO4KKX8xc-XWUa
expires_in 4949
id_token eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImtXYmthYTZxczh3c1RuQ...
expiry_datetime 31.01.2024 14:46:35
scope User.Read profile openid email
session_state 5c044a56-543e-4bcc-a94f-d411ddec5a87
access_token eyJ0eXAiOiJKV1QiLCJub51jZSI6Ik2saWhWbkdCMzNYUnI0VTF5VUVYLXA0Zkp6K...
token_type Bearer
```Hybrid Grant
Example
```powershell
$splat.scope = "user.read openid offline_access"
$splat.redirect_uri = "http://localhost"
$splat.usePkce = $true
$token = Invoke-OAuth2AuthorizationEndpoint -uri $authorization_endpoint @splat -response_type "code id_token"nonce 7B61P-.ST87WdKZ9TPF~1a5sMkPs.atxj8sBCmY2mHHfEKRotmK37dxDl
code_verifier w6Fvr5LTkex0k.aRJhL9rZeEDNSO5sdc8zeQYlstYJuZ2K9ck2azZ~Luxeaw2CCSd...
id_token eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImtXYmthYTZxczh3c1RuQ...
client_id 5eda97cf-2963-41e9-bea0-b6ba2bbf8f99
session_state 5c044a56-543e-4bcc-a94f-d411ddec5a87
redirect_uri http://localhost
code 0.AUcAjvFfm8BTokWLwpwMj2CyxiGBP5hz2ZpErJuc3chlhOUNAVw.AgABAAAAAmo...$token.Remove("id_token"); $token.Remove("session_state")
$tokens = Invoke-OAuth2TokenEndpoint -uri $token_endpoint @tokennonce da1EE3-RRVJO.fFeCEw2TvG7hK46AWFWHJCOBeRfnJ6o
code_verifier ~4fYq2QcXlSIZN_vZ7pnKsO5VZ0Pq39hsdQOAziqDqsGNL-JGP~
client_id 5eda97cf-2963-41e9-bea0-b6ba2bbf8f99
redirect_uri http://localhost
code 0.AUcAjvFfm8BTokWLwpwMj2CyxiGBP5hz2ZpErJuc3chlhOUNAVw.AgABAAIAAAA...
```Implicit Flow (by Form_Post)
Example
```powershell
$splat.redirect_uri = "http://localhost:5001/"
$customParameters = @{
prompt = "none" # login, none, consent, select_account
}
$token = Invoke-OAuth2AuthorizationEndpoint -uri $authorization_endpoint @splat -response_type "code id_token" -response_mode "form_post"nonce iOJ6n7jBlYAL_TrYlFjfKwOsPklX1-4iR
code_verifier j1v4ZEjF4AE.lMfsQ36UzF6OoBp.zwuJ7Qkez9XQX~4lGo9pnxxtN.P4ulFhkwBaZ...
id_token eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImtXYmthYTZxczh3c1RuQ...
client_id 5eda97cf-2963-41e9-bea0-b6ba2bbf8f99
session_state 5c044a56-543e-4bcc-a94f-d411ddec5a87
redirect_uri http://localhost:5001/
code 0.AUcAjvFfm8BTokWLwpwMj2CyxiGBP5hz2ZpErJuc3chlhOUNAVw.AgABAAIAmoF...$token.Remove("id_token"); $token.Remove("session_state")
$tokens = Invoke-OAuth2TokenEndpoint -uri $token_endpoint @tokentoken_type : Bearer
scope : User.Read profile openid email
expires_in : 4840
ext_expires_in : 4840
access_token : eyJ0eXAiOiJKV1QiLCJub55jZSI6IlRsTFVNS5MyaEpscDNfNzKH75GXMXI0WndKMnlKJSJzFdzJEb...
refresh_token : 0.AUcAjvFfm8BTokSLwpwMj2CyxiGBP5kH76pErJuc3chlhOUNAVw.AgABAAEAPKIZ-AgDs_wSA9P9...
id_token : eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImtXYmthYTZxczh3c1RuQndpaU5ZT2hIYm...
expiry_datetime : 31.01.2024 14:54:54
```Device Code Grant
Example
```powershell
$deviceCode = Invoke-OAuth2DeviceAuthorizationEndpoint -uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/devicecode" -client_id $splat.client_id -scope $splat.scopeuser_code : L8EFTXRY3
device_code : LAQABAAEAAAAmoFfGtYxvRrNriQdPKIZ-2b64dTFbGcmRF3rSBagHQGtBcyz0K_XV8ltq-nXz8Ks6...
verification_uri : https://microsoft.com/devicelogin
expires_in : 900
interval : 5
message : To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the co...# Pop interactive browser
Invoke-WebView2 -uri "https://microsoft.com/devicelogin" -UrlCloseConditionRegex "//appverify$" -title "Device Code Flow" | Out-Null# After user-interaction has been completed.
$token = Invoke-OAuth2TokenEndpoint -uri $token_endpoint -device_code $deviceCode.device_code -client_id $splat.client_idtoken_type : Bearer
scope : User.Read profile openid email
expires_in : 5320
ext_expires_in : 5320
access_token : eyJ0eXAiOiJKV1QiKH6Gb25jZSI5IjlzanppVWtNSlkR4WxfWjBRWFJRZUl4TEdyaDBad05TQ01sQ1...
refresh_token : 0.AUcAjvFfm8BlORWLwpwMj2CyxiGBP5hz2ZpErkU62chlhOUNAVw.AgABAAEAAAAmoFfGtYxvRrlK...
id_token : eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImtXYmthYTZxczh3c1RuQndpaU5ZT2hIYm...
expiry_datetime : 31.01.2024 15:07:19```
Resource Owner Password Flow (ROPC)
I did not bother to implement this flow, as its insecure and not recommended for use. Its fairly trivial to implement if you need it. See https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth-ropc for more information.## Issues and Contributions
If you encounter a bug or have a feature request, please [create an issue](https://github.com/alflokken/PSAuthClient/issues). I'm not actively seeking contributions. However, if you have an improvement in mind, please open an issue first to discuss it before submitting a pull request.