@authrim/sveltekit 0.1.3 → 0.1.4

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.
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Smart Handoff SSO Handler for SvelteKit
3
+ *
4
+ * Handles handoff token verification and session management for cross-domain SSO
5
+ * in SvelteKit server-side code.
6
+ */
7
+ import type { Handle, RequestEvent } from '@sveltejs/kit';
8
+ import type { Session, User } from '@authrim/core';
9
+ import { type ServerSessionManagerOptions } from './session.js';
10
+ /**
11
+ * Handoff verification options
12
+ */
13
+ export interface HandoffVerifyOptions {
14
+ /**
15
+ * Authrim IdP URL (required if not using createAuthHandle)
16
+ */
17
+ issuer?: string;
18
+ /**
19
+ * OAuth client ID (required if not using createAuthHandle)
20
+ */
21
+ clientId?: string;
22
+ /**
23
+ * Handoff verify endpoint
24
+ * @default '/auth/external/handoff/verify'
25
+ */
26
+ verifyEndpoint?: string;
27
+ /**
28
+ * Error redirect path
29
+ * @default '/login'
30
+ */
31
+ errorRedirect?: string;
32
+ /**
33
+ * Session manager options
34
+ */
35
+ sessionOptions?: ServerSessionManagerOptions;
36
+ }
37
+ /**
38
+ * Verify handoff token from callback URL
39
+ *
40
+ * Usage in +page.server.ts:
41
+ * ```typescript
42
+ * export const load = async (event) => {
43
+ * const result = await verifyHandoffToken(event);
44
+ * if (!result.success) {
45
+ * throw redirect(302, '/login');
46
+ * }
47
+ * return { session: result.session, user: result.user };
48
+ * };
49
+ * ```
50
+ */
51
+ export declare function verifyHandoffToken(event: RequestEvent, options?: HandoffVerifyOptions): Promise<{
52
+ success: true;
53
+ session: Session;
54
+ user: User;
55
+ } | {
56
+ success: false;
57
+ error: string;
58
+ }>;
59
+ /**
60
+ * Create handoff handler for SvelteKit hooks
61
+ *
62
+ * Usage in hooks.server.ts:
63
+ * ```typescript
64
+ * import { sequence } from '@sveltejs/kit/hooks';
65
+ * import { createAuthHandle, createHandoffHandler } from '@authrim/sveltekit/server';
66
+ *
67
+ * export const handle = sequence(
68
+ * createAuthHandle({
69
+ * issuer: env.AUTHRIM_ISSUER,
70
+ * clientId: env.AUTHRIM_CLIENT_ID,
71
+ * }),
72
+ * createHandoffHandler()
73
+ * );
74
+ * ```
75
+ */
76
+ export declare function createHandoffHandler(options?: HandoffVerifyOptions): Handle;
77
+ //# sourceMappingURL=handoff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handoff.d.ts","sourceRoot":"","sources":["../../src/lib/server/handoff.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE1D,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAGL,KAAK,2BAA2B,EACjC,MAAM,cAAc,CAAC;AAEtB;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,cAAc,CAAC,EAAE,2BAA2B,CAAC;CAC9C;AAmDD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,YAAY,EACnB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CACN;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,GAC/C;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CACpC,CA+DA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAwB3E"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Smart Handoff SSO Handler for SvelteKit
3
+ *
4
+ * Handles handoff token verification and session management for cross-domain SSO
5
+ * in SvelteKit server-side code.
6
+ */
7
+ import { redirect } from '@sveltejs/kit';
8
+ import { createServerSessionManager, } from './session.js';
9
+ /**
10
+ * Get auth config from options or event.locals
11
+ */
12
+ function getAuthConfig(event, options) {
13
+ // Try to get from options first
14
+ if (options?.issuer && options?.clientId) {
15
+ return { issuer: options.issuer, clientId: options.clientId };
16
+ }
17
+ // Fallback to event.locals (set by createAuthHandle)
18
+ const issuer = event.locals.authrim_issuer;
19
+ const clientId = event.locals.authrim_client_id;
20
+ if (!issuer || !clientId) {
21
+ throw new Error('Authrim config not found. Please provide issuer and clientId in options, or use createAuthHandle.');
22
+ }
23
+ return { issuer, clientId };
24
+ }
25
+ /**
26
+ * Verify handoff token from callback URL
27
+ *
28
+ * Usage in +page.server.ts:
29
+ * ```typescript
30
+ * export const load = async (event) => {
31
+ * const result = await verifyHandoffToken(event);
32
+ * if (!result.success) {
33
+ * throw redirect(302, '/login');
34
+ * }
35
+ * return { session: result.session, user: result.user };
36
+ * };
37
+ * ```
38
+ */
39
+ export async function verifyHandoffToken(event, options) {
40
+ const { url } = event;
41
+ const handoffToken = url.searchParams.get('handoff_token');
42
+ const state = url.searchParams.get('state');
43
+ if (!handoffToken || !state) {
44
+ return { success: false, error: 'Missing handoff token or state' };
45
+ }
46
+ try {
47
+ const { issuer, clientId } = getAuthConfig(event, options);
48
+ const verifyEndpoint = options?.verifyEndpoint || '/auth/external/handoff/verify';
49
+ const response = await fetch(`${issuer}${verifyEndpoint}`, {
50
+ method: 'POST',
51
+ headers: { 'Content-Type': 'application/json' },
52
+ body: JSON.stringify({
53
+ handoff_token: handoffToken,
54
+ state: state,
55
+ client_id: clientId,
56
+ }),
57
+ });
58
+ if (!response.ok) {
59
+ const error = await response.json().catch(() => ({}));
60
+ return {
61
+ success: false,
62
+ error: error.error_description || 'Handoff verification failed',
63
+ };
64
+ }
65
+ const data = await response.json();
66
+ // Save session to cookie
67
+ const sessionManager = createServerSessionManager(options?.sessionOptions);
68
+ const authContext = {
69
+ session: {
70
+ id: data.session.id,
71
+ userId: data.session.userId,
72
+ createdAt: data.session.createdAt,
73
+ expiresAt: data.session.expiresAt,
74
+ },
75
+ user: {
76
+ id: data.user.id,
77
+ email: data.user.email ?? undefined,
78
+ name: data.user.name ?? undefined,
79
+ emailVerified: data.user.emailVerified,
80
+ },
81
+ };
82
+ sessionManager.set(event, authContext);
83
+ return {
84
+ success: true,
85
+ session: authContext.session,
86
+ user: authContext.user,
87
+ };
88
+ }
89
+ catch (error) {
90
+ return {
91
+ success: false,
92
+ error: error instanceof Error ? error.message : 'Unknown error',
93
+ };
94
+ }
95
+ }
96
+ /**
97
+ * Create handoff handler for SvelteKit hooks
98
+ *
99
+ * Usage in hooks.server.ts:
100
+ * ```typescript
101
+ * import { sequence } from '@sveltejs/kit/hooks';
102
+ * import { createAuthHandle, createHandoffHandler } from '@authrim/sveltekit/server';
103
+ *
104
+ * export const handle = sequence(
105
+ * createAuthHandle({
106
+ * issuer: env.AUTHRIM_ISSUER,
107
+ * clientId: env.AUTHRIM_CLIENT_ID,
108
+ * }),
109
+ * createHandoffHandler()
110
+ * );
111
+ * ```
112
+ */
113
+ export function createHandoffHandler(options) {
114
+ return async ({ event, resolve }) => {
115
+ // Check if this is a handoff callback
116
+ const { url } = event;
117
+ if (url.searchParams.has('handoff_token')) {
118
+ const result = await verifyHandoffToken(event, options);
119
+ if (!result.success) {
120
+ const errorRedirect = options?.errorRedirect || '/login';
121
+ // Use 303 See Other (POST → GET redirect, safer than 302)
122
+ throw redirect(303, errorRedirect);
123
+ }
124
+ // Remove handoff token from URL
125
+ const cleanUrl = new URL(url);
126
+ cleanUrl.searchParams.delete('handoff_token');
127
+ cleanUrl.searchParams.delete('state');
128
+ // Use 303 See Other (認証後のリダイレクトに適切)
129
+ throw redirect(303, cleanUrl.toString());
130
+ }
131
+ return resolve(event);
132
+ };
133
+ }
@@ -1,4 +1,5 @@
1
1
  export { createServerSessionManager, type ServerSessionManager, type ServerSessionManagerOptions, type ServerAuthContext, } from './session.js';
