69 lines
2.8 KiB
PowerShell
69 lines
2.8 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Gets a valid Bearer token for the Ka-Note production API.
|
|
- Reads from ~/.ka-note/token.txt if not expired (fast path)
|
|
- On expiry: MSAL silent refresh (no browser needed if refresh token valid)
|
|
- Fallback: interactive browser login (once per ~90 days)
|
|
- Saves every acquired token back to the cache file automatically
|
|
#>
|
|
param()
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$ClientId = '1aba7af7-eec1-4e49-b87e-9f941c0e8630'
|
|
$TenantId = '94cf90d7-e9ff-49a1-bc3b-a5b94d3cc8ca'
|
|
$Scopes = "api://$ClientId/access"
|
|
$CacheFile = Join-Path $env:USERPROFILE '.ka-note\token.txt'
|
|
$LoginHint = 'C.KAUER@KRAH-GRUPPE.DE'
|
|
|
|
function Get-JwtExpiry([string]$jwt) {
|
|
try {
|
|
$seg = $jwt.Split('.')[1]
|
|
$pad = 4 - ($seg.Length % 4); if ($pad -ne 4) { $seg += '=' * $pad }
|
|
$seg = $seg.Replace('-','+').Replace('_','/')
|
|
$c = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($seg)) | ConvertFrom-Json
|
|
return [System.DateTimeOffset]::FromUnixTimeSeconds($c.exp).UtcDateTime
|
|
} catch { return [DateTime]::MinValue }
|
|
}
|
|
|
|
function Save-Token([string]$token) {
|
|
$dir = Split-Path $CacheFile
|
|
if (-not (Test-Path $dir)) { New-Item -ItemType Directory $dir | Out-Null }
|
|
$token | Set-Content $CacheFile -Encoding UTF8 -NoNewline
|
|
}
|
|
|
|
# ── 1. Try cached file ────────────────────────────────────────────────────────
|
|
if (Test-Path $CacheFile) {
|
|
$cached = (Get-Content $CacheFile -Raw -Encoding UTF8).Trim()
|
|
$exp = Get-JwtExpiry $cached
|
|
$remaining = ($exp - [DateTime]::UtcNow).TotalMinutes
|
|
if ($remaining -gt 2) {
|
|
Write-Host " Token valid for $([math]::Round($remaining)) min (cached)." -ForegroundColor DarkGray
|
|
Write-Output $cached
|
|
return
|
|
}
|
|
Write-Host " Cached token expired. Refreshing via MSAL..." -ForegroundColor DarkGray
|
|
}
|
|
|
|
# ── 2. MSAL refresh / interactive ────────────────────────────────────────────
|
|
if (-not (Get-Module -ListAvailable MSAL.PS)) {
|
|
Write-Host " Installing MSAL.PS..." -ForegroundColor DarkGray
|
|
Install-Module -Name MSAL.PS -Scope CurrentUser -Force -AllowClobber
|
|
}
|
|
Import-Module MSAL.PS -ErrorAction Stop
|
|
|
|
$p = @{ ClientId = $ClientId; TenantId = $TenantId; Scopes = $Scopes }
|
|
|
|
$r = $null
|
|
try { $r = Get-MsalToken @p -Silent -LoginHint $LoginHint 2>$null } catch {}
|
|
|
|
if (-not $r -or -not $r.AccessToken) {
|
|
Write-Host " [AUTH] Opening browser for login..." -ForegroundColor Yellow
|
|
$r = Get-MsalToken @p -Interactive -LoginHint $LoginHint
|
|
}
|
|
|
|
if (-not $r -or -not $r.AccessToken) { Write-Error "Failed to acquire token."; exit 1 }
|
|
|
|
Save-Token $r.AccessToken
|
|
Write-Host " Token acquired and cached." -ForegroundColor Green
|
|
Write-Output $r.AccessToken
|