Providers/Authentik/Public/New-AuthentikToken.ps1

function New-AuthentikToken {
    <#
    .EXTERNALHELP TestEnvironment-Help.xml
    .SYNOPSIS
        Creates the seeded user tokens from Data\AuthentikTokens.csv
    #>


    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    [OutputType([PSCustomObject])]
    param(
        [Parameter()]
        [string[]]$Identifier,

        [Parameter()]
        [switch]$PassThru
    )

    $connection = Get-AuthentikConnection
    $marker = Get-AuthentikSeedMarker -Connection $connection

    $csvPath = Join-Path -Path (Get-AuthentikDataPath) -ChildPath 'AuthentikTokens.csv'
    $rows = @(Import-Csv -Path $csvPath -Encoding UTF8)

    if ($Identifier) {
        $rows = @($rows | Where-Object { $Identifier -contains $_.Identifier })
        $unknown = @($Identifier | Where-Object { $rows.Identifier -notcontains $_ })
        if ($unknown) { throw "No definition in $csvPath for: $($unknown -join ', ')" }
    }

    $result = [PSCustomObject]@{
        TotalTokens   = $rows.Count
        CreatedTokens = 0
        UpdatedTokens = 0
        Tokens        = @()
        Errors        = @()
    }

    $userByName = @{}
    foreach ($user in (Get-AuthentikSeededObject -Type Users -Connection $connection)) {
        $userByName[[string]$user.username] = $user
    }

    $existingByIdentifier = @{}
    foreach ($existing in (Get-AuthentikSeededObject -Type Tokens -Connection $connection)) {
        $existingByIdentifier[[string]$existing.identifier] = $existing
    }

    $tokens = [System.Collections.Generic.List[object]]::new()

    foreach ($row in $rows) {
        $tokenIdentifier = '{0}-{1}' -f $marker.SlugPrefix, $row.Identifier

        if (-not $PSCmdlet.ShouldProcess("$tokenIdentifier for $($row.User)", 'Create Authentik token')) { continue }

        try {
            if (-not $userByName.ContainsKey($row.User)) {
                $message = "Token '$tokenIdentifier' belongs to user '$($row.User)', which does not exist. Skipped."
                $result.Errors += $message
                Write-Warning $message
                continue
            }

            $expires = $null
            $body = @{
                identifier  = $tokenIdentifier
                intent      = $row.Intent
                user        = [int]$userByName[$row.User].pk
                description = $row.Description
                expiring    = $false
            }
            # Minutes, not days: an instance caps an app password at its default token
            # duration, thirty minutes out of the box, and refuses anything longer. An API
            # token's expiry is set by the server whatever is sent, so only the app passwords
            # carry one here.
            if ($row.ExpiresInMinutes -match '^-?\d+$') {
                $expires = [DateTimeOffset]::UtcNow.AddMinutes([int]$row.ExpiresInMinutes)
                $body.expiring = $true
                $body.expires = $expires.ToString('o')
            }

            # The response is discarded on purpose: it never carries the secret, and nothing
            # here needs the object back.
            if ($existingByIdentifier.ContainsKey($tokenIdentifier)) {
                $null = Invoke-AuthentikRequest -Method PATCH -Path "/core/tokens/$tokenIdentifier/" -Body $body -Connection $connection
                $result.UpdatedTokens++
                Write-Verbose "Updated token $tokenIdentifier"
            }
            else {
                $null = Invoke-AuthentikRequest -Method POST -Path '/core/tokens/' -Body $body -Connection $connection
                $result.CreatedTokens++
                Write-Verbose "Created token $tokenIdentifier"
            }

            $tokens.Add([PSCustomObject]@{
                    Identifier = $tokenIdentifier
                    Key        = $row.Identifier
                    User       = $row.User
                    Intent     = $row.Intent
                    Expires    = $(if ($expires) { $expires.UtcDateTime } else { $null })
                    Expired    = ($null -ne $expires -and $expires -lt [DateTimeOffset]::UtcNow)
                })
        }
        catch {
            $message = "Failed to create token '$tokenIdentifier': $($_.Exception.Message)"
            $result.Errors += $message
            Write-Error $message
        }
    }

    $result.Tokens = $tokens.ToArray()

    Write-Verbose ("Tokens: $($result.CreatedTokens) created, $($result.UpdatedTokens) updated, " +
        "$($result.Errors.Count) problems")

    if ($PassThru) { return $result }
}