/** * OAuth 2.0 device-code flow for Microsoft Identity Platform. * * Bespoke to Maxy — this is NOT the nsakki55 loopback authManager. Registration * runs headless: `startDeviceCode` asks Microsoft for a user code + verification * URL, the operator consents on any device at microsoft.com/devicelogin, and * `pollDeviceToken` exchanges the device_code for tokens. No loopback HTTP * server, no same-machine constraint. * * `refreshAccessToken` (used by the read path in graph-client.ts) and the SCOPES * set are unchanged from the prior Auth-Code implementation. */ export interface TokenResponse { access_token: string; refresh_token?: string; expires_in: number; token_type: string; scope?: string; } export interface DeviceCodeStart { deviceCode: string; userCode: string; verificationUri: string; verificationUriComplete: string; expiresInSec: number; intervalSec: number; scopes: string[]; } /** * Request a device code from `/oauth2/v2.0/devicecode`. Returns the user code * and verification URL to relay to the operator, plus the device_code the caller * persists for polling. `verificationUriComplete` uses the endpoint's field when * present, else Microsoft's documented `?otc=` pre-fill convenience form. */ export declare function startDeviceCode(config: { clientId: string; tenantId: string; }): Promise; export interface AzureTokenError { kind: "error"; httpStatus: number; error: string; errorDescription: string; /** The AADSTSnnnnn code, from `error_codes[0]` or parsed out of the description. */ aadsts: string | null; /** OAuth sub-error (e.g. `token_expired`, `bad_token`, `consent_required`) — the * field that distinguishes causes sharing one top-level `invalid_grant`. */ suberror: string | null; correlationId: string | null; traceId: string | null; timestamp: string | null; /** The verbatim response body — never discarded, so no diagnostic detail is lost. */ raw: string; } export type PollOutcome = { kind: "pending"; } | { kind: "slow_down"; } | { kind: "expired"; } | { kind: "denied"; } | { kind: "success"; tokenResponse: TokenResponse; scopes: string[]; } | AzureTokenError; /** * Parse a Microsoft token-endpoint error body into structured fields. Every part * Azure returns — AADSTS code, sub-error, description, correlation/trace IDs — is * captured so a poll failure is diagnosable from the log without re-deriving it * from an opaque string. A non-JSON body still yields a value: `raw` carries it. */ export declare function parseAzureTokenError(httpStatus: number, text: string): AzureTokenError; /** * One device-code token poll against `/oauth2/v2.0/token`. 200 yields tokens; * the four RFC 8628 polling states map to their kinds. Any other error is * returned as a structured `AzureTokenError` (never thrown, never discarded) so * the caller can log the full Microsoft reason instead of an opaque string. */ export declare function pollDeviceToken(config: { clientId: string; tenantId: string; }, deviceCode: string): Promise; /** * A non-ok response from the token endpoint, carrying the fully parsed Azure * error rather than only its prose. `azure.error` is `invalid_grant` when the * refresh token is revoked, expired, or already consumed — the one case that * justifies destroying an account's stored credentials. * * Callers branch on `azure.error`, never on the message text: whether to wipe a * mailbox must not depend on how Microsoft happens to word a response. */ export declare class TokenRefreshError extends Error { readonly azure: AzureTokenError; constructor(message: string, azure: AzureTokenError); /** The OAuth `error` field, or null when the body carried none (a gateway * 5xx, an empty body, non-JSON HTML). */ get oauthError(): string | null; get statusCode(): number; } export declare function refreshAccessToken(args: { clientId: string; tenantId: string; refreshToken: string; }): Promise; export declare const _internals: { SCOPES: string[]; }; //# sourceMappingURL=device-flow.d.ts.map