2
2
  export { createAuthHandle, getServerSessionManager, getAuthFromEvent, type AuthHandleOptions, } from './handle.js';
3
3
  export { requireAuth, createAuthLoad, isAuthenticated, getUser, getSession, type AuthLoadOptions, } from './load.js';
4
+ export { verifyHandoffToken, createHandoffHandler, type HandoffVerifyOptions, } from './handoff.js';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,KAAK,oBAAoB,EACzB,KAAK,2BAA2B,EAChC,KAAK,iBAAiB,GACvB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,gBAAgB,EAChB,KAAK,iBAAiB,GACvB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,WAAW,EACX,cAAc,EACd,eAAe,EACf,OAAO,EACP,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,KAAK,oBAAoB,EACzB,KAAK,2BAA2B,EAChC,KAAK,iBAAiB,GACvB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,gBAAgB,EAChB,KAAK,iBAAiB,GACvB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,WAAW,EACX,cAAc,EACd,eAAe,EACf,OAAO,EACP,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,oBAAoB,GAC1B,MAAM,cAAc,CAAC"}
@@ -1,3 +1,4 @@
1
1
  export { createServerSessionManager, } from './session.js';
2
2
  export { createAuthHandle, getServerSessionManager, getAuthFromEvent, } from './handle.js';
3
3
  export { requireAuth, createAuthLoad, isAuthenticated, getUser, getSession, } from './load.js';
4
+ export { verifyHandoffToken, createHandoffHandler, } from './handoff.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@authrim/sveltekit",
3
3
  "packageManager": "pnpm@9.15.0",
4
- "version": "0.1.3",
4
+ "version": "0.1.4",
5
5
  "description": "SvelteKit SDK for Authrim authentication",
6
6
  "type": "module",
7
7
  "svelte": "./dist/index.js",