aivi.auth
Types for OAuth 2.0 PKCE sign-in flows.
This module gives you the records and tagged unions used to model a browser-based sign-in flow plus the AuthSource handle marker for @source auth.
Import
use aivi.auth (
AuthSource
AuthTask
PkceConfig
PkceToken
PkceError
UserCancelled
NetworkError
InvalidResponse
PkceTimeout
PkceState
PkceIdle
PkceInProgress
PkceComplete
PkceFailed
)Overview
| Type | Purpose |
|---|---|
AuthSource | Handle annotation for @source auth |
AuthTask A | Background auth work returning A |
PkceConfig | Settings for one OAuth provider |
PkceToken | Access token details returned after sign-in |
PkceError | Why the flow failed or stopped |
PkceState | High-level state of the sign-in process |
Capability handle
use aivi.auth (AuthSource)
@source auth
signal auth : AuthSourceCurrent canonical handle members:
| Member | Type | Description |
|---|---|---|
auth.pkce config | AuthTask PkceToken | Run browser-based PKCE flow, wait for loopback callback, exchange code for tokens |
auth.refresh config refreshToken | AuthTask PkceToken | Exchange one refresh token for a fresh access token |
auth.pkce launches the external browser with xdg-open and listens on http://127.0.0.1:{redirectPort}/callback.
Construct Url fields with aivi.url.parse, handle its Err branch, then pass the completed PkceConfig to auth.pkce or auth.refresh.
PkceConfig
type PkceConfig = {
clientId: Text,
authEndpoint: Url,
tokenEndpoint: Url,
scopes: List Text,
redirectPort: Int
}Configuration for one PKCE login flow.
clientId— the OAuth client ID issued by the providerauthEndpoint— the browser URL where the user grants accesstokenEndpoint— the URL used to exchange the code for a tokenscopes— the permissions your app is asking forredirectPort— the local port that receives the browser callback
use aivi.auth (PkceConfig)
use aivi.url (Url)
type Url -> Url -> PkceConfig
func githubPkce = authEndpoint tokenEndpoint =>
{
clientId: "desktop-client",
authEndpoint: authEndpoint,
tokenEndpoint: tokenEndpoint,
scopes: ["read:user", "user:email"],
redirectPort: 43123
}PkceToken
type PkceToken = {
accessToken: Text,
refreshToken: Option Text,
expiresAt: Option Int
}Token data returned after a successful exchange.
accessToken— the token you send with authenticated requestsrefreshToken— an optional token for getting a fresh access token laterexpiresAt— an optional expiration time supplied by the provider
PkceError
type PkceError =
| UserCancelled
| NetworkError Text
| InvalidResponse Text
| PkceTimeoutReasons a PKCE flow can stop:
UserCancelled— the person closed or cancelled the sign-in flowNetworkError Text— the browser callback or token exchange failed because of networkingInvalidResponse Text— the provider replied, but the data could not be usedPkceTimeout— the flow took too long and was abandoned
use aivi.auth (
PkceError
UserCancelled
NetworkError
InvalidResponse
PkceTimeout
)
type PkceError -> Text
func describePkceError =
||> UserCancelled -> "sign-in cancelled"
||> NetworkError msg -> "network error: {msg}"
||> InvalidResponse msg -> "invalid response: {msg}"
||> PkceTimeout -> "sign-in timed out"PkceState
use aivi.auth (
PkceError
PkceToken
)
type PkceState =
| PkceIdle
| PkceInProgress
| PkceComplete PkceToken
| PkceFailed PkceErrorA simple state machine for the whole sign-in process.
PkceIdle— nothing has started yetPkceInProgress— the browser flow is runningPkceComplete token— sign-in finished and produced a tokenPkceFailed error— sign-in ended with aPkceError
use aivi.auth (
PkceState
PkceIdle
PkceInProgress
PkceComplete
PkceFailed
)
type PkceState -> Bool
func signedIn =
||> PkceComplete _ -> True
||> _ -> FalseRemaining public constructors and aliases
AuthTask A is Task PkceError A. NetworkError message and InvalidResponse message preserve provider failure details. PkceComplete token and PkceFailed error are the terminal PkceState constructors.