@korajs/auth 0.4.0 → 0.5.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.
package/dist/server.d.ts CHANGED
@@ -33,6 +33,12 @@ interface TokenRevocationStore {
33
33
  * @param deviceId - The device ID whose tokens should be revoked
34
34
  */
35
35
  revokeAllForDevice(deviceId: string): Promise<void>;
36
+ /**
37
+ * Check whether all tokens for a device have been revoked.
38
+ * @param deviceId - The device ID to check
39
+ * @returns true if the device's token family has been revoked
40
+ */
41
+ isDeviceRevoked(deviceId: string): Promise<boolean>;
36
42
  }
37
43
  /**
38
44
  * In-memory token revocation store.
@@ -53,7 +59,7 @@ declare class InMemoryTokenRevocationStore implements TokenRevocationStore {
53
59
  /**
54
60
  * Check if a device has been revoked.
55
61
  */
56
- isDeviceRevoked(deviceId: string): boolean;
62
+ isDeviceRevoked(deviceId: string): Promise<boolean>;
57
63
  /**
58
64
  * Remove expired revocations to prevent unbounded memory growth.
59
65
  * Call periodically (e.g., every hour) in long-running servers.
@@ -201,7 +207,7 @@ declare class TokenManager {
201
207
  * Validate a token and check it against the revocation store.
202
208
  *
203
209
  * Like {@link validateToken}, but also checks whether the token's `jti` has been
204
- * revoked. Requires a revocation store to be configured.
210
+ * revoked or belongs to a revoked device. Requires a revocation store to be configured.
205
211
  *
206
212
  * @param token - The JWT string to validate
207
213
  * @returns The decoded {@link TokenPayload} if valid and not revoked, or null otherwise
@@ -857,6 +863,332 @@ declare class BuiltInAuthRoutes {
857
863
  };
858
864
  }
859
865
 
866
+ /**
867
+ * Configuration for an OAuth 2.0 provider.
868
+ */
869
+ interface OAuthProviderConfig {
870
+ /** Provider identifier (e.g., 'google', 'github', 'microsoft') */
871
+ providerId: string;
872
+ /** OAuth client ID */
873
+ clientId: string;
874
+ /** OAuth client secret. Required for confidential server-side clients. */
875
+ clientSecret?: string;
876
+ /** Authorization endpoint URL */
877
+ authorizationUrl: string;
878
+ /** Token exchange endpoint URL */
879
+ tokenUrl: string;
880
+ /** User info endpoint URL */
881
+ userInfoUrl: string;
882
+ /** OAuth scopes to request */
883
+ scopes: string[];
884
+ /** Redirect URI for the callback */
885
+ redirectUri: string;
886
+ /**
887
+ * Enable PKCE (Proof Key for Code Exchange).
888
+ *
889
+ * Required for public clients such as desktop and mobile apps, and recommended
890
+ * whenever the provider supports it.
891
+ */
892
+ pkce?: boolean;
893
+ }
894
+ /**
895
+ * Tokens returned by the OAuth provider after code exchange.
896
+ */
897
+ interface OAuthTokens {
898
+ /** OAuth access token */
899
+ accessToken: string;
900
+ /** Token type (usually 'Bearer') */
901
+ tokenType: string;
902
+ /** Access token expiry in seconds (if provided) */
903
+ expiresIn?: number;
904
+ /** Refresh token (if provided) */
905
+ refreshToken?: string;
906
+ /** ID token (if provided, e.g., OpenID Connect) */
907
+ idToken?: string;
908
+ /** Granted scopes (may differ from requested scopes) */
909
+ scope?: string;
910
+ }
911
+ /**
912
+ * User information from the OAuth provider.
913
+ */
914
+ interface OAuthUserInfo {
915
+ /** Provider-specific user ID */
916
+ providerId: string;
917
+ /** Provider name (e.g., 'google', 'github') */
918
+ provider: string;
919
+ /** User's email address (may be null if not granted) */
920
+ email: string | null;
921
+ /** Whether the email is verified by the provider */
922
+ emailVerified: boolean;
923
+ /** User's display name */
924
+ name: string | null;
925
+ /** URL to the user's avatar/profile picture */
926
+ avatarUrl: string | null;
927
+ /** Raw profile data from the provider */
928
+ rawProfile: Record<string, unknown>;
929
+ }
930
+ /**
931
+ * State stored during the OAuth flow for CSRF protection.
932
+ */
933
+ interface OAuthState {
934
+ /** Random state parameter for CSRF protection */
935
+ state: string;
936
+ /** Provider ID */
937
+ provider: string;
938
+ /** Redirect URI used for this flow */
939
+ redirectUri: string;
940
+ /** When this state was created (ms since epoch) */
941
+ createdAt: number;
942
+ /** When this state expires (ms since epoch) */
943
+ expiresAt: number;
944
+ /** Optional: user-defined data to pass through the flow */
945
+ metadata?: Record<string, unknown>;
946
+ /** PKCE code verifier, stored server-side until the callback is consumed. */
947
+ codeVerifier?: string;
948
+ }
949
+ /**
950
+ * Store for OAuth state parameters.
951
+ */
952
+ interface OAuthStateStore {
953
+ /** Store a state parameter for later validation. */
954
+ store(state: OAuthState): Promise<void>;
955
+ /** Consume a state parameter (single-use). Returns null if not found or expired. */
956
+ consume(stateValue: string): Promise<OAuthState | null>;
957
+ /** Clean up expired states. */
958
+ cleanExpired(): Promise<number>;
959
+ }
960
+ /**
961
+ * A linked OAuth identity for a user.
962
+ * Users can have multiple linked identities (e.g., Google + GitHub).
963
+ */
964
+ interface LinkedIdentity {
965
+ /** Unique ID of this link */
966
+ id: string;
967
+ /** Kora user ID */
968
+ userId: string;
969
+ /** OAuth provider name */
970
+ provider: string;
971
+ /** Provider-specific user ID */
972
+ providerUserId: string;
973
+ /** Provider email (at time of linking) */
974
+ email: string | null;
975
+ /** When this identity was linked */
976
+ linkedAt: number;
977
+ }
978
+ declare class OAuthError extends KoraError {
979
+ constructor(message: string, code: string, context?: Record<string, unknown>);
980
+ }
981
+ declare class OAuthStateMismatchError extends OAuthError {
982
+ constructor();
983
+ }
984
+ declare class OAuthCodeExchangeError extends OAuthError {
985
+ constructor(details?: string);
986
+ }
987
+ declare class OAuthUserInfoError extends OAuthError {
988
+ constructor(details?: string);
989
+ }
990
+ declare class OAuthProviderNotFoundError extends OAuthError {
991
+ constructor(provider: string);
992
+ }
993
+
994
+ interface LinkedIdentityStore {
995
+ findByProvider(provider: string, providerUserId: string): Promise<LinkedIdentity | null>;
996
+ findByUser(userId: string): Promise<LinkedIdentity[]>;
997
+ create(params: {
998
+ userId: string;
999
+ provider: string;
1000
+ providerUserId: string;
1001
+ email: string | null;
1002
+ }): Promise<LinkedIdentity>;
1003
+ delete(userId: string, provider: string): Promise<void>;
1004
+ }
1005
+ declare class DuplicateLinkedIdentityError extends KoraError {
1006
+ constructor(provider: string);
1007
+ }
1008
+ declare class InMemoryLinkedIdentityStore implements LinkedIdentityStore {
1009
+ private readonly identitiesById;
1010
+ private readonly identityIdByProvider;
1011
+ private readonly identityIdsByUser;
1012
+ private readonly identityIdByUserProvider;
1013
+ findByProvider(provider: string, providerUserId: string): Promise<LinkedIdentity | null>;
1014
+ findByUser(userId: string): Promise<LinkedIdentity[]>;
1015
+ create(params: {
1016
+ userId: string;
1017
+ provider: string;
1018
+ providerUserId: string;
1019
+ email: string | null;
1020
+ }): Promise<LinkedIdentity>;
1021
+ delete(userId: string, provider: string): Promise<void>;
1022
+ }
1023
+
1024
+ /**
1025
+ * In-memory OAuth state store for development.
1026
+ * Use Redis or a database in production for multi-server deployments.
1027
+ */
1028
+ declare class InMemoryOAuthStateStore implements OAuthStateStore {
1029
+ private readonly states;
1030
+ store(state: OAuthState): Promise<void>;
1031
+ consume(stateValue: string): Promise<OAuthState | null>;
1032
+ cleanExpired(): Promise<number>;
1033
+ }
1034
+ /**
1035
+ * Configuration for the OAuth manager.
1036
+ */
1037
+ interface OAuthManagerConfig {
1038
+ /** Registered OAuth providers */
1039
+ providers: OAuthProviderConfig[];
1040
+ /** State store. Defaults to InMemoryOAuthStateStore. */
1041
+ stateStore?: OAuthStateStore;
1042
+ /** State TTL in milliseconds. Defaults to 10 minutes. */
1043
+ stateTtlMs?: number;
1044
+ /**
1045
+ * Custom fetch function. Defaults to global fetch.
1046
+ * Useful for testing or custom HTTP clients.
1047
+ */
1048
+ fetch?: typeof globalThis.fetch;
1049
+ }
1050
+ /**
1051
+ * Manages the OAuth 2.0 authorization code flow.
1052
+ *
1053
+ * Supports any standard OAuth 2.0 / OpenID Connect provider.
1054
+ * Pre-built configurations available for Google, GitHub, and Microsoft.
1055
+ *
1056
+ * @example
1057
+ * ```typescript
1058
+ * const oauth = new OAuthManager({
1059
+ * providers: [
1060
+ * googleProvider({ clientId: '...', clientSecret: '...', redirectUri: '...' }),
1061
+ * githubProvider({ clientId: '...', clientSecret: '...', redirectUri: '...' }),
1062
+ * ],
1063
+ * })
1064
+ *
1065
+ * // Step 1: Generate authorization URL
1066
+ * const { url, state } = await oauth.getAuthorizationUrl('google')
1067
+ * // Redirect user to url...
1068
+ *
1069
+ * // Step 2: Handle callback
1070
+ * const { tokens, userInfo } = await oauth.handleCallback('google', code, stateParam)
1071
+ * ```
1072
+ */
1073
+ declare class OAuthManager {
1074
+ private readonly providers;
1075
+ private readonly stateStore;
1076
+ private readonly stateTtlMs;
1077
+ private readonly fetchFn;
1078
+ constructor(config: OAuthManagerConfig);
1079
+ /**
1080
+ * Generate an authorization URL for the user to visit.
1081
+ * Returns the URL and the state parameter for CSRF validation.
1082
+ */
1083
+ getAuthorizationUrl(providerId: string, metadata?: Record<string, unknown>): Promise<{
1084
+ url: string;
1085
+ state: string;
1086
+ }>;
1087
+ /**
1088
+ * Handle the OAuth callback after the user authorizes.
1089
+ * Validates the state parameter, exchanges the code for tokens,
1090
+ * and fetches user info.
1091
+ *
1092
+ * @param providerId - The OAuth provider
1093
+ * @param code - The authorization code from the callback
1094
+ * @param state - The state parameter from the callback
1095
+ * @returns Tokens and user info from the provider
1096
+ */
1097
+ handleCallback(providerId: string, code: string, state: string): Promise<{
1098
+ tokens: OAuthTokens;
1099
+ userInfo: OAuthUserInfo;
1100
+ stateMetadata?: Record<string, unknown>;
1101
+ }>;
1102
+ /**
1103
+ * Get a registered provider by ID.
1104
+ */
1105
+ getProvider(providerId: string): OAuthProviderConfig;
1106
+ /**
1107
+ * List all registered provider IDs.
1108
+ */
1109
+ getProviderIds(): string[];
1110
+ private exchangeCodeForTokens;
1111
+ private fetchUserInfo;
1112
+ }
1113
+ interface ProviderFactoryConfig {
1114
+ clientId: string;
1115
+ clientSecret?: string;
1116
+ redirectUri: string;
1117
+ scopes?: string[];
1118
+ pkce?: boolean;
1119
+ }
1120
+ /**
1121
+ * Create a Google OAuth provider configuration.
1122
+ */
1123
+ declare function googleProvider(config: ProviderFactoryConfig): OAuthProviderConfig;
1124
+ /**
1125
+ * Create a GitHub OAuth provider configuration.
1126
+ */
1127
+ declare function githubProvider(config: ProviderFactoryConfig): OAuthProviderConfig;
1128
+ /**
1129
+ * Create a Microsoft OAuth provider configuration.
1130
+ */
1131
+ declare function microsoftProvider(config: ProviderFactoryConfig & {
1132
+ tenantId?: string;
1133
+ }): OAuthProviderConfig;
1134
+
1135
+ interface KoraAuthHttpRequest {
1136
+ method: string;
1137
+ path: string;
1138
+ body?: unknown;
1139
+ headers?: Record<string, string | string[] | undefined>;
1140
+ query?: Record<string, string | string[] | undefined>;
1141
+ ip?: string;
1142
+ }
1143
+ interface OAuthServerConfig extends Omit<OAuthManagerConfig, 'providers'> {
1144
+ providers: OAuthProviderConfig[];
1145
+ linkedIdentityStore?: LinkedIdentityStore;
1146
+ /** Create a Kora user on first OAuth sign-in. Defaults to true. */
1147
+ createNewUsers?: boolean;
1148
+ /**
1149
+ * Link OAuth identities to an existing Kora user with the same verified email.
1150
+ * Defaults to false so apps choose this trust boundary explicitly.
1151
+ */
1152
+ autoLinkVerifiedEmail?: boolean;
1153
+ /**
1154
+ * Allow a user to unlink their last OAuth identity. Defaults to false to avoid
1155
+ * locking out OAuth-created accounts that do not have a known password.
1156
+ */
1157
+ allowUnlinkLastIdentity?: boolean;
1158
+ }
1159
+ interface CreateKoraAuthServerOptions {
1160
+ /** Existing user store. Defaults to InMemoryUserStore for development. */
1161
+ userStore?: UserStore;
1162
+ /** Existing token manager. Overrides `jwtSecret` and `tokenManager` options. */
1163
+ tokenManager?: TokenManager;
1164
+ /** JWT secret. Required in production when `tokenManager` is not provided. */
1165
+ jwtSecret?: string | string[];
1166
+ /** Additional TokenManager options. */
1167
+ tokenManagerOptions?: Omit<TokenManagerConfig, 'secret'>;
1168
+ /** Auth HTTP path prefix. Defaults to `/auth`. */
1169
+ path?: string;
1170
+ /** OAuth provider routes and account-linking storage. */
1171
+ oauth?: OAuthServerConfig;
1172
+ challengeStore?: ChallengeStore;
1173
+ rateLimiter?: RateLimiter;
1174
+ }
1175
+ interface KoraAuthServer {
1176
+ routes: BuiltInAuthRoutes;
1177
+ userStore: UserStore;
1178
+ tokenManager: TokenManager;
1179
+ oauth?: OAuthManager;
1180
+ linkedIdentityStore?: LinkedIdentityStore;
1181
+ auth: ReturnType<BuiltInAuthRoutes['toSyncAuthProvider']>;
1182
+ handleRequest(request: KoraAuthHttpRequest): Promise<AuthRouteResponse<unknown>>;
1183
+ }
1184
+ /**
1185
+ * Create the built-in Kora auth server with production-shaped defaults.
1186
+ *
1187
+ * Simple apps can use `handleRequest()` for all `/auth/*` HTTP endpoints and
1188
+ * pass `auth` directly to `createProductionServer({ syncOptions: { auth } })`.
1189
+ */
1190
+ declare function createKoraAuthServer(options?: CreateKoraAuthServerOptions): KoraAuthServer;
1191
+
860
1192
  /**
861
1193
  * Creates a signed JWT (HS256) from a payload and secret.
862
1194
  *
@@ -1279,7 +1611,7 @@ declare class EmailVerificationManager {
1279
1611
  * Minimal better-sqlite3 subset to avoid a hard dependency on the package.
1280
1612
  * The real Database instance satisfies this at runtime.
1281
1613
  */
