Private/Invoke-DuneApiAuthCredential.ps1

<#
.SYNOPSIS
Authenticate to the Dune API using username and password credentials.
 
.DESCRIPTION
Posts credentials to the Dune auth endpoint and establishes a token-based session: the JWT access token and refresh token are extracted from the `ss-tok`/`ss-reftok` response cookies, with the expiry derived from the JWT `exp` claim. Uses `-SkipCertificateCheck` for Local instances. Stores the session in the script-scoped DuneSession variable.
 
.PARAMETER DuneInstance
The target Dune instance. Valid values: Prod, Dev, Test, Local.
 
.PARAMETER Tenant
The tenant name to authenticate against.
 
.PARAMETER Credential
A PSCredential object containing the username and password.
 
.EXAMPLE
PS> $cred = Get-Credential
PS> Invoke-DuneApiAuthCredential -DuneInstance Dev -Tenant "yendico" -Credential $cred
Authenticates with credentials against the Dev instance.
#>

function Invoke-DuneApiAuthCredential () {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [ValidateSet("Prod", "Dev","Test","Local")]
        [string]$DuneInstance,

        [Parameter(Mandatory)]
        [string]$Tenant,

        [Parameter(Mandatory)]
        [PSCredential]$Credential
    )

    $DuneApiUrl = Get-DuneApiUrl -DuneInstance $DuneInstance

    # Save websession/jwt/pass
    $AuthUrl = "{0}{1}" -f $DuneApiUrl, "/auth/credentials"
    $Headers = @{
        "Accept"       = "application/json"
        "Content-Type" = "application/json"
        "X-Tenant"     = $Tenant
    }
    Write-Debug "$($MyInvocation.MyCommand)|process|Getting new session ..."
    $UserName = $Credential.UserName
    if ($DuneInstance -eq 'Local') {
        $Response = Invoke-WebRequest -Uri $AuthUrl -Method POST -Headers $Headers -Body (@{UserName = $UserName; Password = (Get-PlainPasswordFromCredential -Credential $credential) } | ConvertTo-Json) -UseBasicParsing -SessionVariable AuthSession -SkipCertificateCheck #UseBasicParsing needed for Az Automation (otherwise internet explorer first launch errorappears) / SkipCertificateCheck not available on Azure
    }
    else {
        $Response = Invoke-WebRequest -Uri $AuthUrl -Method POST -Headers $Headers -Body (@{UserName = $UserName; Password = (Get-PlainPasswordFromCredential -Credential $credential) } | ConvertTo-Json) -UseBasicParsing -SessionVariable AuthSession #UseBasicParsing needed for Az Automation (otherwise internet explorer first launch errorappears) / SkipCertificateCheck not available on Azure
    }
    
    if ($Response.StatusCode -ne 200) {
        throw "Something went wrong with the web request ..."
    }
    if ($null -eq $AuthSession) {
        Write-Warning "AuthSession not returned"
    }
    else{
        Write-Verbose "Successfully established dune AuthSession"
    }

    # save auth info
    if ($AuthSession) {
        $AuthCookies = $AuthSession.Cookies.GetCookies($AuthUrl)
        $Token = ($AuthCookies | Where-Object Name -eq 'ss-tok').Value
        $RefreshToken = ($AuthCookies | Where-Object Name -eq 'ss-reftok').Value
        if (-not $Token) {
            throw "Authentication succeeded but the response contained no 'ss-tok' token cookie. Verify the auth service is configured with UseTokenCookie."
        }
        if (-not $RefreshToken) {
            Write-Verbose "No 'ss-reftok' refresh token cookie returned; the session will not be refreshable."
        }
        $ParsedToken = Parse-JwtToken -Token $Token
        # Use local time: the expiry is compared against Get-Date (local) in Assert-DuneSession.
        $TokenExpiryDate = [System.DateTimeOffset]::FromUnixTimeSeconds($ParsedToken.exp).LocalDateTime
        $Script:DuneSession = [PSCustomObject]@{
            Type         = 'Credential'
            DuneApiUrl   = $DuneApiUrl
            Token        = ($Token | ConvertTo-SecureString -AsPlainText -Force)
            ExpiryDate   = $TokenExpiryDate
            RefreshToken = if ($RefreshToken) { $RefreshToken | ConvertTo-SecureString -AsPlainText -Force }
            Tenant       = $Tenant
        }
    }
    else {
        Write-Warning "The web request did not return an AuthSession; no new DuneSession was created." # AuthSession is not available on second invocation (on sequential workflow) - an existing session is kept
    }
}