@korajs/auth 1.0.0-beta.12 → 1.0.0-beta.13
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/README.md +52 -47
- package/dist/{create-org-session-RsDj9cl4.d.cts → create-org-session-ChFdulEM.d.cts} +211 -17
- package/dist/{create-org-session-RsDj9cl4.d.ts → create-org-session-ChFdulEM.d.ts} +211 -17
- package/dist/index.cjs +645 -150
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -9
- package/dist/index.d.ts +27 -9
- package/dist/index.js +644 -150
- package/dist/index.js.map +1 -1
- package/dist/{operation-encryptor-DRmKNWpF.d.cts → operation-encryptor-DDdlb9bm.d.cts} +16 -0
- package/dist/{operation-encryptor-DRmKNWpF.d.ts → operation-encryptor-DDdlb9bm.d.ts} +16 -0
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/server.cjs +2852 -1675
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +779 -168
- package/dist/server.d.ts +779 -168
- package/dist/server.js +2831 -1665
- package/dist/server.js.map +1 -1
- package/dist/svelte.cjs +2 -2
- package/dist/svelte.cjs.map +1 -1
- package/dist/svelte.d.cts +2 -2
- package/dist/svelte.d.ts +2 -2
- package/dist/svelte.js +2 -2
- package/dist/svelte.js.map +1 -1
- package/dist/vue.d.cts +1 -1
- package/dist/vue.d.ts +1 -1
- package/package.json +7 -7
- package/src/admin/admin-api.ts +327 -0
- package/src/admin/audit-log.ts +324 -0
- package/src/admin/webhooks.ts +576 -0
- package/src/bindings/create-auth-session.ts +184 -0
- package/src/bindings/create-org-session.ts +130 -0
- package/src/client/auth-client.ts +1592 -0
- package/src/client/auth-sync.ts +213 -0
- package/src/client/device-session.ts +104 -0
- package/src/client/org-client.ts +399 -0
- package/src/client/quickstart.ts +108 -0
- package/src/client/storage.ts +94 -0
- package/src/device/device-identity.ts +330 -0
- package/src/device/device-store.ts +379 -0
- package/src/encryption/auto-lock.ts +170 -0
- package/src/encryption/database-encryption.ts +265 -0
- package/src/encryption/key-derivation.ts +149 -0
- package/src/encryption/operation-encryptor.ts +361 -0
- package/src/index.ts +132 -0
- package/src/mfa/totp.ts +826 -0
- package/src/org/org-routes.ts +758 -0
- package/src/org/org-store.ts +490 -0
- package/src/org/org-types.ts +230 -0
- package/src/passkey/passkey-client.ts +597 -0
- package/src/passkey/passkey-server.ts +779 -0
- package/src/postgres/ensure-schema.ts +65 -0
- package/src/provider/adapter.ts +246 -0
- package/src/provider/built-in/auth-routes.ts +1313 -0
- package/src/provider/built-in/email-verification.ts +303 -0
- package/src/provider/built-in/password-hash.ts +118 -0
- package/src/provider/built-in/password-reset.ts +416 -0
- package/src/provider/built-in/postgres-user-store.ts +328 -0
- package/src/provider/built-in/quickstart-server.ts +760 -0
- package/src/provider/built-in/sqlite-user-store.ts +322 -0
- package/src/provider/built-in/sync-scopes.ts +85 -0
- package/src/provider/built-in/user-store.ts +465 -0
- package/src/provider/external/clerk-adapter.ts +157 -0
- package/src/provider/external/external-jwt-provider.ts +491 -0
- package/src/provider/external/supabase-adapter.ts +163 -0
- package/src/provider/oauth/linked-identity-store.ts +108 -0
- package/src/provider/oauth/oauth-flow.ts +550 -0
- package/src/provider/oauth/oauth-types.ts +184 -0
- package/src/provider/oauth/postgres-oauth-store.ts +296 -0
- package/src/provider/oauth/sqlite-oauth-store.ts +272 -0
- package/src/rbac/rbac-engine.ts +323 -0
- package/src/rbac/rbac-types.ts +210 -0
- package/src/rbac/scope-resolver.ts +140 -0
- package/src/react/AuthProvider.tsx +97 -0
- package/src/react/OrgProvider.tsx +41 -0
- package/src/react/auth-context.ts +26 -0
- package/src/react/hooks.ts +110 -0
- package/src/react/org-hooks.ts +214 -0
- package/src/react.ts +26 -0
- package/src/server.ts +334 -0
- package/src/session/session.ts +401 -0
- package/src/svelte/auth-context.ts +50 -0
- package/src/svelte/org-context.ts +32 -0
- package/src/svelte/org-hooks.ts +201 -0
- package/src/svelte/use-auth.ts +115 -0
- package/src/svelte.ts +25 -0
- package/src/tokens/encrypted-token-store.ts +360 -0
- package/src/tokens/jwt.ts +236 -0
- package/src/tokens/postgres-token-revocation-store.ts +140 -0
- package/src/tokens/sqlite-token-revocation-store.ts +121 -0
- package/src/tokens/token-manager.ts +821 -0
- package/src/tokens/token-store.ts +192 -0
- package/src/types.ts +394 -0
- package/src/vue/auth-context.ts +10 -0
- package/src/vue/auth-provider-types.ts +5 -0
- package/src/vue/auth-provider.ts +76 -0
- package/src/vue/org-hooks.ts +193 -0
- package/src/vue/org-provider.ts +49 -0
- package/src/vue/use-auth.ts +139 -0
- package/src/vue.ts +10 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AuthClient,
|
|
3
|
+
AuthState,
|
|
4
|
+
AuthUser,
|
|
5
|
+
LinkedOAuthAccount,
|
|
6
|
+
OAuthAuthorizationOptions,
|
|
7
|
+
OAuthAuthorizationResult,
|
|
8
|
+
OAuthCallbackParams,
|
|
9
|
+
} from '../client/auth-client'
|
|
10
|
+
|
|
11
|
+
export interface AuthSessionSnapshot {
|
|
12
|
+
state: AuthState
|
|
13
|
+
user: AuthUser | null
|
|
14
|
+
isAuthenticated: boolean
|
|
15
|
+
isLoading: boolean
|
|
16
|
+
initError: Error | null
|
|
17
|
+
error: string | null
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface AuthSession {
|
|
21
|
+
readonly client: AuthClient
|
|
22
|
+
getSnapshot(): AuthSessionSnapshot
|
|
23
|
+
subscribe(listener: () => void): () => void
|
|
24
|
+
signUp(params: {
|
|
25
|
+
email: string
|
|
26
|
+
password: string
|
|
27
|
+
name?: string
|
|
28
|
+
deviceId?: string
|
|
29
|
+
devicePublicKey?: string
|
|
30
|
+
}): Promise<void>
|
|
31
|
+
signIn(params: {
|
|
32
|
+
email: string
|
|
33
|
+
password: string
|
|
34
|
+
deviceId?: string
|
|
35
|
+
devicePublicKey?: string
|
|
36
|
+
}): Promise<void>
|
|
37
|
+
signInWithOAuth(
|
|
38
|
+
provider: string,
|
|
39
|
+
options?: OAuthAuthorizationOptions,
|
|
40
|
+
): Promise<OAuthAuthorizationResult>
|
|
41
|
+
completeOAuthSignIn(provider: string, params: OAuthCallbackParams): Promise<void>
|
|
42
|
+
getOAuthAuthorizationUrl(
|
|
43
|
+
provider: string,
|
|
44
|
+
options?: OAuthAuthorizationOptions,
|
|
45
|
+
): Promise<OAuthAuthorizationResult>
|
|
46
|
+
linkOAuth(provider: string, params: OAuthCallbackParams): Promise<LinkedOAuthAccount | null>
|
|
47
|
+
listLinkedAccounts(): Promise<LinkedOAuthAccount[]>
|
|
48
|
+
unlinkOAuth(provider: string): Promise<void>
|
|
49
|
+
signOut(): Promise<void>
|
|
50
|
+
destroy(): void
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Framework-agnostic auth session: initialization, reactive snapshot, and client methods.
|
|
55
|
+
*/
|
|
56
|
+
export function createAuthSession(client: AuthClient): AuthSession {
|
|
57
|
+
let state: AuthState = client.state
|
|
58
|
+
let isLoading = true
|
|
59
|
+
let initError: Error | null = null
|
|
60
|
+
let lastError: string | null = null
|
|
61
|
+
|
|
62
|
+
const listeners = new Set<() => void>()
|
|
63
|
+
let snapshot = buildSnapshot()
|
|
64
|
+
|
|
65
|
+
const refreshSnapshot = (): void => {
|
|
66
|
+
snapshot = buildSnapshot()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const notify = (): void => {
|
|
70
|
+
refreshSnapshot()
|
|
71
|
+
for (const listener of listeners) {
|
|
72
|
+
listener()
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function buildSnapshot(): AuthSessionSnapshot {
|
|
77
|
+
return {
|
|
78
|
+
state,
|
|
79
|
+
user: client.currentUser,
|
|
80
|
+
isAuthenticated: state === 'authenticated',
|
|
81
|
+
isLoading,
|
|
82
|
+
initError,
|
|
83
|
+
error: lastError,
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const captureError = (error: unknown): void => {
|
|
88
|
+
lastError = error instanceof Error ? error.message : String(error)
|
|
89
|
+
notify()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const run = async (action: () => Promise<void>): Promise<void> => {
|
|
93
|
+
lastError = null
|
|
94
|
+
try {
|
|
95
|
+
await action()
|
|
96
|
+
} catch (error) {
|
|
97
|
+
captureError(error)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const runWithResult = async <T>(action: () => Promise<T>): Promise<T | null> => {
|
|
102
|
+
lastError = null
|
|
103
|
+
try {
|
|
104
|
+
return await action()
|
|
105
|
+
} catch (error) {
|
|
106
|
+
captureError(error)
|
|
107
|
+
return null
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const unsubscribeAuth = client.onAuthChange((nextState) => {
|
|
112
|
+
state = nextState
|
|
113
|
+
notify()
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
void client
|
|
117
|
+
.initialize()
|
|
118
|
+
.then(() => {
|
|
119
|
+
state = client.state
|
|
120
|
+
isLoading = false
|
|
121
|
+
notify()
|
|
122
|
+
})
|
|
123
|
+
.catch((error: unknown) => {
|
|
124
|
+
initError = error instanceof Error ? error : new Error(String(error))
|
|
125
|
+
isLoading = false
|
|
126
|
+
notify()
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
client,
|
|
131
|
+
getSnapshot: () => snapshot,
|
|
132
|
+
subscribe(listener) {
|
|
133
|
+
listeners.add(listener)
|
|
134
|
+
return () => {
|
|
135
|
+
listeners.delete(listener)
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
signUp: (params) =>
|
|
139
|
+
run(async () => {
|
|
140
|
+
await client.signUp(params)
|
|
141
|
+
}),
|
|
142
|
+
signIn: (params) =>
|
|
143
|
+
run(async () => {
|
|
144
|
+
await client.signIn(params)
|
|
145
|
+
}),
|
|
146
|
+
signInWithOAuth: async (provider, options) => {
|
|
147
|
+
lastError = null
|
|
148
|
+
try {
|
|
149
|
+
return await client.signInWithOAuth(provider, options)
|
|
150
|
+
} catch (error) {
|
|
151
|
+
captureError(error)
|
|
152
|
+
throw error instanceof Error ? error : new Error(String(error))
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
completeOAuthSignIn: (provider, params) =>
|
|
156
|
+
run(async () => {
|
|
157
|
+
await client.completeOAuthSignIn(provider, params)
|
|
158
|
+
}),
|
|
159
|
+
getOAuthAuthorizationUrl: async (provider, options) => {
|
|
160
|
+
lastError = null
|
|
161
|
+
try {
|
|
162
|
+
return await client.getOAuthAuthorizationUrl(provider, options)
|
|
163
|
+
} catch (error) {
|
|
164
|
+
captureError(error)
|
|
165
|
+
throw error instanceof Error ? error : new Error(String(error))
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
linkOAuth: (provider, params) => runWithResult(async () => client.linkOAuth(provider, params)),
|
|
169
|
+
listLinkedAccounts: () =>
|
|
170
|
+
runWithResult(async () => client.listLinkedAccounts()).then((value) => value ?? []),
|
|
171
|
+
unlinkOAuth: (provider) =>
|
|
172
|
+
run(async () => {
|
|
173
|
+
await client.unlinkOAuth(provider)
|
|
174
|
+
}),
|
|
175
|
+
signOut: () =>
|
|
176
|
+
run(async () => {
|
|
177
|
+
await client.signOut()
|
|
178
|
+
}),
|
|
179
|
+
destroy() {
|
|
180
|
+
unsubscribeAuth()
|
|
181
|
+
listeners.clear()
|
|
182
|
+
},
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ClientInvitation,
|
|
3
|
+
ClientMembership,
|
|
4
|
+
ClientOrganization,
|
|
5
|
+
OrgClient,
|
|
6
|
+
} from '../client/org-client'
|
|
7
|
+
|
|
8
|
+
export interface OrgSnapshot {
|
|
9
|
+
orgId: string | null
|
|
10
|
+
org: ClientOrganization | null
|
|
11
|
+
role: string | null
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface OrgSession {
|
|
15
|
+
readonly client: OrgClient
|
|
16
|
+
getSnapshot(): OrgSnapshot
|
|
17
|
+
subscribe(listener: () => void): () => void
|
|
18
|
+
checkPermission(requiredRole: string): boolean
|
|
19
|
+
destroy(): void
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const ROLE_LEVELS: Record<string, number> = {
|
|
23
|
+
viewer: 10,
|
|
24
|
+
billing: 15,
|
|
25
|
+
member: 20,
|
|
26
|
+
admin: 30,
|
|
27
|
+
owner: 40,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function checkOrgPermission(currentRole: string | null, requiredRole: string): boolean {
|
|
31
|
+
if (!currentRole) return false
|
|
32
|
+
const currentLevel = ROLE_LEVELS[currentRole] ?? 0
|
|
33
|
+
const requiredLevel = ROLE_LEVELS[requiredRole] ?? 0
|
|
34
|
+
return currentLevel >= requiredLevel
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Framework-agnostic org session with reactive snapshot subscription.
|
|
39
|
+
*/
|
|
40
|
+
export function createOrgSession(client: OrgClient): OrgSession {
|
|
41
|
+
let snapshot = buildSnapshot(client)
|
|
42
|
+
const listeners = new Set<() => void>()
|
|
43
|
+
|
|
44
|
+
const notify = (): void => {
|
|
45
|
+
snapshot = buildSnapshot(client)
|
|
46
|
+
for (const listener of listeners) {
|
|
47
|
+
listener()
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const unsubscribeOrgChange = client.onOrgChange(notify)
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
client,
|
|
55
|
+
getSnapshot: () => snapshot,
|
|
56
|
+
subscribe(listener: () => void): () => void {
|
|
57
|
+
listeners.add(listener)
|
|
58
|
+
return () => {
|
|
59
|
+
listeners.delete(listener)
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
checkPermission(requiredRole: string): boolean {
|
|
63
|
+
return checkOrgPermission(snapshot.role, requiredRole)
|
|
64
|
+
},
|
|
65
|
+
destroy(): void {
|
|
66
|
+
unsubscribeOrgChange()
|
|
67
|
+
listeners.clear()
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function buildSnapshot(client: OrgClient): OrgSnapshot {
|
|
73
|
+
return {
|
|
74
|
+
orgId: client.activeOrgId,
|
|
75
|
+
org: client.activeOrg,
|
|
76
|
+
role: client.activeRole,
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface UseOrgMembersActions {
|
|
81
|
+
refresh: () => Promise<void>
|
|
82
|
+
invite: (email: string, role: string) => Promise<ClientInvitation>
|
|
83
|
+
removeMember: (userId: string) => Promise<void>
|
|
84
|
+
updateRole: (userId: string, role: string) => Promise<void>
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Shared org member management actions (loading state remains framework-specific).
|
|
89
|
+
*/
|
|
90
|
+
export function createOrgMembersActions(
|
|
91
|
+
client: OrgClient,
|
|
92
|
+
orgId: string,
|
|
93
|
+
onError: (message: string) => void,
|
|
94
|
+
): UseOrgMembersActions {
|
|
95
|
+
return {
|
|
96
|
+
async refresh(): Promise<void> {
|
|
97
|
+
await client.listMembers(orgId)
|
|
98
|
+
},
|
|
99
|
+
async invite(email: string, role: string): Promise<ClientInvitation> {
|
|
100
|
+
try {
|
|
101
|
+
return await client.inviteMember(orgId, { email, role })
|
|
102
|
+
} catch (error) {
|
|
103
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
104
|
+
onError(message)
|
|
105
|
+
throw error
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
async removeMember(userId: string): Promise<void> {
|
|
109
|
+
try {
|
|
110
|
+
await client.removeMember(orgId, userId)
|
|
111
|
+
} catch (error) {
|
|
112
|
+
onError(error instanceof Error ? error.message : String(error))
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
async updateRole(userId: string, role: string): Promise<void> {
|
|
116
|
+
try {
|
|
117
|
+
await client.updateMemberRole(orgId, userId, role)
|
|
118
|
+
} catch (error) {
|
|
119
|
+
onError(error instanceof Error ? error.message : String(error))
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export async function loadOrgMembers(
|
|
126
|
+
client: OrgClient,
|
|
127
|
+
orgId: string,
|
|
128
|
+
): Promise<ClientMembership[]> {
|
|
129
|
+
return client.listMembers(orgId)
|
|
130
|
+
}
|