1282
- interface SqliteDatabase {
1614
+ interface SqliteDatabase$1 {
1283
1615
  pragma(source: string): unknown;
1284
1616
  exec(source: string): void;
1285
1617
  prepare(source: string): {
@@ -1309,7 +1641,7 @@ interface SqliteDatabase {
1309
1641
  */
1310
1642
  declare class SqliteUserStore implements UserStore {
1311
1643
  private readonly db;
1312
- constructor(db: SqliteDatabase);
1644
+ constructor(db: SqliteDatabase$1);
1313
1645
  private ensureTables;
1314
1646
  createUser(params: {
1315
1647
  email: string;
@@ -1352,8 +1684,8 @@ declare function createSqliteUserStore(options: {
1352
1684
  * Avoids a hard dependency on the postgres package.
1353
1685
  * Uses Record<string, unknown>[] for result type to match postgres-js return shape.
1354
1686
  */
1355
- interface PostgresClient {
1356
- begin<T>(fn: (sql: PostgresClient) => Promise<T>): Promise<T>;
1687
+ interface PostgresClient$1 {
1688
+ begin<T>(fn: (sql: PostgresClient$1) => Promise<T>): Promise<T>;
1357
1689
  (template: TemplateStringsArray, ...args: unknown[]): Promise<Record<string, unknown>[]>;
1358
1690
  }
1359
1691
  /**
@@ -1379,7 +1711,7 @@ interface PostgresClient {
1379
1711
  declare class PostgresUserStore implements UserStore {
1380
1712
  private readonly sql;
1381
1713
  private readonly ready;
1382
- constructor(sql: PostgresClient);
1714
+ constructor(sql: PostgresClient$1);
1383
1715
  private ensureTables;
1384
1716
  createUser(params: {
1385
1717
  email: string;
@@ -2960,234 +3292,93 @@ declare class OrgScopeResolver {
2960
3292
  private resolveCollectionScope;
2961
3293
  }
2962
3294
 
2963
- /**
2964
- * Configuration for an OAuth 2.0 provider.
2965
- */
2966
- interface OAuthProviderConfig {
2967
- /** Provider identifier (e.g., 'google', 'github', 'microsoft') */
2968
- providerId: string;
2969
- /** OAuth client ID */
2970
- clientId: string;
2971
- /** OAuth client secret */
2972
- clientSecret: string;
2973
- /** Authorization endpoint URL */
2974
- authorizationUrl: string;
2975
- /** Token exchange endpoint URL */
2976
- tokenUrl: string;
2977
- /** User info endpoint URL */
2978
- userInfoUrl: string;
2979
- /** OAuth scopes to request */
2980
- scopes: string[];
2981
- /** Redirect URI for the callback */
2982
- redirectUri: string;
2983
- }
2984
- /**
2985
- * Tokens returned by the OAuth provider after code exchange.
2986
- */
2987
- interface OAuthTokens {
2988
- /** OAuth access token */
2989
- accessToken: string;
2990
- /** Token type (usually 'Bearer') */
2991
- tokenType: string;
2992
- /** Access token expiry in seconds (if provided) */
2993
- expiresIn?: number;
2994
- /** Refresh token (if provided) */
2995
- refreshToken?: string;
2996
- /** ID token (if provided, e.g., OpenID Connect) */
2997
- idToken?: string;
2998
- /** Granted scopes (may differ from requested scopes) */
2999
- scope?: string;
3000
- }
3001
- /**
3002
- * User information from the OAuth provider.
3003
- */
3004
- interface OAuthUserInfo {
3005
- /** Provider-specific user ID */
3006
- providerId: string;
3007
- /** Provider name (e.g., 'google', 'github') */
3008
- provider: string;
3009
- /** User's email address (may be null if not granted) */
3010
- email: string | null;
3011
- /** Whether the email is verified by the provider */
3012
- emailVerified: boolean;
3013
- /** User's display name */
3014
- name: string | null;
3015
- /** URL to the user's avatar/profile picture */
3016
- avatarUrl: string | null;
3017
- /** Raw profile data from the provider */
3018
- rawProfile: Record<string, unknown>;
3019
- }
3020
- /**
3021
- * State stored during the OAuth flow for CSRF protection.
3022
- */
3023
- interface OAuthState {
3024
- /** Random state parameter for CSRF protection */
3025
- state: string;
3026
- /** Provider ID */
3027
- provider: string;
3028
- /** Redirect URI used for this flow */
3029
- redirectUri: string;
3030
- /** When this state was created (ms since epoch) */
3031
- createdAt: number;
3032
- /** When this state expires (ms since epoch) */
3033
- expiresAt: number;
3034
- /** Optional: user-defined data to pass through the flow */
3035
- metadata?: Record<string, unknown>;
3295
+ interface SqliteDatabase {
3296
+ pragma(source: string): unknown;
3297
+ exec(source: string): void;
3298
+ prepare(source: string): {
3299
+ run(...params: unknown[]): {
3300
+ changes?: number;
3301
+ } | unknown;
3302
+ get(...params: unknown[]): unknown;
3303
+ all(...params: unknown[]): unknown[];
3304
+ };
3305
+ transaction<T>(fn: () => T): () => T;
3036
3306
  }
3037
- /**
3038
- * Store for OAuth state parameters.
3039
- */
3040
- interface OAuthStateStore {
3041
- /** Store a state parameter for later validation. */
3307
+ declare class SqliteOAuthStateStore implements OAuthStateStore {
3308
+ private readonly db;
3309
+ constructor(db: SqliteDatabase);
3042
3310
  store(state: OAuthState): Promise<void>;
3043
- /** Consume a state parameter (single-use). Returns null if not found or expired. */
3044
3311
  consume(stateValue: string): Promise<OAuthState | null>;
3045
- /** Clean up expired states. */
3046
3312
  cleanExpired(): Promise<number>;
3313
+ private ensureTables;
3047
3314
  }
3048
- /**
3049
- * A linked OAuth identity for a user.
3050
- * Users can have multiple linked identities (e.g., Google + GitHub).
3051
- */
3052
- interface LinkedIdentity {
3053
- /** Unique ID of this link */
3054
- id: string;
3055
- /** Kora user ID */
3056
- userId: string;
3057
- /** OAuth provider name */
3058
- provider: string;
3059
- /** Provider-specific user ID */
3060
- providerUserId: string;
3061
- /** Provider email (at time of linking) */
3062
- email: string | null;
3063
- /** When this identity was linked */
3064
- linkedAt: number;
3065
- }
3066
- declare class OAuthError extends KoraError {
3067
- constructor(message: string, code: string, context?: Record<string, unknown>);
3068
- }
3069
- declare class OAuthStateMismatchError extends OAuthError {
3070
- constructor();
3071
- }
3072
- declare class OAuthCodeExchangeError extends OAuthError {
3073
- constructor(details?: string);
3074
- }
3075
- declare class OAuthUserInfoError extends OAuthError {
3076
- constructor(details?: string);
3077
- }
3078
- declare class OAuthProviderNotFoundError extends OAuthError {
3079
- constructor(provider: string);
3315
+ declare class SqliteLinkedIdentityStore implements LinkedIdentityStore {
3316
+ private readonly db;
3317
+ constructor(db: SqliteDatabase);
3318
+ findByProvider(provider: string, providerUserId: string): Promise<LinkedIdentity | null>;
3319
+ findByUser(userId: string): Promise<LinkedIdentity[]>;
3320
+ create(params: {
3321
+ userId: string;
3322
+ provider: string;
3323
+ providerUserId: string;
3324
+ email: string | null;
3325
+ }): Promise<LinkedIdentity>;
3326
+ delete(userId: string, provider: string): Promise<void>;
3327
+ private ensureTables;
3080
3328
  }
3329
+ declare function createSqliteOAuthStateStore(options: {
3330
+ filename: string;
3331
+ }): Promise<SqliteOAuthStateStore>;
3332
+ declare function createSqliteLinkedIdentityStore(options: {
3333
+ filename: string;
3334
+ }): Promise<SqliteLinkedIdentityStore>;
3335
+ declare function createSqliteOAuthStores(options: {
3336
+ filename: string;
3337
+ }): Promise<{
3338
+ stateStore: SqliteOAuthStateStore;
3339
+ linkedIdentityStore: SqliteLinkedIdentityStore;
3340
+ }>;
3081
3341
 
3082
- /**
3083
- * In-memory OAuth state store for development.
3084
- * Use Redis or a database in production for multi-server deployments.
3085
- */
3086
- declare class InMemoryOAuthStateStore implements OAuthStateStore {
3087
- private readonly states;
3342
+ interface PostgresClient {
3343
+ begin<T>(fn: (sql: PostgresClient) => Promise<T>): Promise<T>;
3344
+ (template: TemplateStringsArray, ...args: unknown[]): Promise<Record<string, unknown>[]>;
3345
+ }
3346
+ declare class PostgresOAuthStateStore implements OAuthStateStore {
3347
+ private readonly sql;
3348
+ private readonly ready;
3349
+ constructor(sql: PostgresClient);
3088
3350
  store(state: OAuthState): Promise<void>;
3089
3351
  consume(stateValue: string): Promise<OAuthState | null>;
3090
3352
  cleanExpired(): Promise<number>;
3353
+ private ensureTables;
3091
3354
  }
3092
- /**
3093
- * Configuration for the OAuth manager.
3094
- */
3095
- interface OAuthManagerConfig {
3096
- /** Registered OAuth providers */
3097
- providers: OAuthProviderConfig[];
3098
- /** State store. Defaults to InMemoryOAuthStateStore. */
3099
- stateStore?: OAuthStateStore;
3100
- /** State TTL in milliseconds. Defaults to 10 minutes. */
3101
- stateTtlMs?: number;
3102
- /**
3103
- * Custom fetch function. Defaults to global fetch.
3104
- * Useful for testing or custom HTTP clients.
3105
- */
3106
- fetch?: typeof globalThis.fetch;
3107
- }
3108
- /**
3109
- * Manages the OAuth 2.0 authorization code flow.
3110
- *
3111
- * Supports any standard OAuth 2.0 / OpenID Connect provider.
3112
- * Pre-built configurations available for Google, GitHub, and Microsoft.
3113
- *
3114
- * @example
3115
- * ```typescript
3116
- * const oauth = new OAuthManager({
3117
- * providers: [
3118
- * googleProvider({ clientId: '...', clientSecret: '...', redirectUri: '...' }),
3119
- * githubProvider({ clientId: '...', clientSecret: '...', redirectUri: '...' }),
3120
- * ],
3121
- * })
3122
- *
3123
- * // Step 1: Generate authorization URL
3124
- * const { url, state } = await oauth.getAuthorizationUrl('google')
3125
- * // Redirect user to url...
3126
- *
3127
- * // Step 2: Handle callback
3128
- * const { tokens, userInfo } = await oauth.handleCallback('google', code, stateParam)
3129
- * ```
3130
- */
3131
- declare class OAuthManager {
3132
- private readonly providers;
3133
- private readonly stateStore;
3134
- private readonly stateTtlMs;
3135
- private readonly fetchFn;
3136
- constructor(config: OAuthManagerConfig);
3137
- /**
3138
- * Generate an authorization URL for the user to visit.
3139
- * Returns the URL and the state parameter for CSRF validation.
3140
- */
3141
- getAuthorizationUrl(providerId: string, metadata?: Record<string, unknown>): Promise<{
3142
- url: string;
3143
- state: string;
3144
- }>;
3145
- /**
3146
- * Handle the OAuth callback after the user authorizes.
3147
- * Validates the state parameter, exchanges the code for tokens,
3148
- * and fetches user info.
3149
- *
3150
- * @param providerId - The OAuth provider
3151
- * @param code - The authorization code from the callback
3152
- * @param state - The state parameter from the callback
3153
- * @returns Tokens and user info from the provider
3154
- */
3155
- handleCallback(providerId: string, code: string, state: string): Promise<{
3156
- tokens: OAuthTokens;
3157
- userInfo: OAuthUserInfo;
3158
- stateMetadata?: Record<string, unknown>;
3159
- }>;
3160
- /**
3161
- * Get a registered provider by ID.
3162
- */
3163
- getProvider(providerId: string): OAuthProviderConfig;
3164
- /**
3165
- * List all registered provider IDs.
3166
- */
3167
- getProviderIds(): string[];
3168
- private exchangeCodeForTokens;
3169
- private fetchUserInfo;
3170
- }
3171
- interface ProviderFactoryConfig {
3172
- clientId: string;
3173
- clientSecret: string;
3174
- redirectUri: string;
3175
- scopes?: string[];
3355
+ declare class PostgresLinkedIdentityStore implements LinkedIdentityStore {
3356
+ private readonly sql;
3357
+ private readonly ready;
3358
+ constructor(sql: PostgresClient);
3359
+ findByProvider(provider: string, providerUserId: string): Promise<LinkedIdentity | null>;
3360
+ findByUser(userId: string): Promise<LinkedIdentity[]>;
3361
+ create(params: {
3362
+ userId: string;
3363
+ provider: string;
3364
+ providerUserId: string;
3365
+ email: string | null;
3366
+ }): Promise<LinkedIdentity>;
3367
+ delete(userId: string, provider: string): Promise<void>;
3368
+ private ensureTables;
3176
3369
  }
3177
- /**
3178
- * Create a Google OAuth provider configuration.
3179
- */
3180
- declare function googleProvider(config: ProviderFactoryConfig): OAuthProviderConfig;
3181
- /**
3182
- * Create a GitHub OAuth provider configuration.
3183
- */
3184
- declare function githubProvider(config: ProviderFactoryConfig): OAuthProviderConfig;
3185
- /**
3186
- * Create a Microsoft OAuth provider configuration.
3187
- */
3188
- declare function microsoftProvider(config: ProviderFactoryConfig & {
3189
- tenantId?: string;
3190
- }): OAuthProviderConfig;
3370
+ declare function createPostgresOAuthStateStore(options: {
3371
+ connectionString: string;
3372
+ }): Promise<PostgresOAuthStateStore>;
3373
+ declare function createPostgresLinkedIdentityStore(options: {
3374
+ connectionString: string;
3375
+ }): Promise<PostgresLinkedIdentityStore>;
3376
+ declare function createPostgresOAuthStores(options: {
3377
+ connectionString: string;
3378
+ }): Promise<{
3379
+ stateStore: PostgresOAuthStateStore;
3380
+ linkedIdentityStore: PostgresLinkedIdentityStore;
3381
+ }>;
3191
3382
 
3192
3383
  /**
3193
3384
  * A user session with metadata.
@@ -3984,4 +4175,4 @@ declare class WebhookManager {
3984
4175
  */
3985
4176
  declare function verifyWebhookSignature(payload: string, signature: string, secret: string): Promise<boolean>;
3986
4177
 
3987
- export { AdminApi, type AdminApiConfig, AdminApiError, AdminUnauthorizedError, AdminUserNotFoundError, type AdminUserUpdate, type AuditAction, type AuditEntry, AuditLogError, type AuditLogQuery, type AuditLogStore, AuditLogger, type AuthDevice, type AuthProviderAdapter, AuthProviderError, type AuthRouteResponse, type AuthRoutesConfig, type AuthUser, type AuthenticationOptions, type AuthenticationVerificationResult, BUILT_IN_ROLES, BuiltInAuthRoutes, BuiltInProvider, CannotRemoveOwnerError, type ChallengeStore, CircularInheritanceError, type ClerkAdapterConfig, type CollectionScopeResolver, type CreateInvitationParams, type CreateOrgParams, type CreateSessionParams, DuplicateEmailError, type EmailVerificationConfig, EmailVerificationError, EmailVerificationManager, type EmailVerificationStore, type EmailVerificationToken, ExternalAuthOperationNotSupportedError, ExternalJwtProvider, type ExternalJwtProviderConfig, ExternalTokenValidationError, type ExternalUserInfo, INVITATION_STATUSES, InMemoryAuditLogStore, InMemoryChallengeStore, InMemoryEmailVerificationStore, InMemoryOAuthStateStore, InMemoryOrgStore, InMemoryPasswordResetStore, InMemoryRateLimiter, InMemorySessionStore, InMemoryTokenRevocationStore, InMemoryTotpStore, InMemoryUserStore, InMemoryWebhookStore, InsufficientRoleError, InvalidPermissionError, InvitationExpiredError, InvitationNotFoundError, type InvitationStatus, type LinkedIdentity, MemberAlreadyExistsError, type Membership, MembershipNotFoundError, OAuthCodeExchangeError, OAuthError, OAuthManager, type OAuthManagerConfig, type OAuthProviderConfig, OAuthProviderNotFoundError, type OAuthState, OAuthStateMismatchError, type OAuthStateStore, type OAuthTokens, type OAuthUserInfo, OAuthUserInfoError, ORG_ROLES, OrgError, type OrgInvitation, OrgNotFoundError, type OrgRole, type OrgRouteResponse, OrgRoutes, type OrgRoutesConfig, OrgScopeResolver, OrgSlugTakenError, type OrgStore, type Organization, type PaginatedResult, PasskeyVerificationError, type PasswordResetConfig, PasswordResetError, PasswordResetManager, type PasswordResetStore, type PasswordResetToken, type Permission, PostgresUserStore, ROLE_HIERARCHY, type RateLimiter, type RbacConfig, RbacEngine, RbacError, type RegistrationOptions, type RegistrationVerificationResult, ResetRateLimitedError, ResetTokenExpiredError, ResetTokenNotFoundError, type RoleDefinition, RoleNotFoundError, type ScopeContext, type ScopeFilter, type Session, SessionError, SessionExpiredError, SessionLimitExceededError, SessionManager, type SessionManagerConfig, SessionMfaRequiredError, SessionNotFoundError, type SessionStore, type SignInParams, type SignUpParams, SqliteUserStore, type StoredUser, type SupabaseAdapterConfig, type SyncScopes, TokenManager, type TokenManagerConfig, type TokenRevocationStore, TotpAlreadyEnabledError, type TotpConfig, TotpError, TotpInvalidCodeError, TotpManager, TotpNotEnabledError, TotpNotVerifiedError, TotpRecoveryExhaustedError, type TotpSecret, type TotpSetupResult, type TotpStore, type UpdateOrgParams, type UserListQuery, type UserStore, VerificationTokenExpiredError, VerificationTokenNotFoundError, type WebhookDelivery, type WebhookEndpoint, WebhookEndpointNotFoundError, WebhookError, type WebhookEvent, WebhookManager, type WebhookPayload, type WebhookStore, base32Decode, base32Encode, createClerkAdapter, createPostgresUserStore, createSqliteUserStore, createSupabaseAdapter, decodeJwt, defineRoles, encodeJwt, generateAuthenticationOptions, generateRegistrationOptions, githubProvider, googleProvider, hasRoleLevel, hashPassword, isExpired, microsoftProvider, parsePermission, permissionCovers, verifyAuthenticationResponse, verifyJwt, verifyPassword, verifyRegistrationResponse, verifyWebhookSignature };
4178
+ export { AdminApi, type AdminApiConfig, AdminApiError, AdminUnauthorizedError, AdminUserNotFoundError, type AdminUserUpdate, type AuditAction, type AuditEntry, AuditLogError, type AuditLogQuery, type AuditLogStore, AuditLogger, type AuthDevice, type AuthProviderAdapter, AuthProviderError, type AuthRouteResponse, type AuthRoutesConfig, type AuthUser, type AuthenticationOptions, type AuthenticationVerificationResult, BUILT_IN_ROLES, BuiltInAuthRoutes, BuiltInProvider, CannotRemoveOwnerError, type ChallengeStore, CircularInheritanceError, type ClerkAdapterConfig, type CollectionScopeResolver, type CreateInvitationParams, type CreateKoraAuthServerOptions, type CreateOrgParams, type CreateSessionParams, DuplicateEmailError, DuplicateLinkedIdentityError, type EmailVerificationConfig, EmailVerificationError, EmailVerificationManager, type EmailVerificationStore, type EmailVerificationToken, ExternalAuthOperationNotSupportedError, ExternalJwtProvider, type ExternalJwtProviderConfig, ExternalTokenValidationError, type ExternalUserInfo, INVITATION_STATUSES, InMemoryAuditLogStore, InMemoryChallengeStore, InMemoryEmailVerificationStore, InMemoryLinkedIdentityStore, InMemoryOAuthStateStore, InMemoryOrgStore, InMemoryPasswordResetStore, InMemoryRateLimiter, InMemorySessionStore, InMemoryTokenRevocationStore, InMemoryTotpStore, InMemoryUserStore, InMemoryWebhookStore, InsufficientRoleError, InvalidPermissionError, InvitationExpiredError, InvitationNotFoundError, type InvitationStatus, type KoraAuthHttpRequest, type KoraAuthServer, type LinkedIdentity, type LinkedIdentityStore, MemberAlreadyExistsError, type Membership, MembershipNotFoundError, OAuthCodeExchangeError, OAuthError, OAuthManager, type OAuthManagerConfig, type OAuthProviderConfig, OAuthProviderNotFoundError, type OAuthServerConfig, type OAuthState, OAuthStateMismatchError, type OAuthStateStore, type OAuthTokens, type OAuthUserInfo, OAuthUserInfoError, ORG_ROLES, OrgError, type OrgInvitation, OrgNotFoundError, type OrgRole, type OrgRouteResponse, OrgRoutes, type OrgRoutesConfig, OrgScopeResolver, OrgSlugTakenError, type OrgStore, type Organization, type PaginatedResult, PasskeyVerificationError, type PasswordResetConfig, PasswordResetError, PasswordResetManager, type PasswordResetStore, type PasswordResetToken, type Permission, PostgresLinkedIdentityStore, PostgresOAuthStateStore, PostgresUserStore, ROLE_HIERARCHY, type RateLimiter, type RbacConfig, RbacEngine, RbacError, type RegistrationOptions, type RegistrationVerificationResult, ResetRateLimitedError, ResetTokenExpiredError, ResetTokenNotFoundError, type RoleDefinition, RoleNotFoundError, type ScopeContext, type ScopeFilter, type Session, SessionError, SessionExpiredError, SessionLimitExceededError, SessionManager, type SessionManagerConfig, SessionMfaRequiredError, SessionNotFoundError, type SessionStore, type SignInParams, type SignUpParams, SqliteLinkedIdentityStore, SqliteOAuthStateStore, SqliteUserStore, type StoredUser, type SupabaseAdapterConfig, type SyncScopes, TokenManager, type TokenManagerConfig, type TokenRevocationStore, TotpAlreadyEnabledError, type TotpConfig, TotpError, TotpInvalidCodeError, TotpManager, TotpNotEnabledError, TotpNotVerifiedError, TotpRecoveryExhaustedError, type TotpSecret, type TotpSetupResult, type TotpStore, type UpdateOrgParams, type UserListQuery, type UserStore, VerificationTokenExpiredError, VerificationTokenNotFoundError, type WebhookDelivery, type WebhookEndpoint, WebhookEndpointNotFoundError, WebhookError, type WebhookEvent, WebhookManager, type WebhookPayload, type WebhookStore, base32Decode, base32Encode, createClerkAdapter, createKoraAuthServer, createPostgresLinkedIdentityStore, createPostgresOAuthStateStore, createPostgresOAuthStores, createPostgresUserStore, createSqliteLinkedIdentityStore, createSqliteOAuthStateStore, createSqliteOAuthStores, createSqliteUserStore, createSupabaseAdapter, decodeJwt, defineRoles, encodeJwt, generateAuthenticationOptions, generateRegistrationOptions, githubProvider, googleProvider, hasRoleLevel, hashPassword, isExpired, microsoftProvider, parsePermission, permissionCovers, verifyAuthenticationResponse, verifyJwt, verifyPassword, verifyRegistrationResponse, verifyWebhookSignature };