feat: activate MSAL auto-login in get-token.ps1
Azure Portal config done: - Added redirect URI: https://login.microsoftonline.com/common/oauth2/nativeclient - Allow public client flows: Yes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a67dc06b30
commit
dc52f64ed4
|
|
@ -1,70 +1,34 @@
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Gets a valid Bearer token for the Ka-Note production API.
|
Gets a valid Bearer token for the Ka-Note production API via MSAL.PS.
|
||||||
|
On first run (or after token cache expires): opens browser popup for login.
|
||||||
PREFERRED (fully automatic): Add the redirect URI once in Azure Portal:
|
Subsequent runs: silent refresh via cached refresh token.
|
||||||
App registrations → Ka-Note (1aba7af7-...) → Authentication
|
|
||||||
→ Add platform "Mobile and desktop" → URI: https://login.microsoftonline.com/common/oauth2/nativeclient
|
|
||||||
Then uncomment the MSAL section below.
|
|
||||||
|
|
||||||
CURRENT FALLBACK: reads cached token from %USERPROFILE%\.ka-note\token.txt
|
|
||||||
Store a fresh token there with: .\set-token.ps1 "eyJ..."
|
|
||||||
|
|
||||||
.OUTPUTS
|
.OUTPUTS
|
||||||
Writes the access token string to stdout (no trailing newline).
|
Writes the access token string to stdout.
|
||||||
#>
|
#>
|
||||||
param()
|
param()
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
$tokenFile = Join-Path $env:USERPROFILE '.ka-note\token.txt'
|
$ClientId = '1aba7af7-eec1-4e49-b87e-9f941c0e8630'
|
||||||
|
$TenantId = '94cf90d7-e9ff-49a1-bc3b-a5b94d3cc8ca'
|
||||||
|
$Scopes = "api://$ClientId/access"
|
||||||
|
|
||||||
# ── Option A: MSAL.PS (uncomment after adding redirect URI in Azure Portal) ───
|
if (-not (Get-Module -ListAvailable -Name 'MSAL.PS')) {
|
||||||
# Requires one-time Azure Portal step:
|
Write-Host " [INFO] Installing MSAL.PS..." -ForegroundColor DarkGray
|
||||||
# App registrations → 1aba7af7-eec1-4e49-b87e-9f941c0e8630 → Authentication
|
Install-Module -Name 'MSAL.PS' -Scope CurrentUser -Force -AllowClobber
|
||||||
# → Add platform "Mobile and desktop applications"
|
}
|
||||||
# → Redirect URI: https://login.microsoftonline.com/common/oauth2/nativeclient
|
Import-Module MSAL.PS -ErrorAction Stop
|
||||||
# → Save
|
|
||||||
#
|
|
||||||
# if (-not (Get-Module -ListAvailable MSAL.PS)) {
|
|
||||||
# Install-Module -Name MSAL.PS -Scope CurrentUser -Force -AllowClobber
|
|
||||||
# }
|
|
||||||
# Import-Module MSAL.PS
|
|
||||||
# $p = @{
|
|
||||||
# ClientId = '1aba7af7-eec1-4e49-b87e-9f941c0e8630'
|
|
||||||
# TenantId = '94cf90d7-e9ff-49a1-bc3b-a5b94d3cc8ca'
|
|
||||||
# Scopes = 'api://1aba7af7-eec1-4e49-b87e-9f941c0e8630/access'
|
|
||||||
# }
|
|
||||||
# try { $r = Get-MsalToken @p -Silent 2>$null }
|
|
||||||
# catch { $r = Get-MsalToken @p -Interactive }
|
|
||||||
# Write-Output $r.AccessToken
|
|
||||||
# return
|
|
||||||
|
|
||||||
# ── Option B: cached token file (current default) ────────────────────────────
|
$p = @{ ClientId = $ClientId; TenantId = $TenantId; Scopes = $Scopes }
|
||||||
if (-not (Test-Path $tokenFile)) {
|
|
||||||
Write-Error "No cached token found. Run: .\set-token.ps1 `"eyJ...`""
|
$r = $null
|
||||||
exit 1
|
try { $r = Get-MsalToken @p -Silent 2>$null } catch {}
|
||||||
|
|
||||||
|
if (-not $r) {
|
||||||
|
Write-Host " [AUTH] Opening browser for login..." -ForegroundColor Yellow
|
||||||
|
$r = Get-MsalToken @p -Interactive
|
||||||
}
|
}
|
||||||
|
|
||||||
$token = (Get-Content $tokenFile -Raw -Encoding UTF8).Trim()
|
if (-not $r?.AccessToken) { Write-Error "Failed to acquire token."; exit 1 }
|
||||||
|
Write-Output $r.AccessToken
|
||||||
# Check JWT expiry (payload is base64url, second segment)
|
|
||||||
try {
|
|
||||||
$parts = $token.Split('.')
|
|
||||||
$payload = $parts[1]
|
|
||||||
# Pad base64url to multiple of 4
|
|
||||||
$pad = 4 - ($payload.Length % 4); if ($pad -ne 4) { $payload += '=' * $pad }
|
|
||||||
$payload = $payload.Replace('-', '+').Replace('_', '/')
|
|
||||||
$claims = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($payload)) | ConvertFrom-Json
|
|
||||||
$expUtc = [System.DateTimeOffset]::FromUnixTimeSeconds($claims.exp).UtcDateTime
|
|
||||||
$remaining = ($expUtc - [System.DateTime]::UtcNow).TotalMinutes
|
|
||||||
|
|
||||||
if ($remaining -lt 2) {
|
|
||||||
Write-Warning "Token expired $(if ($remaining -lt 0) { [math]::Round(-$remaining) + ' min ago' } else { 'in < 2 min' }). Run: .\set-token.ps1 `"eyJ...`""
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
Write-Host " Token valid for $([math]::Round($remaining)) min." -ForegroundColor DarkGray
|
|
||||||
} catch {
|
|
||||||
Write-Warning "Could not parse token expiry - using as-is."
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Output $token
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue