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
TypeScript
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