TokenTactics v2

repository·main·Indexed 19 days ago

https://github.com/f-bader/tokentacticsv2

A PowerShell toolset for manipulating Azure JSON Web Tokens (JWT) and leveraging FOCI (Family of Client IDs) capable refresh tokens to obtain access tokens for Microsoft services including Graph, Outlook, and SharePoint. It provides cmdlets for device code flows, TPM-backed certificate authentication, passkey sign-in, and extracting tokens from SCCAUTH and ESTSAuth cookies.

Tokens
3.3K
Snippets
20
Records
21
Agent score
16%

What's inside TokenTactics v2

  1. Overview of Azure JWT Manipulation with TokenTactics

    main

    TokenTactics v2 is a toolset designed for manipulating Azure JSON Web Tokens (JWT). It is particularly useful when you possess a FOCI (Family of Client IDs) capable refresh token.

    Key capabilities include:

    • Using refresh tokens to obtain access tokens for known FOCI capable endpoints.
    • Leveraging MFA (Multi-Factor Authentication) status contained within refresh tokens.
    • Accessing applications like Outlook, SharePoint, OneDrive, and MSTeams once an access token is obtained.
    • Connecting to Azure to dump users and groups using Graph or MSGraph refresh tokens.
    • Switching to Azure Core Management tokens to run tools like AzureHound.

    This toolset can be used in conjunction with AAD Internals.

  2. Continuous Access Evaluation (CAE) support

    main

    TokenTactics supports CAE, which allows Microsoft services (MSGraph, Exchange, Teams, SharePoint) to extend access token lifetimes up to 24 hours while allowing real-time revocation for critical events (e.g., password change, account deletion).

    You can use the -UseCAE flag with refresh cmdlets and verify if a token is CAE capable by checking if (Parse-JWTtoken $token.access_token).ValidForHours is greater than 23.

    Invoke-RefreshToMSGraphToken -Domain "myclient.org" -UseCAE
    if ((Parse-JWTtoken $MSGraphToken.access_token).ValidForHours -gt 23) { "MSGraph token is CAE capable" }
  3. Sign-in using a passkey

    main

    Requires PowerShell 7.0+. If you have exported private key material from a provider (like KeePassXC, Bitwarden, or 1Password), you can use Invoke-EntraIDPasskeyLogin to obtain an ESTSAUTH cookie.

    Because the initial sign-in only retrieves the cookie, you must follow up with Get-EntraIDTokenFromESTSCookie to exchange it for bearer tokens (access, refresh, and ID tokens).

    # Using a native KeePassXC passkey file
    Invoke-EntraIDPasskeyLogin -Verbose -KeyFilePath "C:\Users\Fabian\Microsoft.passkey"
    Get-EntraIDTokenFromESTSCookie -CookieValue $Global:ESTSAUTH
    
    # Using manual parameters for unsupported formats
    Invoke-EntraIDPasskeyLogin -Verbose -UserPrincipalName "myUserName@example.com" -UserHandle "XYZ" -CredentialId "9e9c8297-0cde-4726-8852-16c141e15bd3" -PrivateKey $PrivateKey
    Get-EntraIDTokenFromESTSCookie -CookieValue $Global:ESTSAUTH
  4. Set up the TokenTactics test suite

    main

    The test suite requires PowerShell 7 and Pester 5.7.1. It uses mocked HTTP responses and does not require Entra ID credentials or network access. The suite is compatible with Linux, macOS, and Windows.

    Install-Module Pester -RequiredVersion 5.7.1 -Scope CurrentUser
    pwsh ./tests/Invoke-Tests.ps1
  5. Authenticate an application with a TPM-backed certificate

    main

    This requires Windows, a provisioned TPM, and the Microsoft Platform Crypto Provider.

    1. Create a non-exportable RSA certificate in the current user's personal store.
    2. Export the public .cer file (DER encoded) and upload it to your Azure App Registration under Certificates & secrets > Certificates.
    3. Configure application permissions and grant tenant admin consent.
    4. Use New-TPMCertificate to generate the certificate and Get-EntraIDTokenFromCertificate to request the token.

    Note: New-TPMCertificate defaults to Cert:\CurrentUser\My. For service accounts, use -CertStoreLocation Cert:\LocalMachine\My if permissions allow.

    $certificate = New-TPMCertificate \
        -Subject 'CN=EntraID-TPM-Auth' \
        -PublicKeyPath 'C:\Temp\EntraID-TPM-Auth.cer'
    
    $token = Get-EntraIDTokenFromCertificate \
        -TenantId 'contoso.onmicrosoft.com' \
        -ClientId '00000000-0000-0000-0000-000000000000' \
        -CertificateThumbprint $certificate.Thumbprint \
        -Scope 'https://graph.microsoft.com/.default'
  6. Get a refresh token using the Authorization Code flow

    main

    This flow can be used to bypass certain device compliance requirements (e.g., Intune Company Portal).

    1. Use Get-AzureAuthorizationCode to generate an authentication URL.
    2. Authenticate via the URL.
    3. Use Get-EntraIDTokenFromAuthorizationCode with the resulting code and redirect URL to exchange it for tokens.
    # Step 1: Get the URL
    Get-AzureAuthorizationCode
    
    # Step 2: Exchange the code (using full URL or specific params)
    Get-EntraIDTokenFromAuthorizationCode -AuthorizationCode "CODE" -RedirectUrl "URL"
  7. Install and use TokenTactics v2

    main

    To use TokenTactics v2, import the PowerShell module from the local directory and then use the provided cmdlets. The module provides tools for manipulating Azure JSON Web Tokens (JWT) and interacting with FOCI (Family of Client IDs) capable endpoints.

    Basic usage pattern:

    1. Import the .psd1 module file.
    2. Use specific cmdlets like Get-EntraIDTokenFromDeviceCode or Invoke-RefreshToSubstrateToken to perform token operations.
    Import-Module .\TokenTactics.psd1
    Get-Help Get-EntraIDTokenFromDeviceCode
    Invoke-RefreshToSubstrateToken -Domain "myclient.org"
  8. Refresh to a new access token

    main

    If you have a refresh token (stored in $response.refresh_token by default), you can use specialized cmdlets to refresh and obtain new access tokens for specific services.

    # Refresh for Outlook
    Invoke-RefreshToOutlookToken -domain "myclient.org"
    $OutlookToken.access_token
    
    # Refresh for MS Graph
    Invoke-RefreshToMSGraphToken -Domain "myclient.org"
    Connect-MgGraph -AccessToken $MSGraphToken.access_token -Scopes "User.Read.All","Group.ReadWrite.All"
  9. Connect to AzureAD or MgGraph using an access token

    main

    Once you have an access token, you can use it to authenticate existing PowerShell modules.

    # Connect to AzureAD
    Connect-AzureAD -AadAccessToken $response.access_token -AccountId user@myclient.org
    
    # Connect to Microsoft Graph
    Connect-MgGraph -AccessToken $MSGraphToken.access_token -Scopes "User.Read.All","Group.ReadWrite.All"
  10. Get a refresh token using Device Code flow

    main

    Use Get-EntraIDTokenFromDeviceCode to initiate a device code flow. You can specify a client preset like MSGraph or DODMSGraph (for DOD/Mil). Once the user authenticates, the JWT response is saved in the $response variable. Access the tokens via $response.access_token or $response.refresh_token.

    # Standard MS Graph client
    Get-EntraIDTokenFromDeviceCode -Client MSGraph
    
    # DOD/Mil Device Code
    Get-EntraIDTokenFromDeviceCode -Client DODMSGraph
  11. Automate Passkey sign-in with Invoke-EntraIDPasskeyLogin

    main
    Use Invoke-EntraIDPasskeyLogin to automate Passkey sign-in flows. This cmdlet saves the ESTSAUTH cookie and the websession as global variables, which can then be reused by other cmdlets such as Get-EntraIDTokenFromESTSCookie.
    Invoke-EntraIDPasskeyLogin
  12. Get a nested app token using NAA / BroCi

    main

    Exchanges a broker application's refresh token for a token issued to a nested application.

    Supported -BrokerPreset values:

    • AzurePortal
    • Teams
    • Microsoft365
    • EntraAdminCenter
    • IntuneAdminCenter
    • Defender
    • Purview

    If -RefreshToken is omitted, it defaults to $response.refresh_token. If -RedirectUri is omitted, it is derived from the broker client ID using the brk-<brokerClientId>://<broker-host> format.

    Get-EntraIDTokenFromNestedAppAuth \
        -BrokerPreset Defender \
        -TenantId "e3686c4f-af27-4f22-b9de-062f05b93aac" \
        -RefreshToken $response.refresh_token \
        -AnchorMailbox "Oid:3135fd4e-140c-43c0-ad02-718913648fb9@e3686c4f-af27-4f22-b9de-062f05b93aac" \
        -UseCAE