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.
422 lines (420 loc) • 15 kB
TypeScript
import * as _alepha_core1 from "alepha";
import * as _alepha_core5 from "alepha";
import * as _alepha_core0 from "alepha";
import { Alepha, 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, UserAccountInfo, UserAccountToken } from "alepha/security";
import { Configuration } from "openid-client";
import * as _alepha_server0 from "alepha/server";
import { HttpClient } from "alepha/server";
import * as _alepha_server_links0 from "alepha/server/links";
import { HttpVirtualClient, LinkProvider, ServerLinksProvider } from "alepha/server/links";
import * as _sinclair_typebox92 from "@sinclair/typebox";
import * as _sinclair_typebox0 from "@sinclair/typebox";
//#region src/schemas/tokensSchema.d.ts
declare const tokensSchema: _sinclair_typebox92.TObject<{
provider: _sinclair_typebox92.TString;
access_token: _sinclair_typebox92.TString;
issued_at: _sinclair_typebox92.TNumber;
expires_in: _sinclair_typebox92.TOptional<_sinclair_typebox92.TNumber>;
refresh_token: _sinclair_typebox92.TOptional<_sinclair_typebox92.TString>;
refresh_token_expires_in: _sinclair_typebox92.TOptional<_sinclair_typebox92.TNumber>;
id_token: _sinclair_typebox92.TOptional<_sinclair_typebox92.TString>;
scope: _sinclair_typebox92.TOptional<_sinclair_typebox92.TString>;
}>;
type Tokens = Static<typeof tokensSchema>;
//# sourceMappingURL=tokensSchema.d.ts.map
//#endregion
//#region src/providers/ReactAuthProvider.d.ts
declare class ReactAuthProvider {
protected readonly log: _alepha_core1.Logger;
protected readonly alepha: Alepha;
protected readonly serverCookiesProvider: ServerCookiesProvider;
protected readonly securityProvider: SecurityProvider;
protected readonly dateTimeProvider: DateTimeProvider;
protected readonly serverLinksProvider: ServerLinksProvider;
protected readonly authorizationCode: _alepha_server_cookies0.AbstractCookieDescriptor<_sinclair_typebox0.TObject<{
provider: _sinclair_typebox0.TString;
codeVerifier: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
redirectUri: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
state: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
nonce: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
}>>;
readonly tokens: _alepha_server_cookies0.AbstractCookieDescriptor<_sinclair_typebox0.TObject<{
provider: _sinclair_typebox0.TString;
access_token: _sinclair_typebox0.TString;
issued_at: _sinclair_typebox0.TNumber;
expires_in: _sinclair_typebox0.TOptional<_sinclair_typebox0.TNumber>;
refresh_token: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
refresh_token_expires_in: _sinclair_typebox0.TOptional<_sinclair_typebox0.TNumber>;
id_token: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
scope: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
}>>;
readonly onRender: _alepha_core1.HookDescriptor<"react:server:render:begin">;
get identities(): Array<AuthDescriptor>;
protected readonly configure: _alepha_core1.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_core1.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>;
readonly userinfo: _alepha_server0.ActionDescriptor<{
response: _sinclair_typebox0.TObject<{
id: _sinclair_typebox0.TString;
name: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
email: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
picture: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
organizations: _sinclair_typebox0.TOptional<_sinclair_typebox0.TArray<_sinclair_typebox0.TString>>;
roles: _sinclair_typebox0.TOptional<_sinclair_typebox0.TArray<_sinclair_typebox0.TString>>;
}>;
}>;
readonly token: _alepha_server0.RouteDescriptor<{
query: _sinclair_typebox0.TObject<{
provider: _sinclair_typebox0.TString;
}>;
body: _sinclair_typebox0.TObject<{
username: _sinclair_typebox0.TString;
password: _sinclair_typebox0.TString;
}>;
response: _sinclair_typebox0.TObject<{
provider: _sinclair_typebox0.TString;
access_token: _sinclair_typebox0.TString;
issued_at: _sinclair_typebox0.TNumber;
expires_in: _sinclair_typebox0.TOptional<_sinclair_typebox0.TNumber>;
refresh_token: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
refresh_token_expires_in: _sinclair_typebox0.TOptional<_sinclair_typebox0.TNumber>;
id_token: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
scope: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
user: _sinclair_typebox0.TObject<{
id: _sinclair_typebox0.TString;
name: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
email: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
picture: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
organizations: _sinclair_typebox0.TOptional<_sinclair_typebox0.TArray<_sinclair_typebox0.TString>>;
roles: _sinclair_typebox0.TOptional<_sinclair_typebox0.TArray<_sinclair_typebox0.TString>>;
}>;
links: _sinclair_typebox0.TObject<{
prefix: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
links: _sinclair_typebox0.TArray<_sinclair_typebox0.TObject<{
name: _sinclair_typebox0.TString;
path: _sinclair_typebox0.TString;
method: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
group: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
requestBodyType: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
service: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
}>>;
}>;
}>;
}>;
readonly login: _alepha_server0.RouteDescriptor<{
query: _sinclair_typebox0.TObject<{
provider: _sinclair_typebox0.TString;
redirect_uri: _sinclair_typebox0.TOptional<_sinclair_typebox0.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>;
readonly logout: _alepha_server0.RouteDescriptor<{
query: _sinclair_typebox0.TObject<{
post_logout_redirect_uri: _sinclair_typebox0.TOptional<_sinclair_typebox0.TString>;
}>;
}>;
protected provider(opts: string | {
provider: string;
}): AuthDescriptor;
protected setTokens(tokens: Tokens, cookies?: Cookies): void;
}
interface OAuth2UserInfo {
sub: string;
name?: string;
given_name?: string;
family_name?: string;
middle_name?: string;
nickname?: string;
preferred_username?: string;
profile?: string;
picture?: string;
website?: string;
email?: 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;
}
//# sourceMappingURL=ReactAuthProvider.d.ts.map
//#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 = {
user: (entry: {
username: string;
password: string;
}) => Async<UserAccountInfo>;
};
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;
user?: (tokens: {
id_token?: string;
access_token: string;
expires_in?: number;
scope?: string;
user: OAuth2UserInfo;
}) => Async<UserAccountInfo>;
}
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.
*/
user: (tokens: Tokens) => Async<UserAccountInfo>;
/**
* 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.
*/
refresh(tokens: Tokens): 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<UserAccountInfo>;
protected getUserFromIdToken(idToken: string): OAuth2UserInfo;
prepare(): Promise<void>;
}
type AccessToken = string | {
token: () => Async<string>;
};
//# sourceMappingURL=$auth.d.ts.map
//#endregion
//#region src/hooks/useAuth.d.ts
declare const useAuth: <T extends object = any>() => {
user: {
name?: string | undefined;
email?: string | undefined;
picture?: 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;
};
//# sourceMappingURL=useAuth.d.ts.map
//#endregion
//#region src/services/ReactAuth.d.ts
declare class ReactAuth {
protected readonly log: _alepha_core5.Logger;
protected readonly alepha: Alepha;
protected readonly auth: _alepha_server_links0.HttpVirtualClient<ReactAuthProvider>;
protected readonly client: HttpClient;
protected readonly linkProvider: LinkProvider;
static path: {
login: string;
callback: string;
logout: string;
token: string;
userinfo: string;
};
protected readonly onFetchRequest: _alepha_core5.HookDescriptor<"client:onRequest">;
readonly onRender: _alepha_core5.HookDescriptor<"react:transition:begin">;
get user(): UserAccountToken | undefined;
login(provider: string, options: {
username?: string;
password?: string;
redirect?: string;
[extra: string]: any;
}): Promise<void>;
logout(): void;
}
//# sourceMappingURL=ReactAuth.d.ts.map
//#endregion
//#region src/index.d.ts
declare module "alepha" {
interface State {
user?: UserAccountInfo;
}
}
declare module "alepha/react" {
interface PageReactContext {
user?: UserAccountInfo;
}
interface ReactHydrationState {
user?: UserAccountInfo;
}
}
/**
* The ReactAuthModule provides authentication services for React applications.
*
* @see {@link ReactAuthProvider}
* @module alepha.react.auth
*/
declare const AlephaReactAuth: _alepha_core0.Service<_alepha_core0.Module>;
//# sourceMappingURL=index.d.ts.map
//#endregion
export { $auth, AccessToken, AlephaReactAuth, AuthDescriptor, AuthDescriptorOptions, AuthExternal, AuthInternal, CredentialsOptions, OAuth2Options, OAuth2UserInfo, OidcOptions, ReactAuth, ReactAuthProvider, useAuth };
//# sourceMappingURL=index.d.ts.map