@absolutejs/auth 0.25.1 → 0.26.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/audit/config.d.ts +8 -0
  2. package/dist/audit/inMemoryAuditStore.d.ts +2 -0
  3. package/dist/audit/postgresAuditStore.d.ts +142 -0
  4. package/dist/audit/types.d.ts +18 -0
  5. package/dist/audit/wrap.d.ts +9 -0
  6. package/dist/credentials/config.d.ts +61 -0
  7. package/dist/credentials/emailVerification.d.ts +83 -0
  8. package/dist/credentials/inMemoryCredentialStore.d.ts +2 -0
  9. package/dist/credentials/login.d.ts +75 -0
  10. package/dist/credentials/passwordPolicy.d.ts +14 -0
  11. package/dist/credentials/passwordReset.d.ts +87 -0
  12. package/dist/credentials/postgresCredentialStore.d.ts +279 -0
  13. package/dist/credentials/register.d.ts +54 -0
  14. package/dist/credentials/routes.d.ts +200 -0
  15. package/dist/credentials/types.d.ts +26 -0
  16. package/dist/crypto.d.ts +32 -0
  17. package/dist/{ui → htmx}/index.js +2 -2
  18. package/dist/{ui → htmx}/index.js.map +2 -2
  19. package/dist/{htmxRoutes.d.ts → htmx/routes.d.ts} +4 -4
  20. package/dist/index.d.ts +427 -27
  21. package/dist/index.js +3314 -1932
  22. package/dist/index.js.map +60 -27
  23. package/dist/{neonLinkedProviders.d.ts → linkedProviders/neonStores.d.ts} +619 -613
  24. package/dist/{oauthLinkedProviderResolver.d.ts → linkedProviders/oauthResolver.d.ts} +1 -1
  25. package/dist/lockout/config.d.ts +17 -0
  26. package/dist/lockout/inMemoryLockoutStore.d.ts +2 -0
  27. package/dist/lockout/postgresLockoutStore.d.ts +81 -0
  28. package/dist/lockout/types.d.ts +12 -0
  29. package/dist/mfa/backupCodes.d.ts +5 -0
  30. package/dist/mfa/challenge.d.ts +65 -0
  31. package/dist/mfa/config.d.ts +32 -0
  32. package/dist/mfa/gate.d.ts +2 -0
  33. package/dist/mfa/inMemoryMfaStore.d.ts +2 -0
  34. package/dist/mfa/postgresMfaStore.d.ts +134 -0
  35. package/dist/mfa/routes.d.ts +117 -0
  36. package/dist/mfa/secret.d.ts +2 -0
  37. package/dist/mfa/totp.d.ts +91 -0
  38. package/dist/mfa/types.d.ts +16 -0
  39. package/dist/{providerClients.d.ts → providers/clients.d.ts} +35 -19
  40. package/dist/{authorize.d.ts → routes/authorize.d.ts} +5 -5
  41. package/dist/{callback.d.ts → routes/callback.d.ts} +4 -4
  42. package/dist/{profile.d.ts → routes/profile.d.ts} +5 -5
  43. package/dist/{protectRoute.d.ts → routes/protectRoute.d.ts} +5 -5
  44. package/dist/{refresh.d.ts → routes/refresh.d.ts} +5 -5
  45. package/dist/{revoke.d.ts → routes/revoke.d.ts} +6 -6
  46. package/dist/routes/sessions.d.ts +103 -0
  47. package/dist/{signout.d.ts → routes/signout.d.ts} +4 -4
  48. package/dist/routes/stepUp.d.ts +48 -0
  49. package/dist/{userStatus.d.ts → routes/userStatus.d.ts} +4 -4
  50. package/dist/{sessionAccess.d.ts → session/access.d.ts} +12 -12
  51. package/dist/{sessionCleanup.d.ts → session/cleanup.d.ts} +2 -2
  52. package/dist/{authSessionStores.d.ts → session/inMemoryStore.d.ts} +2 -2
  53. package/dist/{neonAuthSessionStore.d.ts → session/neonStore.d.ts} +209 -175
  54. package/dist/session/promote.d.ts +13 -0
  55. package/dist/session/sessionsConfig.d.ts +9 -0
  56. package/dist/{sessionStore.d.ts → session/state.d.ts} +1 -1
  57. package/dist/{sessionTypes.d.ts → session/types.d.ts} +1 -1
  58. package/dist/session/userSessions.d.ts +16 -0
  59. package/dist/stores/postgres.d.ts +5 -0
  60. package/dist/tenancy.d.ts +9 -0
  61. package/dist/typeGuards.d.ts +2 -2
  62. package/dist/typebox.d.ts +3 -3
  63. package/dist/types.d.ts +33 -3
  64. package/dist/utils.d.ts +9 -9
  65. package/package.json +19 -16
  66. /package/dist/{ui → htmx}/index.d.ts +0 -0
  67. /package/dist/{ui → htmx}/renderers.d.ts +0 -0
  68. /package/dist/{ui → htmx}/types.d.ts +0 -0
  69. /package/dist/{linkedProviderStores.d.ts → linkedProviders/inMemoryStores.d.ts} +0 -0
  70. /package/dist/{linkedProviderResolver.d.ts → linkedProviders/resolver.d.ts} +0 -0
@@ -0,0 +1,16 @@
1
+ import type { SessionData, UserSessionId } from '../types';
2
+ import type { AuthSessionStore } from './types';
3
+ export type UserSession<UserType> = {
4
+ id: UserSessionId;
5
+ session: SessionData<UserType>;
6
+ };
7
+ type ListUserSessionsProps<UserType> = {
8
+ authSessionStore: AuthSessionStore<UserType>;
9
+ getUserId: (user: UserType) => string;
10
+ userId: string;
11
+ };
12
+ export declare const listUserSessions: <UserType>({ authSessionStore, getUserId, userId }: ListUserSessionsProps<UserType>) => Promise<UserSession<UserType>[]>;
13
+ export declare const revokeUserSessions: <UserType>({ authSessionStore, exceptSessionId, getUserId, userId }: ListUserSessionsProps<UserType> & {
14
+ exceptSessionId?: UserSessionId;
15
+ }) => Promise<number>;
16
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { PgDatabase, PgQueryResultHKT } from 'drizzle-orm/pg-core';
2
+ export type AnyPgDatabase = PgDatabase<PgQueryResultHKT>;
3
+ export declare const createNeonDatabase: (databaseUrl: string) => import("drizzle-orm/neon-http").NeonHttpDatabase<Record<string, never>> & {
4
+ $client: import("@neondatabase/serverless").NeonQueryFunction<false, false>;
5
+ };
@@ -0,0 +1,9 @@
1
+ export type OrganizationId = string;
2
+ export type WithOrganization<Resource> = Resource & {
3
+ organizationId?: OrganizationId;
4
+ };
5
+ export declare const hasOrganizationScope: (value: {
6
+ organizationId?: OrganizationId;
7
+ }) => value is {
8
+ organizationId: OrganizationId;
9
+ };
@@ -1,6 +1,6 @@
1
1
  import { AuthIntent, StatusReturn, UserSessionId } from './types';
2
2
  export declare const isValidUser: <UserType>(user: unknown) => user is UserType;
3
- export declare const isUserSessionId: (key: string) => key is UserSessionId;
3
+ export declare const isAuthIntent: (value: unknown) => value is AuthIntent;
4
4
  export declare const isNonEmptyString: (str: string | null | undefined) => str is string;
5
5
  export declare const isStatusResponse: (value: unknown) => value is StatusReturn;
6
- export declare const isAuthIntent: (value: unknown) => value is AuthIntent;
6
+ export declare const isUserSessionId: (key: string) => key is UserSessionId;
package/dist/typebox.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export declare const userSessionIdTypebox: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TTemplateLiteralSyntax<"${string}-${string}-${string}-${string}-${string}">>;
1
+ export declare const authClientOption: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
2
+ export declare const authIntentOption: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"login">, import("@sinclair/typebox").TLiteral<"link_identity">, import("@sinclair/typebox").TLiteral<"link_connector">]>>;
2
3
  export declare const authProviderOption: import("@sinclair/typebox").TEnum<{
3
4
  [k: string]: "42" | "amazoncognito" | "anilist" | "apple" | "atlassian" | "auth0" | "authentik" | "autodesk" | "battlenet" | "bitbucket" | "box" | "bungie" | "coinbase" | "discord" | "donationalerts" | "dribbble" | "dropbox" | "epicgames" | "etsy" | "facebook" | "figma" | "gitea" | "github" | "gitlab" | "google" | "intuit" | "kakao" | "keycloak" | "kick" | "lichess" | "line" | "linear" | "linkedin" | "mastodon" | "mercadolibre" | "mercadopago" | "microsoftentraid" | "myanimelist" | "naver" | "notion" | "okta" | "osu" | "patreon" | "polar" | "polaraccesslink" | "polarteampro" | "reddit" | "roblox" | "salesforce" | "shikimori" | "slack" | "spotify" | "startgg" | "strava" | "synology" | "tiktok" | "tiltify" | "tumblr" | "twitch" | "twitter" | "vk" | "withings" | "workos" | "yahoo" | "yandex" | "zoom";
4
5
  }>;
5
- export declare const authClientOption: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
6
- export declare const authIntentOption: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"login">, import("@sinclair/typebox").TLiteral<"link_identity">, import("@sinclair/typebox").TLiteral<"link_connector">]>>;
6
+ export declare const userSessionIdTypebox: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TTemplateLiteralSyntax<"${string}-${string}-${string}-${string}-${string}">>;
package/dist/types.d.ts CHANGED
@@ -1,9 +1,14 @@
1
1
  import { CredentialsFor, NonEmptyArray, OAuth2Client, OAuth2TokenResponse, ProviderOption, ProvidersMap } from 'citra';
2
2
  import { Cookie, status as statusType, redirect as redirectType } from 'elysia';
3
3
  import { ElysiaCustomStatusResponse } from 'elysia/error';
4
+ import type { AuditConfig } from './audit/config';
5
+ import type { CredentialsConfig } from './credentials/config';
4
6
  import type { AuthIdentityConflict } from './errors';
5
- import type { AuthSessionStore } from './sessionTypes';
6
- import type { AuthHtmxConfig, AuthHtmxUser } from './ui/types';
7
+ import type { AuthHtmxConfig, AuthHtmxUser } from './htmx/types';
8
+ import type { LockoutConfig } from './lockout/config';
9
+ import type { MfaConfig } from './mfa/config';
10
+ import type { SessionsConfig } from './session/sessionsConfig';
11
+ import type { AuthSessionStore } from './session/types';
7
12
  export type AuthIntent = 'login' | 'link_identity' | 'link_connector';
8
13
  export type OAuth2ProviderClientConfiguration<Provider extends ProviderOption> = {
9
14
  credentials: CredentialsFor<Provider>;
@@ -20,9 +25,15 @@ export type OAuth2ConfigurationOptions = {
20
25
  export type UserSessionId = `${string}-${string}-${string}-${string}-${string}`;
21
26
  export type SessionData<UserType> = {
22
27
  user: UserType;
23
- accessToken: string;
28
+ /** OAuth provider access token. Optional: credential / SSO sessions are not backed
29
+ * by a provider token, so they omit it. Only the OAuth routes (profile, refresh,
30
+ * revoke) read it, and they are all gated on an `auth_provider`. */
31
+ accessToken?: string;
24
32
  refreshToken?: string;
25
33
  expiresAt: number;
34
+ /** When the session was last established by an actual authentication (login, OAuth
35
+ * callback, or MFA challenge — NOT a token refresh). Drives step-up `requireRecentAuth`. */
36
+ authenticatedAt?: number;
26
37
  };
27
38
  export type SessionRecord<UserType> = Record<UserSessionId, SessionData<UserType>>;
28
39
  export type UnregisteredSessionData = {
@@ -151,6 +162,25 @@ export type AuthConfig<UserType> = {
151
162
  maxSessions?: number;
152
163
  sessionDurationMs?: number;
153
164
  authSessionStore?: AuthSessionStore<UserType>;
165
+ /** Append-only audit logging. When present, `auth()` emits structured events
166
+ * (register, login, mfa_*, password_reset, logout, …) from every flow into the
167
+ * `auditStore` and/or `onAuditEvent` hook. SOC 2 prerequisite. */
168
+ audit?: AuditConfig<UserType>;
169
+ /** Local email/password (credentials) block. Additive and optional — when present,
170
+ * mounts register / verify-email / login / reset-password routes that produce the
171
+ * same `SessionData<UserType>` as OAuth, transparent to `protectRoute`. */
172
+ credentials?: CredentialsConfig<UserType>;
173
+ /** Multi-factor auth (TOTP + backup codes). When present alongside `credentials`,
174
+ * `auth()` auto-wires the login MFA gate, mounts the enroll/challenge routes, and
175
+ * promotes the parked session once a factor is verified. */
176
+ mfa?: MfaConfig<UserType>;
177
+ /** Per-identity attempt throttling + account lockout on the credential login route
178
+ * (progressive: locks after `maxAttempts` failures within `windowMs`). */
179
+ lockout?: LockoutConfig;
180
+ /** Self-service session management: `GET /auth/sessions` (list the caller's active
181
+ * sessions) and `DELETE /auth/sessions/:id` (remote revoke). Requires an
182
+ * `authSessionStore` that can enumerate sessions. */
183
+ sessions?: SessionsConfig<UserType>;
154
184
  /** Enable the built-in HTMX fragment routes (login, identities, connectors,
155
185
  * account, signout, delete-account). Supply provider display data + the
156
186
  * identity/connector data actions; the package owns the route wiring and
package/dist/utils.d.ts CHANGED
@@ -1,15 +1,7 @@
1
1
  import { OAuth2Client, OAuth2TokenResponse, ProviderOption } from 'citra';
2
2
  import { Cookie } from 'elysia';
3
+ import { AuthHtmxConfig } from './htmx/types';
3
4
  import { AuthConfig, InsantiateUserSessionProps, OAuth2ConfigurationOptions, ResolvedOAuthAuthorization, SessionRecord, UnregisteredSessionRecord, UserSessionId } from './types';
4
- import { AuthHtmxConfig } from './ui/types';
5
- export declare const resolveOAuthTokenExpiresAt: (tokenResponse: OAuth2TokenResponse, now?: number) => number | undefined;
6
- export declare const resolveOAuthAuthorization: ({ authProvider, providerInstance, tokenResponse, now }: {
7
- authProvider: ProviderOption;
8
- providerInstance: OAuth2Client<ProviderOption>;
9
- tokenResponse: OAuth2TokenResponse;
10
- now?: number;
11
- }) => Promise<ResolvedOAuthAuthorization>;
12
- export declare const instantiateUserSession: <UserType>({ authProvider, session, user_session_id, unregisteredSession, tokenResponse, providerInstance, getUser, onNewUser, resolvedAuthorization, sessionDurationMs, unregisteredSessionDurationMs }: InsantiateUserSessionProps<UserType>) => Promise<import("./types").StatusReturn | Response | undefined>;
13
5
  export declare const defineAuthConfig: <UserType>(configuration: AuthConfig<UserType>) => AuthConfig<UserType>;
14
6
  export declare const defineAuthHtmxConfig: (htmxConfig: AuthHtmxConfig) => AuthHtmxConfig;
15
7
  export declare const defineProvidersConfiguration: (providersConfiguration: OAuth2ConfigurationOptions) => OAuth2ConfigurationOptions;
@@ -23,6 +15,14 @@ export declare const getStatus: <UserType>(session: SessionRecord<UserType>, use
23
15
  error: null;
24
16
  user: NonNullable<UserType> | null;
25
17
  }>;
18
+ export declare const instantiateUserSession: <UserType>({ authProvider, session, user_session_id, unregisteredSession, tokenResponse, providerInstance, getUser, onNewUser, resolvedAuthorization, sessionDurationMs, unregisteredSessionDurationMs }: InsantiateUserSessionProps<UserType>) => Promise<Response | import("./types").StatusReturn | undefined>;
19
+ export declare const resolveOAuthAuthorization: ({ authProvider, providerInstance, tokenResponse, now }: {
20
+ authProvider: ProviderOption;
21
+ providerInstance: OAuth2Client<ProviderOption>;
22
+ tokenResponse: OAuth2TokenResponse;
23
+ now?: number;
24
+ }) => Promise<ResolvedOAuthAuthorization>;
25
+ export declare const resolveOAuthTokenExpiresAt: (tokenResponse: OAuth2TokenResponse, now?: number) => number | undefined;
26
26
  type ValidateSessionProps<SessionType extends Record<string, unknown> & {
27
27
  expiresAt: number;
28
28
  }> = {
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.25.1",
2
+ "version": "0.26.0-beta.0",
3
3
  "name": "@absolutejs/auth",
4
4
  "description": "An authorization library for absolutejs",
5
5
  "repository": {
@@ -10,11 +10,11 @@
10
10
  "license": "CC BY-NC 4.0",
11
11
  "author": "Alex Kahn",
12
12
  "scripts": {
13
- "build": "rm -rf dist && bun build src/index.ts src/ui/index.ts --outdir dist --sourcemap --target=bun --external elysia && tsc --emitDeclarationOnly --project tsconfig.json",
14
- "test": "echo \"Error: no test specified\" && exit 1",
15
- "format": "prettier --write \"./**/*.{js,jsx,ts,tsx,css,json}\"",
16
- "lint": "eslint ./src ./eslint.config.mjs",
17
- "typecheck": "bun run tsc --noEmit",
13
+ "build": "rm -rf dist && bun build src/index.ts src/htmx/index.ts --outdir dist --sourcemap --target=bun --external elysia && tsc --emitDeclarationOnly --project tsconfig.json",
14
+ "test": "bun test",
15
+ "format": "absolute prettier --write",
16
+ "lint": "absolute eslint",
17
+ "typecheck": "absolute typecheck",
18
18
  "release": "bun run format && bun run build && bun publish"
19
19
  },
20
20
  "keywords": [
@@ -35,17 +35,20 @@
35
35
  "drizzle-orm": "0.41.0"
36
36
  },
37
37
  "devDependencies": {
38
- "@stylistic/eslint-plugin-ts": "4.2.0",
38
+ "@absolutejs/absolute": "^0.19.0-beta.1023",
39
+ "@eslint/js": "^10.0.1",
40
+ "@stylistic/eslint-plugin": "^5.10.0",
39
41
  "@types/bun": "1.2.9",
42
+ "@typescript-eslint/parser": "^8.57.2",
40
43
  "elysia": "1.4.26",
41
- "eslint": "9.26.0",
42
- "eslint-plugin-absolute": "0.0.3",
43
- "eslint-plugin-import": "2.31.0",
44
- "eslint-plugin-promise": "7.2.1",
45
- "eslint-plugin-security": "3.0.1",
44
+ "eslint": "^10.1.0",
45
+ "eslint-plugin-absolute": "^0.11.0",
46
+ "eslint-plugin-promise": "^7.2.1",
47
+ "eslint-plugin-security": "^4.0.0",
48
+ "globals": "^17.4.0",
46
49
  "prettier": "3.5.3",
47
50
  "typescript": "5.8.3",
48
- "typescript-eslint": "8.32.0"
51
+ "typescript-eslint": "^8.57.2"
49
52
  },
50
53
  "module": "./dist/index.js",
51
54
  "exports": {
@@ -53,9 +56,9 @@
53
56
  "import": "./dist/index.js",
54
57
  "types": "./dist/index.d.ts"
55
58
  },
56
- "./ui": {
57
- "import": "./dist/ui/index.js",
58
- "types": "./dist/ui/index.d.ts"
59
+ "./htmx": {
60
+ "import": "./dist/htmx/index.js",
61
+ "types": "./dist/htmx/index.d.ts"
59
62
  }
60
63
  },
61
64
  "type": "module",
File without changes
File without changes
File without changes