UNPKG

alepha

Version:

Alepha is a convention-driven TypeScript framework for building robust, end-to-end type-safe applications, from serverless APIs to full-stack React apps.

499 lines (498 loc) 16.7 kB
import * as _alepha_core4 from "alepha"; import { Alepha, AlephaError, Async, Descriptor, KIND, Static } from "alepha"; import * as _alepha_server_cookies0 from "alepha/server/cookies"; import { Cookies, ServerCookiesProvider } from "alepha/server/cookies"; import { DateTimeProvider } from "alepha/datetime"; import { AccessTokenResponse, RealmDescriptor, SecurityProvider, UserAccount, UserAccountToken } from "alepha/security"; import { Configuration } from "openid-client"; import * as _alepha_logger0 from "alepha/logger"; import * as _alepha_server0 from "alepha/server"; import { HttpClient } from "alepha/server"; import { HttpVirtualClient, ServerLinksProvider } from "alepha/server/links"; import * as typebox143 from "typebox"; //#region src/schemas/tokensSchema.d.ts declare const tokensSchema: typebox143.TObject<{ provider: typebox143.TString; access_token: typebox143.TString; issued_at: typebox143.TNumber; expires_in: typebox143.TOptional<typebox143.TNumber>; refresh_token: typebox143.TOptional<typebox143.TString>; refresh_token_expires_in: typebox143.TOptional<typebox143.TNumber>; refresh_expires_in: typebox143.TOptional<typebox143.TNumber>; id_token: typebox143.TOptional<typebox143.TString>; scope: typebox143.TOptional<typebox143.TString>; }>; type Tokens = Static<typeof tokensSchema>; //#endregion //#region src/services/ReactAuth.d.ts /** * Browser, SSR friendly, service to handle authentication. */ declare class ReactAuth { protected readonly log: _alepha_logger0.Logger; protected readonly alepha: Alepha; protected readonly httpClient: HttpClient; static path: { login: string; callback: string; logout: string; token: string; refresh: string; userinfo: string; }; protected readonly onBeginTransition: _alepha_core4.HookDescriptor<"react:transition:begin">; protected readonly onFetchRequest: _alepha_core4.HookDescriptor<"client:onRequest">; /** * Get the current authenticated user. * * Alias for `alepha.state.get("user")` */ get user(): UserAccountToken | undefined; ping(): Promise<{ name?: string | undefined; email?: string | undefined; username?: string | undefined; picture?: string | undefined; sessionId?: string | undefined; organizations?: string[] | undefined; roles?: string[] | undefined; id: string; } | undefined>; login(provider: string, options: { hostname?: string; username?: string; password?: string; redirect?: string; [extra: string]: any; }): Promise<Tokens>; logout(): void; } //#endregion //#region src/providers/ReactAuthProvider.d.ts declare class ReactAuthProvider { protected readonly log: _alepha_logger0.Logger; protected readonly alepha: Alepha; protected readonly serverCookiesProvider: ServerCookiesProvider; protected readonly dateTimeProvider: DateTimeProvider; protected readonly serverLinksProvider: ServerLinksProvider; protected readonly reactAuth: ReactAuth; protected readonly authorizationCode: _alepha_server_cookies0.AbstractCookieDescriptor<typebox143.TObject<{ provider: typebox143.TString; codeVerifier: typebox143.TOptional<typebox143.TString>; redirectUri: typebox143.TOptional<typebox143.TString>; state: typebox143.TOptional<typebox143.TString>; nonce: typebox143.TOptional<typebox143.TString>; }>>; readonly tokens: _alepha_server_cookies0.AbstractCookieDescriptor<typebox143.TObject<{ provider: typebox143.TString; access_token: typebox143.TString; issued_at: typebox143.TNumber; expires_in: typebox143.TOptional<typebox143.TNumber>; refresh_token: typebox143.TOptional<typebox143.TString>; refresh_token_expires_in: typebox143.TOptional<typebox143.TNumber>; refresh_expires_in: typebox143.TOptional<typebox143.TNumber>; id_token: typebox143.TOptional<typebox143.TString>; scope: typebox143.TOptional<typebox143.TString>; }>>; readonly onRender: _alepha_core4.HookDescriptor<"react:server:render:begin">; get identities(): Array<AuthDescriptor>; protected readonly configure: _alepha_core4.HookDescriptor<"configure">; protected getAccessTokens(tokens: Tokens): string | undefined; /** * Fill request headers with access token from cookies or fallback to provider's fallback function. */ protected readonly onRequest: _alepha_core4.HookDescriptor<"server:onRequest">; /** * Convert cookies to tokens. * If the tokens are expired, try to refresh them using the refresh token. */ protected cookiesToTokens(cookies: Cookies): Promise<Tokens | undefined>; protected refreshTokens(tokens: Tokens): Promise<Tokens | undefined>; /** * Get user information. */ readonly userinfo: _alepha_server0.RouteDescriptor<{ response: typebox143.TObject<{ user: typebox143.TOptional<typebox143.TObject<{ id: typebox143.TString; name: typebox143.TOptional<typebox143.TString>; email: typebox143.TOptional<typebox143.TString>; username: typebox143.TOptional<typebox143.TString>; picture: typebox143.TOptional<typebox143.TString>; sessionId: typebox143.TOptional<typebox143.TString>; organizations: typebox143.TOptional<typebox143.TArray<typebox143.TString>>; roles: typebox143.TOptional<typebox143.TArray<typebox143.TString>>; }>>; api: typebox143.TObject<{ prefix: typebox143.TOptional<typebox143.TString>; links: typebox143.TArray<typebox143.TObject<{ name: typebox143.TString; group: typebox143.TOptional<typebox143.TString>; path: typebox143.TString; method: typebox143.TOptional<typebox143.TString>; requestBodyType: typebox143.TOptional<typebox143.TString>; service: typebox143.TOptional<typebox143.TString>; }>>; }>; }>; }>; /** * Refresh a token for internal providers. */ readonly refresh: _alepha_server0.RouteDescriptor<{ query: typebox143.TObject<{ provider: typebox143.TString; }>; body: typebox143.TObject<{ refresh_token: typebox143.TString; access_token: typebox143.TOptional<typebox143.TString>; }>; response: typebox143.TObject<{ provider: typebox143.TString; access_token: typebox143.TString; issued_at: typebox143.TNumber; expires_in: typebox143.TOptional<typebox143.TNumber>; refresh_token: typebox143.TOptional<typebox143.TString>; refresh_token_expires_in: typebox143.TOptional<typebox143.TNumber>; refresh_expires_in: typebox143.TOptional<typebox143.TNumber>; id_token: typebox143.TOptional<typebox143.TString>; scope: typebox143.TOptional<typebox143.TString>; }>; }>; /** * Login for local password-based authentication. */ readonly token: _alepha_server0.RouteDescriptor<{ query: typebox143.TObject<{ provider: typebox143.TString; }>; body: typebox143.TObject<{ username: typebox143.TString; password: typebox143.TString; }>; response: typebox143.TObject<{ provider: typebox143.TString; access_token: typebox143.TString; issued_at: typebox143.TNumber; expires_in: typebox143.TOptional<typebox143.TNumber>; refresh_token: typebox143.TOptional<typebox143.TString>; refresh_token_expires_in: typebox143.TOptional<typebox143.TNumber>; refresh_expires_in: typebox143.TOptional<typebox143.TNumber>; id_token: typebox143.TOptional<typebox143.TString>; scope: typebox143.TOptional<typebox143.TString>; user: typebox143.TObject<{ id: typebox143.TString; name: typebox143.TOptional<typebox143.TString>; email: typebox143.TOptional<typebox143.TString>; username: typebox143.TOptional<typebox143.TString>; picture: typebox143.TOptional<typebox143.TString>; sessionId: typebox143.TOptional<typebox143.TString>; organizations: typebox143.TOptional<typebox143.TArray<typebox143.TString>>; roles: typebox143.TOptional<typebox143.TArray<typebox143.TString>>; }>; api: typebox143.TObject<{ prefix: typebox143.TOptional<typebox143.TString>; links: typebox143.TArray<typebox143.TObject<{ name: typebox143.TString; group: typebox143.TOptional<typebox143.TString>; path: typebox143.TString; method: typebox143.TOptional<typebox143.TString>; requestBodyType: typebox143.TOptional<typebox143.TString>; service: typebox143.TOptional<typebox143.TString>; }>>; }>; }>; }>; /** * Oauth2/OIDC login route. */ readonly login: _alepha_server0.RouteDescriptor<{ query: typebox143.TObject<{ provider: typebox143.TString; redirect_uri: typebox143.TOptional<typebox143.TString>; }>; }>; /** * Callback for OAuth2/OIDC providers. * It handles the authorization code flow and retrieves the access token. */ readonly callback: _alepha_server0.RouteDescriptor<_alepha_server0.RequestConfigSchema>; /** * Logout route for OAuth2/OIDC providers. */ readonly logout: _alepha_server0.RouteDescriptor<{ query: typebox143.TObject<{ post_logout_redirect_uri: typebox143.TOptional<typebox143.TString>; }>; }>; protected provider(opts: string | { provider: string; }): AuthDescriptor; protected setTokens(tokens: Tokens, cookies?: Cookies): void; } interface OAuth2Profile { sub: string; email?: string; name?: string; given_name?: string; family_name?: string; middle_name?: string; nickname?: string; preferred_username?: string; profile?: string; picture?: string; website?: string; email_verified?: boolean; gender?: string; birthdate?: string; zoneinfo?: string; locale?: string; phone_number?: string; phone_number_verified?: boolean; address?: { formatted?: string; street_address?: string; locality?: string; region?: string; postal_code?: string; country?: string; }; updated_at?: number; [key: string]: unknown; } //#endregion //#region src/descriptors/$auth.d.ts declare const $auth: { (options: AuthDescriptorOptions): AuthDescriptor; [KIND]: typeof AuthDescriptor; }; type AuthDescriptorOptions = { /** * Name of the identity provider. * If not provided, it will be derived from the property key. */ name?: string; /** * If true, auth provider will be skipped. */ disabled?: boolean; } & (AuthExternal | AuthInternal); /** * When you let an external service handle authentication. (e.g. Keycloak, Auth0, etc.) */ type AuthExternal = { /** * Only OIDC is supported for external authentication. */ oidc: OidcOptions; /** * For anonymous access, this will expect a service account access token. * * ```ts * class App { * anonymous = $serviceAccount(...); * auth = $auth({ * // ... config ... * fallback: this.anonymous, * }) * } * ``` */ fallback?: () => Async<AccessToken>; }; /** * When using your own authentication system, e.g. using a database to store user accounts. * This is usually used with a custom login form. * * This relies on the `realm`, which is used to create/verify the access token. */ type AuthInternal = { realm: RealmDescriptor; } & ({ /** * The common username/password authentication. * * - It uses the OAuth2 Client Credentials flow to obtain an access token. * * This is usually used with a custom login form on your website or mobile app. */ credentials: CredentialsOptions; } | { /** * OAuth2 authentication. Delegates authentication to an OAuth2 provider. (e.g. Google, GitHub, etc.) * * - It uses the OAuth2 Authorization Code flow to obtain an access token and user information. * * This is usually used with a login button that redirects to the OAuth2 provider. */ oauth: OAuth2Options; } | { /** * Like OAuth2, but uses OIDC (OpenID Connect) for authentication and user information retrieval. * OIDC is an identity layer on top of OAuth2, providing user authentication and profile information. * * - It uses the OAuth2 Authorization Code flow to obtain an access token and user information. * - PCKE (Proof Key for Code Exchange) is recommended for security. * * This is usually used with a login button that redirects to the OIDC provider. */ oidc: OidcOptions; }); type CredentialsOptions = { account: (credentials: { username: string; password: string; }) => Async<UserAccount>; }; interface OidcOptions { /** * URL of the OIDC issuer. */ issuer: string; /** * Client ID for the OIDC client. */ clientId: string; /** * Client secret for the OIDC client. * Optional if PKCE (Proof Key for Code Exchange) is used. */ clientSecret?: string; /** * Redirect URI for the OIDC client. * This is where the user will be redirected after authentication. */ redirectUri?: string; /** * For external auth providers only. * Take the ID token instead of the access token for validation. */ useIdToken?: boolean; /** * URI to redirect the user after logout. */ logoutUri?: string; /** * Optional scope for the OIDC client. * @default "openid profile email". */ scope?: string; account?: (tokens: { access_token: string; user: OAuth2Profile; id_token?: string; expires_in?: number; scope?: string; }) => Async<UserAccount>; } interface OAuth2Options { /** * URL of the OAuth2 authorization endpoint. */ clientId: string; /** * Client secret for the OAuth2 client. */ clientSecret: string; /** * URL of the OAuth2 authorization endpoint. */ authorization: string; /** * URL of the OAuth2 token endpoint. */ token: string; /** * Function to retrieve user profile information from the OAuth2 tokens. */ userinfo: (tokens: Tokens) => Async<OAuth2Profile>; account?: (tokens: { access_token: string; user: OAuth2Profile; id_token?: string; expires_in?: number; scope?: string; }) => Async<UserAccount>; /** * URL of the OAuth2 authorization endpoint. */ redirectUri?: string; /** * URL of the OAuth2 authorization endpoint. */ scope?: string; } declare class AuthDescriptor extends Descriptor<AuthDescriptorOptions> { protected readonly securityProvider: SecurityProvider; protected readonly dateTimeProvider: DateTimeProvider; oauth?: Configuration; get name(): string; get jwks_uri(): string; get scope(): string | undefined; get redirect_uri(): string | undefined; /** * Refreshes the access token using the refresh token. * Can be used on oauth2, oidc or credentials auth providers. */ refresh(refreshToken: string, accessToken?: string): Promise<AccessTokenResponse>; /** * Extracts user information from the access token. * This is used to create a user account from the access token. */ user(tokens: Tokens): Promise<UserAccount>; protected getUserFromIdToken(idToken: string): OAuth2Profile; prepare(): Promise<void>; } type AccessToken = string | { token: () => Async<string>; }; //#endregion //#region src/errors/SessionExpiredError.d.ts declare class SessionExpiredError extends AlephaError { readonly name = "SessionExpiredError"; readonly status = 401; } //#endregion //#region src/hooks/useAuth.d.ts declare const useAuth: <T extends object = any>() => { user: { name?: string | undefined; email?: string | undefined; username?: string | undefined; picture?: string | undefined; sessionId?: string | undefined; organizations?: string[] | undefined; roles?: string[] | undefined; id: string; } | undefined; logout: () => void; login: (provider: keyof T, options?: { username?: string; password?: string; redirect?: string; [extra: string]: any; }) => Promise<void>; can: <Api extends object = any>(name: keyof HttpVirtualClient<Api>) => boolean; }; //#endregion //#region src/index.d.ts declare module "alepha" { interface State { user?: UserAccount; } } declare module "alepha/react" { interface ReactRouterState { user?: UserAccount; } } /** * The ReactAuthModule provides authentication services for React applications. * * @see {@link ReactAuthProvider} * @module alepha.react.auth */ declare const AlephaReactAuth: _alepha_core4.Service<_alepha_core4.Module<{}>>; //#endregion export { $auth, AccessToken, AlephaReactAuth, AuthDescriptor, AuthDescriptorOptions, AuthExternal, AuthInternal, CredentialsOptions, OAuth2Options, OAuth2Profile, OidcOptions, ReactAuth, ReactAuthProvider, SessionExpiredError, useAuth }; //# sourceMappingURL=index.d.ts.map