clearauth 0.3.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/CHANGELOG.md +235 -0
- package/LICENSE +21 -0
- package/README.md +417 -0
- package/dist/auth/handler.d.ts +38 -0
- package/dist/auth/handler.js +483 -0
- package/dist/auth/handler.js.map +1 -0
- package/dist/auth/login.d.ts +69 -0
- package/dist/auth/login.js +103 -0
- package/dist/auth/login.js.map +1 -0
- package/dist/auth/register.d.ts +72 -0
- package/dist/auth/register.js +122 -0
- package/dist/auth/register.js.map +1 -0
- package/dist/auth/reset-password.d.ts +106 -0
- package/dist/auth/reset-password.js +213 -0
- package/dist/auth/reset-password.js.map +1 -0
- package/dist/auth/utils.d.ts +58 -0
- package/dist/auth/utils.js +121 -0
- package/dist/auth/utils.js.map +1 -0
- package/dist/auth/verify-email.d.ts +70 -0
- package/dist/auth/verify-email.js +137 -0
- package/dist/auth/verify-email.js.map +1 -0
- package/dist/createMechAuth.d.ts +178 -0
- package/dist/createMechAuth.js +215 -0
- package/dist/createMechAuth.js.map +1 -0
- package/dist/database/schema.d.ts +135 -0
- package/dist/database/schema.js +37 -0
- package/dist/database/schema.js.map +1 -0
- package/dist/edge.d.ts +4 -0
- package/dist/edge.js +6 -0
- package/dist/edge.js.map +1 -0
- package/dist/errors.d.ts +25 -0
- package/dist/errors.js +44 -0
- package/dist/errors.js.map +1 -0
- package/dist/handler.d.ts +100 -0
- package/dist/handler.js +213 -0
- package/dist/handler.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +22 -0
- package/dist/logger.js +40 -0
- package/dist/logger.js.map +1 -0
- package/dist/mech-kysely.d.ts +22 -0
- package/dist/mech-kysely.js +88 -0
- package/dist/mech-kysely.js.map +1 -0
- package/dist/mech-sql-client.d.ts +85 -0
- package/dist/mech-sql-client.js +155 -0
- package/dist/mech-sql-client.js.map +1 -0
- package/dist/node.d.ts +4 -0
- package/dist/node.js +10 -0
- package/dist/node.js.map +1 -0
- package/dist/oauth/arctic-providers.d.ts +60 -0
- package/dist/oauth/arctic-providers.js +94 -0
- package/dist/oauth/arctic-providers.js.map +1 -0
- package/dist/oauth/callbacks.d.ts +155 -0
- package/dist/oauth/callbacks.js +286 -0
- package/dist/oauth/callbacks.js.map +1 -0
- package/dist/oauth/github.d.ts +47 -0
- package/dist/oauth/github.js +136 -0
- package/dist/oauth/github.js.map +1 -0
- package/dist/oauth/google.d.ts +49 -0
- package/dist/oauth/google.js +104 -0
- package/dist/oauth/google.js.map +1 -0
- package/dist/oauth/handler.d.ts +31 -0
- package/dist/oauth/handler.js +277 -0
- package/dist/oauth/handler.js.map +1 -0
- package/dist/password-hasher-argon2.d.ts +7 -0
- package/dist/password-hasher-argon2.js +16 -0
- package/dist/password-hasher-argon2.js.map +1 -0
- package/dist/password-hasher.d.ts +12 -0
- package/dist/password-hasher.js +115 -0
- package/dist/password-hasher.js.map +1 -0
- package/dist/react.d.ts +152 -0
- package/dist/react.js +296 -0
- package/dist/react.js.map +1 -0
- package/dist/types.d.ts +190 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/cors.d.ts +65 -0
- package/dist/utils/cors.js +152 -0
- package/dist/utils/cors.js.map +1 -0
- package/dist/utils/normalize-auth-path.d.ts +1 -0
- package/dist/utils/normalize-auth-path.js +8 -0
- package/dist/utils/normalize-auth-path.js.map +1 -0
- package/dist/validation.d.ts +23 -0
- package/dist/validation.js +70 -0
- package/dist/validation.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory function to create a complete ClearAuth configuration
|
|
3
|
+
*
|
|
4
|
+
* This module provides a convenient way to create a fully configured ClearAuthConfig
|
|
5
|
+
* with sensible defaults for session management, cookies, and security settings.
|
|
6
|
+
*
|
|
7
|
+
* @module createClearAuth
|
|
8
|
+
*/
|
|
9
|
+
import { createMechKysely } from "./mech-kysely.js";
|
|
10
|
+
import { ClearAuthConfigError } from "./errors.js";
|
|
11
|
+
import { getDefaultLogger } from "./logger.js";
|
|
12
|
+
import { createPbkdf2PasswordHasher } from "./password-hasher.js";
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Session & Cookie Presets
|
|
15
|
+
// ============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Default session configuration
|
|
18
|
+
* - 7 day expiration
|
|
19
|
+
* - Secure cookies in production
|
|
20
|
+
* - SameSite: lax
|
|
21
|
+
*/
|
|
22
|
+
export const defaultSessionConfig = {
|
|
23
|
+
expiresIn: 60 * 60 * 24 * 7, // 7 days
|
|
24
|
+
cookie: {
|
|
25
|
+
name: 'session',
|
|
26
|
+
httpOnly: true,
|
|
27
|
+
sameSite: 'lax',
|
|
28
|
+
path: '/',
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Short-lived session configuration (for high-security apps)
|
|
33
|
+
* - 1 hour expiration
|
|
34
|
+
* - Strict cookies
|
|
35
|
+
*/
|
|
36
|
+
export const shortSessionConfig = {
|
|
37
|
+
expiresIn: 60 * 60, // 1 hour
|
|
38
|
+
cookie: {
|
|
39
|
+
name: 'session',
|
|
40
|
+
httpOnly: true,
|
|
41
|
+
sameSite: 'strict',
|
|
42
|
+
path: '/',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Long-lived session configuration (for consumer apps)
|
|
47
|
+
* - 30 day expiration
|
|
48
|
+
* - Lax cookies for better UX
|
|
49
|
+
*/
|
|
50
|
+
export const longSessionConfig = {
|
|
51
|
+
expiresIn: 60 * 60 * 24 * 30, // 30 days
|
|
52
|
+
cookie: {
|
|
53
|
+
name: 'session',
|
|
54
|
+
httpOnly: true,
|
|
55
|
+
sameSite: 'lax',
|
|
56
|
+
path: '/',
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Helper to check if database config is the simplified format
|
|
61
|
+
*/
|
|
62
|
+
function isSimpleDatabaseConfig(db) {
|
|
63
|
+
return db !== null && typeof db === 'object' && 'appId' in db && 'apiKey' in db;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create a complete ClearAuth configuration
|
|
67
|
+
*
|
|
68
|
+
* All configuration must be provided explicitly - no environment variables are read.
|
|
69
|
+
*
|
|
70
|
+
* Configuration formats:
|
|
71
|
+
*
|
|
72
|
+
* 1. **Simplified config (recommended)**:
|
|
73
|
+
* ```ts
|
|
74
|
+
* const config = createClearAuth({
|
|
75
|
+
* secret: "your-secret-key",
|
|
76
|
+
* baseUrl: "https://yourdomain.com",
|
|
77
|
+
* database: { appId: "...", apiKey: "..." },
|
|
78
|
+
* isProduction: true,
|
|
79
|
+
* oauth: {
|
|
80
|
+
* github: {
|
|
81
|
+
* clientId: env.GITHUB_CLIENT_ID,
|
|
82
|
+
* clientSecret: env.GITHUB_CLIENT_SECRET,
|
|
83
|
+
* redirectUri: 'https://yourdomain.com/auth/callback/github',
|
|
84
|
+
* },
|
|
85
|
+
* },
|
|
86
|
+
* })
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* 2. **With session presets**:
|
|
90
|
+
* ```ts
|
|
91
|
+
* const config = createClearAuth({
|
|
92
|
+
* secret: "your-secret-key",
|
|
93
|
+
* baseUrl: "https://yourdomain.com",
|
|
94
|
+
* database: { appId: "...", apiKey: "..." },
|
|
95
|
+
* session: longSessionConfig, // Use 30-day sessions
|
|
96
|
+
* })
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* @param options - Configuration options
|
|
100
|
+
* @returns A configured ClearAuthConfig object
|
|
101
|
+
* @throws ClearAuthConfigError if required config is missing or invalid
|
|
102
|
+
*
|
|
103
|
+
* @example Cloudflare Workers setup
|
|
104
|
+
* ```ts
|
|
105
|
+
* import { createClearAuth, defaultSessionConfig } from 'clearauth'
|
|
106
|
+
*
|
|
107
|
+
* const config = createClearAuth({
|
|
108
|
+
* secret: env.AUTH_SECRET,
|
|
109
|
+
* baseUrl: 'https://yourdomain.com',
|
|
110
|
+
* database: {
|
|
111
|
+
* appId: env.MECH_APP_ID,
|
|
112
|
+
* apiKey: env.MECH_API_KEY,
|
|
113
|
+
* },
|
|
114
|
+
* isProduction: true,
|
|
115
|
+
* session: defaultSessionConfig,
|
|
116
|
+
* oauth: {
|
|
117
|
+
* github: {
|
|
118
|
+
* clientId: env.GITHUB_CLIENT_ID,
|
|
119
|
+
* clientSecret: env.GITHUB_CLIENT_SECRET,
|
|
120
|
+
* redirectUri: 'https://yourdomain.com/auth/callback/github',
|
|
121
|
+
* },
|
|
122
|
+
* },
|
|
123
|
+
* })
|
|
124
|
+
* ```
|
|
125
|
+
*
|
|
126
|
+
* @example Next.js setup
|
|
127
|
+
* ```ts
|
|
128
|
+
* import { createClearAuth } from 'clearauth'
|
|
129
|
+
*
|
|
130
|
+
* export const authConfig = createClearAuth({
|
|
131
|
+
* secret: process.env.AUTH_SECRET!,
|
|
132
|
+
* baseUrl: process.env.NEXT_PUBLIC_BASE_URL!,
|
|
133
|
+
* database: {
|
|
134
|
+
* appId: process.env.MECH_APP_ID!,
|
|
135
|
+
* apiKey: process.env.MECH_API_KEY!,
|
|
136
|
+
* },
|
|
137
|
+
* oauth: {
|
|
138
|
+
* github: {
|
|
139
|
+
* clientId: process.env.GITHUB_CLIENT_ID!,
|
|
140
|
+
* clientSecret: process.env.GITHUB_CLIENT_SECRET!,
|
|
141
|
+
* redirectUri: `${process.env.NEXT_PUBLIC_BASE_URL}/auth/callback/github`,
|
|
142
|
+
* },
|
|
143
|
+
* },
|
|
144
|
+
* })
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
export function createClearAuth(options) {
|
|
148
|
+
const logger = getDefaultLogger();
|
|
149
|
+
// Validate required fields
|
|
150
|
+
if (!options.secret) {
|
|
151
|
+
throw new ClearAuthConfigError("secret is required", { isProduction: options.isProduction });
|
|
152
|
+
}
|
|
153
|
+
if (!options.baseUrl) {
|
|
154
|
+
throw new ClearAuthConfigError("baseUrl is required", { isProduction: options.isProduction });
|
|
155
|
+
}
|
|
156
|
+
// Warn about development defaults
|
|
157
|
+
if (options.secret === "better-auth-secret-123456789" || options.secret === "dev-secret-key") {
|
|
158
|
+
if (options.isProduction) {
|
|
159
|
+
throw new ClearAuthConfigError("Cannot use default secret in production", { isProduction: options.isProduction });
|
|
160
|
+
}
|
|
161
|
+
logger.warn("Using default secret. This is only safe in development.");
|
|
162
|
+
}
|
|
163
|
+
// Determine database config format
|
|
164
|
+
let kyselyConfig;
|
|
165
|
+
if (isSimpleDatabaseConfig(options.database)) {
|
|
166
|
+
// Simplified format: { appId, apiKey, ... }
|
|
167
|
+
logger.debug("Creating auth config with simplified database config");
|
|
168
|
+
kyselyConfig = {
|
|
169
|
+
appId: options.database.appId,
|
|
170
|
+
apiKey: options.database.apiKey,
|
|
171
|
+
baseUrl: options.database.baseUrl,
|
|
172
|
+
appSchemaId: options.database.appSchemaId,
|
|
173
|
+
timeout: options.database.timeout,
|
|
174
|
+
maxRetries: options.database.maxRetries,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
else if ('config' in options.database) {
|
|
178
|
+
// Full config format: { config: MechKyselyConfig }
|
|
179
|
+
logger.debug("Creating auth config with full database config");
|
|
180
|
+
kyselyConfig = options.database.config;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
throw new ClearAuthConfigError("Invalid database configuration format", {
|
|
184
|
+
database: options.database
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
logger.debug("Creating Kysely instance...");
|
|
189
|
+
const db = createMechKysely(kyselyConfig);
|
|
190
|
+
logger.debug("Kysely created successfully");
|
|
191
|
+
// Build final config
|
|
192
|
+
const config = {
|
|
193
|
+
database: db,
|
|
194
|
+
secret: options.secret,
|
|
195
|
+
baseUrl: options.baseUrl,
|
|
196
|
+
isProduction: options.isProduction ?? false,
|
|
197
|
+
session: options.session ?? defaultSessionConfig,
|
|
198
|
+
oauth: options.oauth,
|
|
199
|
+
password: options.password ?? {
|
|
200
|
+
minLength: 8,
|
|
201
|
+
},
|
|
202
|
+
passwordHasher: options.passwordHasher ?? createPbkdf2PasswordHasher(),
|
|
203
|
+
};
|
|
204
|
+
return config;
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
if (err instanceof ClearAuthConfigError) {
|
|
208
|
+
throw err;
|
|
209
|
+
}
|
|
210
|
+
throw new ClearAuthConfigError(`Failed to create ClearAuth config: ${err.message}`, {
|
|
211
|
+
originalError: err.message
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=createMechAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createMechAuth.js","sourceRoot":"","sources":["../src/createMechAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Schema Types
|
|
3
|
+
*
|
|
4
|
+
* TypeScript interfaces and Kysely types for the mech-auth database schema.
|
|
5
|
+
* These types must match the SQL schema defined in the migration files.
|
|
6
|
+
*
|
|
7
|
+
* @see /migrations/001_create_users_table.sql
|
|
8
|
+
* @see /migrations/002_create_sessions_table.sql
|
|
9
|
+
* @see /migrations/003_create_verification_tokens.sql
|
|
10
|
+
* @see /migrations/004_create_reset_tokens.sql
|
|
11
|
+
*/
|
|
12
|
+
import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
|
|
13
|
+
/**
|
|
14
|
+
* Users Table
|
|
15
|
+
*
|
|
16
|
+
* Core users table with support for email/password and OAuth authentication.
|
|
17
|
+
*/
|
|
18
|
+
export interface UsersTable {
|
|
19
|
+
id: ColumnType<string, string | undefined, never>;
|
|
20
|
+
email: string;
|
|
21
|
+
email_verified: ColumnType<boolean, boolean | undefined, boolean>;
|
|
22
|
+
password_hash: string | null;
|
|
23
|
+
github_id: string | null;
|
|
24
|
+
google_id: string | null;
|
|
25
|
+
name: string | null;
|
|
26
|
+
avatar_url: string | null;
|
|
27
|
+
created_at: ColumnType<Date, Date | undefined, never>;
|
|
28
|
+
updated_at: ColumnType<Date, Date | undefined, Date>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Sessions Table
|
|
32
|
+
*
|
|
33
|
+
* Session management with expiration tracking.
|
|
34
|
+
* Session IDs are generated by the application using Oslo.
|
|
35
|
+
*/
|
|
36
|
+
export interface SessionsTable {
|
|
37
|
+
id: string;
|
|
38
|
+
user_id: string;
|
|
39
|
+
expires_at: Date;
|
|
40
|
+
ip_address: string | null;
|
|
41
|
+
user_agent: string | null;
|
|
42
|
+
created_at: ColumnType<Date, Date | undefined, never>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Email Verification Tokens Table
|
|
46
|
+
*
|
|
47
|
+
* Tokens for email verification flow.
|
|
48
|
+
* Typically expire after 24 hours.
|
|
49
|
+
*/
|
|
50
|
+
export interface EmailVerificationTokensTable {
|
|
51
|
+
token: string;
|
|
52
|
+
user_id: string;
|
|
53
|
+
email: string;
|
|
54
|
+
expires_at: Date;
|
|
55
|
+
created_at: ColumnType<Date, Date | undefined, never>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Password Reset Tokens Table
|
|
59
|
+
*
|
|
60
|
+
* Tokens for password reset flow.
|
|
61
|
+
* Typically expire after 1 hour for security.
|
|
62
|
+
*/
|
|
63
|
+
export interface PasswordResetTokensTable {
|
|
64
|
+
token: string;
|
|
65
|
+
user_id: string;
|
|
66
|
+
expires_at: Date;
|
|
67
|
+
created_at: ColumnType<Date, Date | undefined, never>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Database Schema
|
|
71
|
+
*
|
|
72
|
+
* Complete database schema for Kysely type-safe queries.
|
|
73
|
+
*/
|
|
74
|
+
export interface Database {
|
|
75
|
+
users: UsersTable;
|
|
76
|
+
sessions: SessionsTable;
|
|
77
|
+
email_verification_tokens: EmailVerificationTokensTable;
|
|
78
|
+
password_reset_tokens: PasswordResetTokensTable;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Type-safe row types for SELECT queries
|
|
82
|
+
*/
|
|
83
|
+
export type User = Selectable<UsersTable>;
|
|
84
|
+
export type Session = Selectable<SessionsTable>;
|
|
85
|
+
export type EmailVerificationToken = Selectable<EmailVerificationTokensTable>;
|
|
86
|
+
export type PasswordResetToken = Selectable<PasswordResetTokensTable>;
|
|
87
|
+
/**
|
|
88
|
+
* Type-safe input types for INSERT queries
|
|
89
|
+
*/
|
|
90
|
+
export type NewUser = Insertable<UsersTable>;
|
|
91
|
+
export type NewSession = Insertable<SessionsTable>;
|
|
92
|
+
export type NewEmailVerificationToken = Insertable<EmailVerificationTokensTable>;
|
|
93
|
+
export type NewPasswordResetToken = Insertable<PasswordResetTokensTable>;
|
|
94
|
+
/**
|
|
95
|
+
* Type-safe input types for UPDATE queries
|
|
96
|
+
*/
|
|
97
|
+
export type UserUpdate = Updateable<UsersTable>;
|
|
98
|
+
export type SessionUpdate = Updateable<SessionsTable>;
|
|
99
|
+
export type EmailVerificationTokenUpdate = Updateable<EmailVerificationTokensTable>;
|
|
100
|
+
export type PasswordResetTokenUpdate = Updateable<PasswordResetTokensTable>;
|
|
101
|
+
/**
|
|
102
|
+
* User with session information (common join result)
|
|
103
|
+
*/
|
|
104
|
+
export interface UserWithSession {
|
|
105
|
+
user: User;
|
|
106
|
+
session: Session;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Public user profile (safe to expose to client)
|
|
110
|
+
*/
|
|
111
|
+
export interface PublicUser {
|
|
112
|
+
id: string;
|
|
113
|
+
email: string;
|
|
114
|
+
email_verified: boolean;
|
|
115
|
+
name: string | null;
|
|
116
|
+
avatar_url: string | null;
|
|
117
|
+
created_at: Date;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Session with user information (common join result)
|
|
121
|
+
*/
|
|
122
|
+
export interface SessionWithUser {
|
|
123
|
+
session: Session;
|
|
124
|
+
user: PublicUser;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Helper function to convert User to PublicUser
|
|
128
|
+
*/
|
|
129
|
+
export declare function toPublicUser(user: User): PublicUser;
|
|
130
|
+
/**
|
|
131
|
+
* Type guards
|
|
132
|
+
*/
|
|
133
|
+
export declare function isValidSession(session: Session): boolean;
|
|
134
|
+
export declare function isValidEmailVerificationToken(token: EmailVerificationToken): boolean;
|
|
135
|
+
export declare function isValidPasswordResetToken(token: PasswordResetToken): boolean;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Schema Types
|
|
3
|
+
*
|
|
4
|
+
* TypeScript interfaces and Kysely types for the mech-auth database schema.
|
|
5
|
+
* These types must match the SQL schema defined in the migration files.
|
|
6
|
+
*
|
|
7
|
+
* @see /migrations/001_create_users_table.sql
|
|
8
|
+
* @see /migrations/002_create_sessions_table.sql
|
|
9
|
+
* @see /migrations/003_create_verification_tokens.sql
|
|
10
|
+
* @see /migrations/004_create_reset_tokens.sql
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Helper function to convert User to PublicUser
|
|
14
|
+
*/
|
|
15
|
+
export function toPublicUser(user) {
|
|
16
|
+
return {
|
|
17
|
+
id: user.id,
|
|
18
|
+
email: user.email,
|
|
19
|
+
email_verified: user.email_verified,
|
|
20
|
+
name: user.name,
|
|
21
|
+
avatar_url: user.avatar_url,
|
|
22
|
+
created_at: user.created_at,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Type guards
|
|
27
|
+
*/
|
|
28
|
+
export function isValidSession(session) {
|
|
29
|
+
return new Date(session.expires_at) > new Date();
|
|
30
|
+
}
|
|
31
|
+
export function isValidEmailVerificationToken(token) {
|
|
32
|
+
return new Date(token.expires_at) > new Date();
|
|
33
|
+
}
|
|
34
|
+
export function isValidPasswordResetToken(token) {
|
|
35
|
+
return new Date(token.expires_at) > new Date();
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/database/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAsIH;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,UAAU,EAAE,IAAI,CAAC,UAAU;KAC5B,CAAA;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,IAAI,EAAE,CAAA;AAClD,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,KAA6B;IACzE,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI,IAAI,EAAE,CAAA;AAChD,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAyB;IACjE,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI,IAAI,EAAE,CAAA;AAChD,CAAC"}
|
package/dist/edge.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ClearAuthConfig } from "./types.js";
|
|
2
|
+
export { createClearAuth, defaultSessionConfig, longSessionConfig, shortSessionConfig, } from "./createMechAuth.js";
|
|
3
|
+
export type { CorsConfig, ClearAuthConfig, OAuthProviderConfig, OAuthProvidersConfig, SessionConfig } from "./types.js";
|
|
4
|
+
export declare function handleClearAuthEdgeRequest(request: Request, config: ClearAuthConfig): Promise<Response>;
|
package/dist/edge.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { handleClearAuthRequest } from "./handler.js";
|
|
2
|
+
export { createClearAuth, defaultSessionConfig, longSessionConfig, shortSessionConfig, } from "./createMechAuth.js";
|
|
3
|
+
export async function handleClearAuthEdgeRequest(request, config) {
|
|
4
|
+
return await handleClearAuthRequest(request, config);
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=edge.js.map
|
package/dist/edge.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edge.js","sourceRoot":"","sources":["../src/edge.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAErD,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,qBAAqB,CAAA;AAG5B,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,OAAgB,EAAE,MAAuB;IACxF,OAAO,MAAM,sBAAsB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;AACtD,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error types for ClearAuth
|
|
3
|
+
*/
|
|
4
|
+
export declare class ClearAuthError extends Error {
|
|
5
|
+
readonly code: string;
|
|
6
|
+
readonly details?: Record<string, any> | undefined;
|
|
7
|
+
constructor(message: string, code: string, details?: Record<string, any> | undefined);
|
|
8
|
+
}
|
|
9
|
+
export declare class ClearAuthSqlError extends ClearAuthError {
|
|
10
|
+
constructor(message: string, details?: Record<string, any>);
|
|
11
|
+
}
|
|
12
|
+
export declare class ClearAuthConfigError extends ClearAuthError {
|
|
13
|
+
constructor(message: string, details?: Record<string, any>);
|
|
14
|
+
}
|
|
15
|
+
export declare class ClearAuthNetworkError extends ClearAuthError {
|
|
16
|
+
readonly statusCode?: number | undefined;
|
|
17
|
+
constructor(message: string, statusCode?: number | undefined, details?: Record<string, any>);
|
|
18
|
+
}
|
|
19
|
+
export declare class ClearAuthTimeoutError extends ClearAuthError {
|
|
20
|
+
constructor(message: string, details?: Record<string, any>);
|
|
21
|
+
}
|
|
22
|
+
export declare class ClearAuthRateLimitError extends ClearAuthError {
|
|
23
|
+
readonly retryAfter: number;
|
|
24
|
+
constructor(retryAfter: number, details?: Record<string, any>);
|
|
25
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error types for ClearAuth
|
|
3
|
+
*/
|
|
4
|
+
export class ClearAuthError extends Error {
|
|
5
|
+
constructor(message, code, details) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.details = details;
|
|
9
|
+
this.name = "ClearAuthError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class ClearAuthSqlError extends ClearAuthError {
|
|
13
|
+
constructor(message, details) {
|
|
14
|
+
super(message, "CLEARAUTH_SQL_ERROR", details);
|
|
15
|
+
this.name = "ClearAuthSqlError";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export class ClearAuthConfigError extends ClearAuthError {
|
|
19
|
+
constructor(message, details) {
|
|
20
|
+
super(message, "CLEARAUTH_CONFIG_ERROR", details);
|
|
21
|
+
this.name = "ClearAuthConfigError";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export class ClearAuthNetworkError extends ClearAuthError {
|
|
25
|
+
constructor(message, statusCode, details) {
|
|
26
|
+
super(message, "CLEARAUTH_NETWORK_ERROR", details);
|
|
27
|
+
this.statusCode = statusCode;
|
|
28
|
+
this.name = "ClearAuthNetworkError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export class ClearAuthTimeoutError extends ClearAuthError {
|
|
32
|
+
constructor(message, details) {
|
|
33
|
+
super(message, "CLEARAUTH_TIMEOUT_ERROR", details);
|
|
34
|
+
this.name = "ClearAuthTimeoutError";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export class ClearAuthRateLimitError extends ClearAuthError {
|
|
38
|
+
constructor(retryAfter, details) {
|
|
39
|
+
super(`Rate limit exceeded. Retry after ${retryAfter}ms`, "CLEARAUTH_RATE_LIMIT_ERROR", details);
|
|
40
|
+
this.retryAfter = retryAfter;
|
|
41
|
+
this.name = "ClearAuthRateLimitError";
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe,EAAkB,IAAY,EAAkB,OAA6B;QACtG,KAAK,CAAC,OAAO,CAAC,CAAA;QAD6B,SAAI,GAAJ,IAAI,CAAQ;QAAkB,YAAO,GAAP,OAAO,CAAsB;QAEtG,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAA;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,cAAc;IACnD,YAAY,OAAe,EAAE,OAA6B;QACxD,KAAK,CAAC,OAAO,EAAE,qBAAqB,EAAE,OAAO,CAAC,CAAA;QAC9C,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAA;IACjC,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,cAAc;IACtD,YAAY,OAAe,EAAE,OAA6B;QACxD,KAAK,CAAC,OAAO,EAAE,wBAAwB,EAAE,OAAO,CAAC,CAAA;QACjD,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAA;IACpC,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,cAAc;IACvD,YAAY,OAAe,EAAkB,UAAmB,EAAE,OAA6B;QAC7F,KAAK,CAAC,OAAO,EAAE,yBAAyB,EAAE,OAAO,CAAC,CAAA;QADP,eAAU,GAAV,UAAU,CAAS;QAE9D,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAA;IACrC,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,cAAc;IACvD,YAAY,OAAe,EAAE,OAA6B;QACxD,KAAK,CAAC,OAAO,EAAE,yBAAyB,EAAE,OAAO,CAAC,CAAA;QAClD,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAA;IACrC,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,cAAc;IACzD,YAA4B,UAAkB,EAAE,OAA6B;QAC3E,KAAK,CAAC,oCAAoC,UAAU,IAAI,EAAE,4BAA4B,EAAE,OAAO,CAAC,CAAA;QADtE,eAAU,GAAV,UAAU,CAAQ;QAE5C,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAA;IACvC,CAAC;CACF"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified HTTP request handler for ClearAuth
|
|
3
|
+
*
|
|
4
|
+
* This module provides a single entry point for handling all authentication requests,
|
|
5
|
+
* automatically routing to the appropriate handler (OAuth or email/password).
|
|
6
|
+
*
|
|
7
|
+
* @module handler
|
|
8
|
+
*/
|
|
9
|
+
import type { ClearAuthConfig } from './types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Unified authentication request handler
|
|
12
|
+
*
|
|
13
|
+
* Automatically routes requests to the appropriate handler based on the URL path:
|
|
14
|
+
* - OAuth routes: `/auth/oauth/*`, `/auth/github/*`, `/auth/google/*`, `/auth/callback/*`
|
|
15
|
+
* - Email/password routes: All other `/auth/*` routes
|
|
16
|
+
*
|
|
17
|
+
* @param request - The HTTP request to handle
|
|
18
|
+
* @param config - ClearAuth configuration
|
|
19
|
+
* @returns HTTP response
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* // Cloudflare Workers
|
|
24
|
+
* export default {
|
|
25
|
+
* async fetch(request: Request, env: Env): Promise<Response> {
|
|
26
|
+
* const config: ClearAuthConfig = {
|
|
27
|
+
* database: createMechKysely({ appId: env.MECH_APP_ID, apiKey: env.MECH_API_KEY }),
|
|
28
|
+
* secret: env.AUTH_SECRET,
|
|
29
|
+
* baseUrl: 'https://yourdomain.com',
|
|
30
|
+
* oauth: {
|
|
31
|
+
* github: {
|
|
32
|
+
* clientId: env.GITHUB_CLIENT_ID,
|
|
33
|
+
* clientSecret: env.GITHUB_CLIENT_SECRET,
|
|
34
|
+
* redirectUri: 'https://yourdomain.com/auth/callback/github',
|
|
35
|
+
* },
|
|
36
|
+
* },
|
|
37
|
+
* }
|
|
38
|
+
* return handleClearAuthRequest(request, config)
|
|
39
|
+
* },
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* // Next.js API route
|
|
46
|
+
* import { handleClearAuthRequest } from 'clearauth'
|
|
47
|
+
* import { config } from '@/lib/auth-config'
|
|
48
|
+
*
|
|
49
|
+
* export async function GET(request: Request) {
|
|
50
|
+
* return handleClearAuthRequest(request, config)
|
|
51
|
+
* }
|
|
52
|
+
*
|
|
53
|
+
* export async function POST(request: Request) {
|
|
54
|
+
* return handleClearAuthRequest(request, config)
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function handleClearAuthRequest(request: Request, config: ClearAuthConfig): Promise<Response>;
|
|
59
|
+
/**
|
|
60
|
+
* Get a list of all supported routes
|
|
61
|
+
*
|
|
62
|
+
* Useful for debugging and documentation purposes.
|
|
63
|
+
*
|
|
64
|
+
* @returns Object containing OAuth and auth routes
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* const routes = getSupportedRoutes()
|
|
69
|
+
* console.log('OAuth routes:', routes.oauth)
|
|
70
|
+
* console.log('Auth routes:', routes.auth)
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export declare function getSupportedRoutes(): {
|
|
74
|
+
oauth: {
|
|
75
|
+
method: string;
|
|
76
|
+
path: string;
|
|
77
|
+
description: string;
|
|
78
|
+
}[];
|
|
79
|
+
auth: {
|
|
80
|
+
method: string;
|
|
81
|
+
path: string;
|
|
82
|
+
description: string;
|
|
83
|
+
}[];
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Health check endpoint
|
|
87
|
+
*
|
|
88
|
+
* Returns a simple health check response to verify the auth service is running.
|
|
89
|
+
*
|
|
90
|
+
* @returns HTTP response with health status
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* // In your handler
|
|
95
|
+
* if (url.pathname === '/auth/health') {
|
|
96
|
+
* return healthCheck()
|
|
97
|
+
* }
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export declare function healthCheck(): Response;
|