@authrim/sveltekit 0.1.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/LICENSE +191 -0
- package/README.md +531 -0
- package/dist/__tests__/client-events.test.d.ts +2 -0
- package/dist/__tests__/client-events.test.d.ts.map +1 -0
- package/dist/__tests__/client-events.test.js +225 -0
- package/dist/__tests__/providers.test.d.ts +2 -0
- package/dist/__tests__/providers.test.d.ts.map +1 -0
- package/dist/__tests__/providers.test.js +68 -0
- package/dist/__tests__/response.test.d.ts +2 -0
- package/dist/__tests__/response.test.d.ts.map +1 -0
- package/dist/__tests__/response.test.js +99 -0
- package/dist/__tests__/stores.test.d.ts +2 -0
- package/dist/__tests__/stores.test.d.ts.map +1 -0
- package/dist/__tests__/stores.test.js +91 -0
- package/dist/client.d.ts +25 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +411 -0
- package/dist/components/AuthProvider.svelte +56 -0
- package/dist/components/AuthProvider.svelte.d.ts +34 -0
- package/dist/components/AuthProvider.svelte.d.ts.map +1 -0
- package/dist/components/ProtectedRoute.svelte +71 -0
- package/dist/components/ProtectedRoute.svelte.d.ts +38 -0
- package/dist/components/ProtectedRoute.svelte.d.ts.map +1 -0
- package/dist/components/SignInButton.svelte +93 -0
- package/dist/components/SignInButton.svelte.d.ts +43 -0
- package/dist/components/SignInButton.svelte.d.ts.map +1 -0
- package/dist/components/SignOutButton.svelte +72 -0
- package/dist/components/SignOutButton.svelte.d.ts +40 -0
- package/dist/components/SignOutButton.svelte.d.ts.map +1 -0
- package/dist/components/UserProfile.svelte +71 -0
- package/dist/components/UserProfile.svelte.d.ts +51 -0
- package/dist/components/UserProfile.svelte.d.ts.map +1 -0
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +5 -0
- package/dist/direct-auth/ciba.d.ts +47 -0
- package/dist/direct-auth/ciba.d.ts.map +1 -0
- package/dist/direct-auth/ciba.js +77 -0
- package/dist/direct-auth/consent.d.ts +85 -0
- package/dist/direct-auth/consent.d.ts.map +1 -0
- package/dist/direct-auth/consent.js +57 -0
- package/dist/direct-auth/device-flow.d.ts +40 -0
- package/dist/direct-auth/device-flow.d.ts.map +1 -0
- package/dist/direct-auth/device-flow.js +45 -0
- package/dist/direct-auth/email-code.d.ts +48 -0
- package/dist/direct-auth/email-code.d.ts.map +1 -0
- package/dist/direct-auth/email-code.js +265 -0
- package/dist/direct-auth/index.d.ts +9 -0
- package/dist/direct-auth/index.d.ts.map +1 -0
- package/dist/direct-auth/index.js +8 -0
- package/dist/direct-auth/login-challenge.d.ts +41 -0
- package/dist/direct-auth/login-challenge.d.ts.map +1 -0
- package/dist/direct-auth/login-challenge.js +34 -0
- package/dist/direct-auth/passkey.d.ts +30 -0
- package/dist/direct-auth/passkey.d.ts.map +1 -0
- package/dist/direct-auth/passkey.js +392 -0
- package/dist/direct-auth/session.d.ts +48 -0
- package/dist/direct-auth/session.d.ts.map +1 -0
- package/dist/direct-auth/session.js +219 -0
- package/dist/direct-auth/social.d.ts +56 -0
- package/dist/direct-auth/social.d.ts.map +1 -0
- package/dist/direct-auth/social.js +484 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/providers/crypto.d.ts +13 -0
- package/dist/providers/crypto.d.ts.map +1 -0
- package/dist/providers/crypto.js +27 -0
- package/dist/providers/http.d.ts +30 -0
- package/dist/providers/http.d.ts.map +1 -0
- package/dist/providers/http.js +65 -0
- package/dist/providers/index.d.ts +4 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +3 -0
- package/dist/providers/storage.d.ts +21 -0
- package/dist/providers/storage.d.ts.map +1 -0
- package/dist/providers/storage.js +83 -0
- package/dist/server/handle.d.ts +46 -0
- package/dist/server/handle.d.ts.map +1 -0
- package/dist/server/handle.js +60 -0
- package/dist/server/index.d.ts +4 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +3 -0
- package/dist/server/load.d.ts +83 -0
- package/dist/server/load.d.ts.map +1 -0
- package/dist/server/load.js +86 -0
- package/dist/server/session.d.ts +44 -0
- package/dist/server/session.d.ts.map +1 -0
- package/dist/server/session.js +50 -0
- package/dist/stores/auth.d.ts +56 -0
- package/dist/stores/auth.d.ts.map +1 -0
- package/dist/stores/auth.js +64 -0
- package/dist/stores/index.d.ts +2 -0
- package/dist/stores/index.d.ts.map +1 -0
- package/dist/stores/index.js +1 -0
- package/dist/types.d.ts +164 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/ui/account/LinkAccountButton.svelte +133 -0
- package/dist/ui/account/LinkAccountButton.svelte.d.ts +37 -0
- package/dist/ui/account/LinkAccountButton.svelte.d.ts.map +1 -0
- package/dist/ui/account/LinkedAccountsList.svelte +233 -0
- package/dist/ui/account/LinkedAccountsList.svelte.d.ts +32 -0
- package/dist/ui/account/LinkedAccountsList.svelte.d.ts.map +1 -0
- package/dist/ui/account/UnlinkAccountButton.svelte +179 -0
- package/dist/ui/account/UnlinkAccountButton.svelte.d.ts +28 -0
- package/dist/ui/account/UnlinkAccountButton.svelte.d.ts.map +1 -0
- package/dist/ui/account/index.d.ts +7 -0
- package/dist/ui/account/index.d.ts.map +1 -0
- package/dist/ui/account/index.js +6 -0
- package/dist/ui/context.d.ts +17 -0
- package/dist/ui/context.d.ts.map +1 -0
- package/dist/ui/context.js +71 -0
- package/dist/ui/forms/CIBARequestCard.svelte +315 -0
- package/dist/ui/forms/CIBARequestCard.svelte.d.ts +50 -0
- package/dist/ui/forms/CIBARequestCard.svelte.d.ts.map +1 -0
- package/dist/ui/forms/ClientInfo.svelte +232 -0
- package/dist/ui/forms/ClientInfo.svelte.d.ts +35 -0
- package/dist/ui/forms/ClientInfo.svelte.d.ts.map +1 -0
- package/dist/ui/forms/ConsentScopesList.svelte +109 -0
- package/dist/ui/forms/ConsentScopesList.svelte.d.ts +30 -0
- package/dist/ui/forms/ConsentScopesList.svelte.d.ts.map +1 -0
- package/dist/ui/forms/EmailCodeForm.svelte +224 -0
- package/dist/ui/forms/EmailCodeForm.svelte.d.ts +39 -0
- package/dist/ui/forms/EmailCodeForm.svelte.d.ts.map +1 -0
- package/dist/ui/forms/OrgSelector.svelte +95 -0
- package/dist/ui/forms/OrgSelector.svelte.d.ts +37 -0
- package/dist/ui/forms/OrgSelector.svelte.d.ts.map +1 -0
- package/dist/ui/forms/PasskeyConditionalInput.svelte +173 -0
- package/dist/ui/forms/PasskeyConditionalInput.svelte.d.ts +36 -0
- package/dist/ui/forms/PasskeyConditionalInput.svelte.d.ts.map +1 -0
- package/dist/ui/forms/QRCodeDisplay.svelte +122 -0
- package/dist/ui/forms/QRCodeDisplay.svelte.d.ts +27 -0
- package/dist/ui/forms/QRCodeDisplay.svelte.d.ts.map +1 -0
- package/dist/ui/forms/SocialLoginButtons.svelte +209 -0
- package/dist/ui/forms/SocialLoginButtons.svelte.d.ts +33 -0
- package/dist/ui/forms/SocialLoginButtons.svelte.d.ts.map +1 -0
- package/dist/ui/forms/UserCodeInput.svelte +183 -0
- package/dist/ui/forms/UserCodeInput.svelte.d.ts +34 -0
- package/dist/ui/forms/UserCodeInput.svelte.d.ts.map +1 -0
- package/dist/ui/forms/index.d.ts +13 -0
- package/dist/ui/forms/index.d.ts.map +1 -0
- package/dist/ui/forms/index.js +12 -0
- package/dist/ui/helpers/AuthError.svelte +124 -0
- package/dist/ui/helpers/AuthError.svelte.d.ts +26 -0
- package/dist/ui/helpers/AuthError.svelte.d.ts.map +1 -0
- package/dist/ui/helpers/AuthLoading.svelte +83 -0
- package/dist/ui/helpers/AuthLoading.svelte.d.ts +25 -0
- package/dist/ui/helpers/AuthLoading.svelte.d.ts.map +1 -0
- package/dist/ui/helpers/OTPInput.svelte +214 -0
- package/dist/ui/helpers/OTPInput.svelte.d.ts +34 -0
- package/dist/ui/helpers/OTPInput.svelte.d.ts.map +1 -0
- package/dist/ui/helpers/ResendCodeButton.svelte +140 -0
- package/dist/ui/helpers/ResendCodeButton.svelte.d.ts +28 -0
- package/dist/ui/helpers/ResendCodeButton.svelte.d.ts.map +1 -0
- package/dist/ui/helpers/index.d.ts +8 -0
- package/dist/ui/helpers/index.d.ts.map +1 -0
- package/dist/ui/helpers/index.js +7 -0
- package/dist/ui/index.d.ts +43 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +48 -0
- package/dist/ui/passkey/PasskeyDeleteButton.svelte +177 -0
- package/dist/ui/passkey/PasskeyDeleteButton.svelte.d.ts +26 -0
- package/dist/ui/passkey/PasskeyDeleteButton.svelte.d.ts.map +1 -0
- package/dist/ui/passkey/PasskeyList.svelte +225 -0
- package/dist/ui/passkey/PasskeyList.svelte.d.ts +30 -0
- package/dist/ui/passkey/PasskeyList.svelte.d.ts.map +1 -0
- package/dist/ui/passkey/PasskeyRegisterButton.svelte +52 -0
- package/dist/ui/passkey/PasskeyRegisterButton.svelte.d.ts +38 -0
- package/dist/ui/passkey/PasskeyRegisterButton.svelte.d.ts.map +1 -0
- package/dist/ui/passkey/index.d.ts +7 -0
- package/dist/ui/passkey/index.d.ts.map +1 -0
- package/dist/ui/passkey/index.js +6 -0
- package/dist/ui/session/SessionExpiryIndicator.svelte +109 -0
- package/dist/ui/session/SessionExpiryIndicator.svelte.d.ts +23 -0
- package/dist/ui/session/SessionExpiryIndicator.svelte.d.ts.map +1 -0
- package/dist/ui/session/SessionList.svelte +231 -0
- package/dist/ui/session/SessionList.svelte.d.ts +31 -0
- package/dist/ui/session/SessionList.svelte.d.ts.map +1 -0
- package/dist/ui/session/SessionRevokeButton.svelte +72 -0
- package/dist/ui/session/SessionRevokeButton.svelte.d.ts +26 -0
- package/dist/ui/session/SessionRevokeButton.svelte.d.ts.map +1 -0
- package/dist/ui/session/index.d.ts +7 -0
- package/dist/ui/session/index.d.ts.map +1 -0
- package/dist/ui/session/index.js +6 -0
- package/dist/ui/shared/Alert.svelte +246 -0
- package/dist/ui/shared/Alert.svelte.d.ts +36 -0
- package/dist/ui/shared/Alert.svelte.d.ts.map +1 -0
- package/dist/ui/shared/Badge.svelte +100 -0
- package/dist/ui/shared/Badge.svelte.d.ts +35 -0
- package/dist/ui/shared/Badge.svelte.d.ts.map +1 -0
- package/dist/ui/shared/Button.svelte +213 -0
- package/dist/ui/shared/Button.svelte.d.ts +42 -0
- package/dist/ui/shared/Button.svelte.d.ts.map +1 -0
- package/dist/ui/shared/Card.svelte +85 -0
- package/dist/ui/shared/Card.svelte.d.ts +39 -0
- package/dist/ui/shared/Card.svelte.d.ts.map +1 -0
- package/dist/ui/shared/CountdownTimer.svelte +150 -0
- package/dist/ui/shared/CountdownTimer.svelte.d.ts +30 -0
- package/dist/ui/shared/CountdownTimer.svelte.d.ts.map +1 -0
- package/dist/ui/shared/Dialog.svelte +240 -0
- package/dist/ui/shared/Dialog.svelte.d.ts +39 -0
- package/dist/ui/shared/Dialog.svelte.d.ts.map +1 -0
- package/dist/ui/shared/Input.svelte +192 -0
- package/dist/ui/shared/Input.svelte.d.ts +42 -0
- package/dist/ui/shared/Input.svelte.d.ts.map +1 -0
- package/dist/ui/shared/LanguageSwitcher.svelte +99 -0
- package/dist/ui/shared/LanguageSwitcher.svelte.d.ts +31 -0
- package/dist/ui/shared/LanguageSwitcher.svelte.d.ts.map +1 -0
- package/dist/ui/shared/Spinner.svelte +75 -0
- package/dist/ui/shared/Spinner.svelte.d.ts +24 -0
- package/dist/ui/shared/Spinner.svelte.d.ts.map +1 -0
- package/dist/ui/shared/index.d.ts +13 -0
- package/dist/ui/shared/index.d.ts.map +1 -0
- package/dist/ui/shared/index.js +12 -0
- package/dist/ui/styles/base.css +168 -0
- package/dist/ui/styles/theme.css +279 -0
- package/dist/ui/templates/AccountSettingsTemplate.svelte +205 -0
- package/dist/ui/templates/AccountSettingsTemplate.svelte.d.ts +49 -0
- package/dist/ui/templates/AccountSettingsTemplate.svelte.d.ts.map +1 -0
- package/dist/ui/templates/CIBATemplate.svelte +227 -0
- package/dist/ui/templates/CIBATemplate.svelte.d.ts +45 -0
- package/dist/ui/templates/CIBATemplate.svelte.d.ts.map +1 -0
- package/dist/ui/templates/ConsentTemplate.svelte +549 -0
- package/dist/ui/templates/ConsentTemplate.svelte.d.ts +76 -0
- package/dist/ui/templates/ConsentTemplate.svelte.d.ts.map +1 -0
- package/dist/ui/templates/DeviceFlowTemplate.svelte +228 -0
- package/dist/ui/templates/DeviceFlowTemplate.svelte.d.ts +47 -0
- package/dist/ui/templates/DeviceFlowTemplate.svelte.d.ts.map +1 -0
- package/dist/ui/templates/LoginTemplate.svelte +234 -0
- package/dist/ui/templates/LoginTemplate.svelte.d.ts +49 -0
- package/dist/ui/templates/LoginTemplate.svelte.d.ts.map +1 -0
- package/dist/ui/templates/ReauthTemplate.svelte +269 -0
- package/dist/ui/templates/ReauthTemplate.svelte.d.ts +54 -0
- package/dist/ui/templates/ReauthTemplate.svelte.d.ts.map +1 -0
- package/dist/ui/templates/SignUpTemplate.svelte +345 -0
- package/dist/ui/templates/SignUpTemplate.svelte.d.ts +53 -0
- package/dist/ui/templates/SignUpTemplate.svelte.d.ts.map +1 -0
- package/dist/ui/templates/index.d.ts +14 -0
- package/dist/ui/templates/index.d.ts.map +1 -0
- package/dist/ui/templates/index.js +13 -0
- package/dist/ui/types.d.ts +151 -0
- package/dist/ui/types.d.ts.map +1 -0
- package/dist/ui/types.js +4 -0
- package/dist/utils/context.d.ts +12 -0
- package/dist/utils/context.d.ts.map +1 -0
- package/dist/utils/context.js +26 -0
- package/dist/utils/error-mapping.d.ts +29 -0
- package/dist/utils/error-mapping.d.ts.map +1 -0
- package/dist/utils/error-mapping.js +38 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/response.d.ts +21 -0
- package/dist/utils/response.d.ts.map +1 -0
- package/dist/utils/response.js +84 -0
- package/dist/utils/sensitive-data.d.ts +9 -0
- package/dist/utils/sensitive-data.d.ts.map +1 -0
- package/dist/utils/sensitive-data.js +56 -0
- package/dist/utils/ssr.d.ts +38 -0
- package/dist/utils/ssr.d.ts.map +1 -0
- package/dist/utils/ssr.js +73 -0
- package/dist/utils/webauthn-converters.d.ts +9 -0
- package/dist/utils/webauthn-converters.d.ts.map +1 -0
- package/dist/utils/webauthn-converters.js +75 -0
- package/package.json +111 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Social Login Authentication
|
|
3
|
+
*/
|
|
4
|
+
import { type CryptoProvider, type AuthrimStorage, type SocialAuth, type SocialProvider, type SocialLoginOptions, type AuthResult, type Session, type User } from '@authrim/core';
|
|
5
|
+
export interface SocialAuthOptions {
|
|
6
|
+
issuer: string;
|
|
7
|
+
clientId: string;
|
|
8
|
+
crypto: CryptoProvider;
|
|
9
|
+
storage: AuthrimStorage;
|
|
10
|
+
exchangeToken: (authCode: string, codeVerifier: string) => Promise<{
|
|
11
|
+
session?: Session;
|
|
12
|
+
user?: User;
|
|
13
|
+
}>;
|
|
14
|
+
/**
|
|
15
|
+
* Popup close detection interval in milliseconds.
|
|
16
|
+
* Lower values provide faster detection but use more CPU.
|
|
17
|
+
* Default: 200ms
|
|
18
|
+
*/
|
|
19
|
+
popupCheckInterval?: number;
|
|
20
|
+
}
|
|
21
|
+
export declare class SocialAuthImpl implements SocialAuth {
|
|
22
|
+
private readonly issuer;
|
|
23
|
+
private readonly clientId;
|
|
24
|
+
private readonly pkce;
|
|
25
|
+
private readonly storage;
|
|
26
|
+
private readonly exchangeToken;
|
|
27
|
+
private readonly popupCheckIntervalMs;
|
|
28
|
+
private popupWindow;
|
|
29
|
+
private popupCheckIntervalId;
|
|
30
|
+
private popupResolve;
|
|
31
|
+
private readonly boundHandlePopupMessage;
|
|
32
|
+
constructor(options: SocialAuthOptions);
|
|
33
|
+
/**
|
|
34
|
+
* Cleanup resources (must be called when the auth client is destroyed)
|
|
35
|
+
*/
|
|
36
|
+
destroy(): void;
|
|
37
|
+
loginWithPopup(provider: SocialProvider, options?: SocialLoginOptions & {
|
|
38
|
+
redirectTo?: string;
|
|
39
|
+
}): Promise<AuthResult>;
|
|
40
|
+
loginWithRedirect(provider: SocialProvider, options?: SocialLoginOptions & {
|
|
41
|
+
redirectTo?: string;
|
|
42
|
+
}): Promise<void>;
|
|
43
|
+
handleCallback(): Promise<AuthResult>;
|
|
44
|
+
hasCallbackParams(): boolean;
|
|
45
|
+
getSupportedProviders(): SocialProvider[];
|
|
46
|
+
private generateState;
|
|
47
|
+
private buildAuthorizationUrl;
|
|
48
|
+
private getPopupCallbackUrl;
|
|
49
|
+
private getPopupFeatures;
|
|
50
|
+
private buildPopupFeaturesString;
|
|
51
|
+
private handlePopupMessage;
|
|
52
|
+
private cleanupPopup;
|
|
53
|
+
private clearStoredState;
|
|
54
|
+
private clearUrlParams;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=social.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"social.d.ts","sourceRoot":"","sources":["../../src/lib/direct-auth/social.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,OAAO,EACZ,KAAK,IAAI,EACV,MAAM,eAAe,CAAC;AAwGvB,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,cAAc,CAAC;IACxB,aAAa,EAAE,CACb,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,KACjB,OAAO,CAAC;QACX,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,IAAI,CAAC,EAAE,IAAI,CAAC;KACb,CAAC,CAAC;IACH;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAYD,qBAAa,cAAe,YAAW,UAAU;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqC;IACnE,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,oBAAoB,CAAuB;IACnD,OAAO,CAAC,YAAY,CAA+C;IACnE,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAgC;gBAE5D,OAAO,EAAE,iBAAiB;IActC;;OAEG;IACH,OAAO,IAAI,IAAI;IAOT,cAAc,CAClB,QAAQ,EAAE,cAAc,EACxB,OAAO,CAAC,EAAE,kBAAkB,GAAG;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GACrD,OAAO,CAAC,UAAU,CAAC;IAmEhB,iBAAiB,CACrB,QAAQ,EAAE,cAAc,EACxB,OAAO,CAAC,EAAE,kBAAkB,GAAG;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,GACrD,OAAO,CAAC,IAAI,CAAC;IA6BV,cAAc,IAAI,OAAO,CAAC,UAAU,CAAC;IA+G3C,iBAAiB,IAAI,OAAO;IAK5B,qBAAqB,IAAI,cAAc,EAAE;YAI3B,aAAa;IAM3B,OAAO,CAAC,qBAAqB;IA+B7B,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,wBAAwB;YAelB,kBAAkB;IAoHhC,OAAO,CAAC,YAAY;YAaN,gBAAgB;IAO9B,OAAO,CAAC,cAAc;CAQvB"}
|
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Social Login Authentication
|
|
3
|
+
*/
|
|
4
|
+
import { AuthrimError, PKCEHelper, } from '@authrim/core';
|
|
5
|
+
import { getAuthrimCode, mapSeverity } from '../utils/error-mapping.js';
|
|
6
|
+
const STORAGE_KEYS = {
|
|
7
|
+
STATE: 'authrim:direct:social:state',
|
|
8
|
+
CODE_VERIFIER: 'authrim:direct:social:code_verifier',
|
|
9
|
+
PROVIDER: 'authrim:direct:social:provider',
|
|
10
|
+
REDIRECT_URI: 'authrim:direct:social:redirect_uri',
|
|
11
|
+
};
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Redirect Path Validation & State Encoding
|
|
14
|
+
// =============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* Validates that a path is a safe relative path (no open redirect).
|
|
17
|
+
* Only allows paths starting with '/' and blocks protocol schemes.
|
|
18
|
+
*/
|
|
19
|
+
function isValidRelativePath(path) {
|
|
20
|
+
if (!path || typeof path !== 'string')
|
|
21
|
+
return false;
|
|
22
|
+
// Block protocol schemes (e.g., https:, javascript:, data:)
|
|
23
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(path))
|
|
24
|
+
return false;
|
|
25
|
+
// Block protocol-relative URLs (e.g., //evil.com)
|
|
26
|
+
if (path.startsWith('//'))
|
|
27
|
+
return false;
|
|
28
|
+
// Block backslashes (some browsers normalize \/ to //)
|
|
29
|
+
if (path.includes('\\'))
|
|
30
|
+
return false;
|
|
31
|
+
// Must start with '/' (relative to origin)
|
|
32
|
+
if (!path.startsWith('/'))
|
|
33
|
+
return false;
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Base64url encode (URL-safe base64 without padding)
|
|
38
|
+
*/
|
|
39
|
+
function base64urlEncode(bytes) {
|
|
40
|
+
// Use reduce instead of spread to avoid stack overflow with large arrays
|
|
41
|
+
const binary = bytes.reduce((str, byte) => str + String.fromCharCode(byte), '');
|
|
42
|
+
const base64 = btoa(binary);
|
|
43
|
+
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Base64url decode (URL-safe base64)
|
|
47
|
+
*/
|
|
48
|
+
function base64urlDecode(encoded) {
|
|
49
|
+
// Restore standard base64 characters
|
|
50
|
+
let base64 = encoded.replace(/-/g, '+').replace(/_/g, '/');
|
|
51
|
+
// Add padding if needed
|
|
52
|
+
while (base64.length % 4) {
|
|
53
|
+
base64 += '=';
|
|
54
|
+
}
|
|
55
|
+
const binary = atob(base64);
|
|
56
|
+
const bytes = new Uint8Array(binary.length);
|
|
57
|
+
for (let i = 0; i < binary.length; i++) {
|
|
58
|
+
bytes[i] = binary.charCodeAt(i);
|
|
59
|
+
}
|
|
60
|
+
return bytes;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Encode state data (nonce + optional redirectTo) into a string.
|
|
64
|
+
* Uses base64url encoding with TextEncoder for Unicode support.
|
|
65
|
+
*/
|
|
66
|
+
function encodeStateData(nonce, redirectTo) {
|
|
67
|
+
// If no redirectTo, return plain nonce for backwards compatibility
|
|
68
|
+
if (!redirectTo)
|
|
69
|
+
return nonce;
|
|
70
|
+
const data = { nonce, redirectTo };
|
|
71
|
+
const json = JSON.stringify(data);
|
|
72
|
+
const bytes = new TextEncoder().encode(json);
|
|
73
|
+
return base64urlEncode(bytes);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Decode state data from encoded string.
|
|
77
|
+
* Supports both legacy plain nonce and new JSON format.
|
|
78
|
+
*/
|
|
79
|
+
function decodeStateData(encoded) {
|
|
80
|
+
if (!encoded)
|
|
81
|
+
return null;
|
|
82
|
+
// Legacy format: plain hex nonce (64 chars of hex)
|
|
83
|
+
if (/^[0-9a-f]+$/i.test(encoded)) {
|
|
84
|
+
return { nonce: encoded };
|
|
85
|
+
}
|
|
86
|
+
// New format: base64url encoded JSON
|
|
87
|
+
try {
|
|
88
|
+
const bytes = base64urlDecode(encoded);
|
|
89
|
+
const json = new TextDecoder().decode(bytes);
|
|
90
|
+
const data = JSON.parse(json);
|
|
91
|
+
// Validate structure
|
|
92
|
+
if (typeof data.nonce !== 'string')
|
|
93
|
+
return null;
|
|
94
|
+
if (data.redirectTo !== undefined && typeof data.redirectTo !== 'string')
|
|
95
|
+
return null;
|
|
96
|
+
return data;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** Default interval for checking if popup is closed (ms) */
|
|
103
|
+
const DEFAULT_POPUP_CHECK_INTERVAL = 200;
|
|
104
|
+
export class SocialAuthImpl {
|
|
105
|
+
issuer;
|
|
106
|
+
clientId;
|
|
107
|
+
pkce;
|
|
108
|
+
storage;
|
|
109
|
+
exchangeToken;
|
|
110
|
+
popupCheckIntervalMs;
|
|
111
|
+
popupWindow = null;
|
|
112
|
+
popupCheckIntervalId = null;
|
|
113
|
+
popupResolve = null;
|
|
114
|
+
boundHandlePopupMessage;
|
|
115
|
+
constructor(options) {
|
|
116
|
+
this.issuer = options.issuer;
|
|
117
|
+
this.clientId = options.clientId;
|
|
118
|
+
this.pkce = new PKCEHelper(options.crypto);
|
|
119
|
+
this.storage = options.storage;
|
|
120
|
+
this.exchangeToken = options.exchangeToken;
|
|
121
|
+
this.popupCheckIntervalMs = options.popupCheckInterval ?? DEFAULT_POPUP_CHECK_INTERVAL;
|
|
122
|
+
this.boundHandlePopupMessage = this.handlePopupMessage.bind(this);
|
|
123
|
+
if (typeof window !== 'undefined') {
|
|
124
|
+
window.addEventListener('message', this.boundHandlePopupMessage);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Cleanup resources (must be called when the auth client is destroyed)
|
|
129
|
+
*/
|
|
130
|
+
destroy() {
|
|
131
|
+
this.cleanupPopup();
|
|
132
|
+
if (typeof window !== 'undefined') {
|
|
133
|
+
window.removeEventListener('message', this.boundHandlePopupMessage);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async loginWithPopup(provider, options) {
|
|
137
|
+
const { codeVerifier, codeChallenge } = await this.pkce.generatePKCE();
|
|
138
|
+
const nonce = await this.generateState();
|
|
139
|
+
// Validate redirectTo and encode into state
|
|
140
|
+
const validatedRedirectTo = options?.redirectTo && isValidRelativePath(options.redirectTo)
|
|
141
|
+
? options.redirectTo
|
|
142
|
+
: undefined;
|
|
143
|
+
const state = encodeStateData(nonce, validatedRedirectTo);
|
|
144
|
+
const redirectUri = options?.redirectUri || this.getPopupCallbackUrl();
|
|
145
|
+
const authUrl = this.buildAuthorizationUrl(provider, {
|
|
146
|
+
state,
|
|
147
|
+
codeChallenge,
|
|
148
|
+
redirectUri,
|
|
149
|
+
scopes: options?.scopes,
|
|
150
|
+
loginHint: options?.loginHint,
|
|
151
|
+
});
|
|
152
|
+
const popupFeatures = this.getPopupFeatures(options?.popupFeatures);
|
|
153
|
+
const popup = window.open(authUrl, 'authrim_social_popup', this.buildPopupFeaturesString(popupFeatures));
|
|
154
|
+
if (!popup) {
|
|
155
|
+
return {
|
|
156
|
+
success: false,
|
|
157
|
+
error: {
|
|
158
|
+
error: 'popup_blocked',
|
|
159
|
+
error_description: 'Popup was blocked by the browser. Please allow popups and try again.',
|
|
160
|
+
code: 'AR004001',
|
|
161
|
+
meta: { retryable: false, severity: 'warn' },
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
this.popupWindow = popup;
|
|
166
|
+
await this.storage.set(STORAGE_KEYS.STATE, state);
|
|
167
|
+
await this.storage.set(STORAGE_KEYS.CODE_VERIFIER, codeVerifier);
|
|
168
|
+
await this.storage.set(STORAGE_KEYS.PROVIDER, provider);
|
|
169
|
+
await this.storage.set(STORAGE_KEYS.REDIRECT_URI, redirectUri);
|
|
170
|
+
return new Promise((resolve, reject) => {
|
|
171
|
+
this.popupResolve = resolve;
|
|
172
|
+
void reject;
|
|
173
|
+
this.popupCheckIntervalId = window.setInterval(() => {
|
|
174
|
+
if (popup.closed) {
|
|
175
|
+
this.cleanupPopup();
|
|
176
|
+
resolve({
|
|
177
|
+
success: false,
|
|
178
|
+
error: {
|
|
179
|
+
error: 'popup_closed',
|
|
180
|
+
error_description: 'The login popup was closed before completing authentication.',
|
|
181
|
+
code: 'AR004002',
|
|
182
|
+
meta: { retryable: false, severity: 'warn' },
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}, this.popupCheckIntervalMs);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
async loginWithRedirect(provider, options) {
|
|
190
|
+
const { codeVerifier, codeChallenge } = await this.pkce.generatePKCE();
|
|
191
|
+
const nonce = await this.generateState();
|
|
192
|
+
// Validate redirectTo and encode into state
|
|
193
|
+
const validatedRedirectTo = options?.redirectTo && isValidRelativePath(options.redirectTo)
|
|
194
|
+
? options.redirectTo
|
|
195
|
+
: undefined;
|
|
196
|
+
const state = encodeStateData(nonce, validatedRedirectTo);
|
|
197
|
+
const redirectUri = options?.redirectUri || window.location.href.split('?')[0];
|
|
198
|
+
await this.storage.set(STORAGE_KEYS.STATE, state);
|
|
199
|
+
await this.storage.set(STORAGE_KEYS.CODE_VERIFIER, codeVerifier);
|
|
200
|
+
await this.storage.set(STORAGE_KEYS.PROVIDER, provider);
|
|
201
|
+
await this.storage.set(STORAGE_KEYS.REDIRECT_URI, redirectUri);
|
|
202
|
+
const authUrl = this.buildAuthorizationUrl(provider, {
|
|
203
|
+
state,
|
|
204
|
+
codeChallenge,
|
|
205
|
+
redirectUri,
|
|
206
|
+
scopes: options?.scopes,
|
|
207
|
+
loginHint: options?.loginHint,
|
|
208
|
+
});
|
|
209
|
+
window.location.href = authUrl;
|
|
210
|
+
}
|
|
211
|
+
async handleCallback() {
|
|
212
|
+
const params = new URLSearchParams(window.location.search);
|
|
213
|
+
const code = params.get('code');
|
|
214
|
+
const state = params.get('state');
|
|
215
|
+
const error = params.get('error');
|
|
216
|
+
const errorDescription = params.get('error_description');
|
|
217
|
+
if (error) {
|
|
218
|
+
await this.clearStoredState();
|
|
219
|
+
return {
|
|
220
|
+
success: false,
|
|
221
|
+
error: {
|
|
222
|
+
error: error,
|
|
223
|
+
error_description: errorDescription || 'Authentication failed',
|
|
224
|
+
code: 'AR004003',
|
|
225
|
+
meta: { retryable: false, severity: 'error' },
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
if (!code || !state) {
|
|
230
|
+
await this.clearStoredState();
|
|
231
|
+
return {
|
|
232
|
+
success: false,
|
|
233
|
+
error: {
|
|
234
|
+
error: 'invalid_response',
|
|
235
|
+
error_description: 'Missing authorization code or state parameter',
|
|
236
|
+
code: 'AR004004',
|
|
237
|
+
meta: { retryable: false, severity: 'error' },
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
const storedState = await this.storage.get(STORAGE_KEYS.STATE);
|
|
242
|
+
const codeVerifier = await this.storage.get(STORAGE_KEYS.CODE_VERIFIER);
|
|
243
|
+
if (state !== storedState) {
|
|
244
|
+
await this.clearStoredState();
|
|
245
|
+
return {
|
|
246
|
+
success: false,
|
|
247
|
+
error: {
|
|
248
|
+
error: 'state_mismatch',
|
|
249
|
+
error_description: 'State parameter mismatch. Please try again.',
|
|
250
|
+
code: 'AR004005',
|
|
251
|
+
meta: { retryable: false, severity: 'error' },
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
if (!codeVerifier) {
|
|
256
|
+
await this.clearStoredState();
|
|
257
|
+
return {
|
|
258
|
+
success: false,
|
|
259
|
+
error: {
|
|
260
|
+
error: 'invalid_state',
|
|
261
|
+
error_description: 'No code verifier found. Please try again.',
|
|
262
|
+
code: 'AR004006',
|
|
263
|
+
meta: { retryable: false, severity: 'error' },
|
|
264
|
+
},
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
try {
|
|
268
|
+
const { session, user } = await this.exchangeToken(code, codeVerifier);
|
|
269
|
+
// Extract redirectTo from state (after validation)
|
|
270
|
+
const stateData = storedState ? decodeStateData(storedState) : null;
|
|
271
|
+
const redirectTo = stateData?.redirectTo && isValidRelativePath(stateData.redirectTo)
|
|
272
|
+
? stateData.redirectTo
|
|
273
|
+
: undefined;
|
|
274
|
+
await this.clearStoredState();
|
|
275
|
+
this.clearUrlParams();
|
|
276
|
+
return {
|
|
277
|
+
success: true,
|
|
278
|
+
session,
|
|
279
|
+
user,
|
|
280
|
+
redirectTo,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
catch (err) {
|
|
284
|
+
await this.clearStoredState();
|
|
285
|
+
if (err instanceof AuthrimError) {
|
|
286
|
+
return {
|
|
287
|
+
success: false,
|
|
288
|
+
error: {
|
|
289
|
+
error: err.code,
|
|
290
|
+
error_description: err.message,
|
|
291
|
+
code: getAuthrimCode(err.code, 'AR004000'),
|
|
292
|
+
meta: {
|
|
293
|
+
retryable: err.meta.retryable,
|
|
294
|
+
severity: mapSeverity(err.meta.severity),
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
success: false,
|
|
301
|
+
error: {
|
|
302
|
+
error: 'token_error',
|
|
303
|
+
error_description: err instanceof Error ? err.message : 'Failed to exchange token',
|
|
304
|
+
code: 'AR004007',
|
|
305
|
+
meta: { retryable: false, severity: 'error' },
|
|
306
|
+
},
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
hasCallbackParams() {
|
|
311
|
+
const params = new URLSearchParams(window.location.search);
|
|
312
|
+
return params.has('code') || params.has('error');
|
|
313
|
+
}
|
|
314
|
+
getSupportedProviders() {
|
|
315
|
+
return ['google', 'github', 'apple', 'microsoft', 'facebook'];
|
|
316
|
+
}
|
|
317
|
+
async generateState() {
|
|
318
|
+
const bytes = new Uint8Array(32);
|
|
319
|
+
crypto.getRandomValues(bytes);
|
|
320
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
|
|
321
|
+
}
|
|
322
|
+
buildAuthorizationUrl(provider, options) {
|
|
323
|
+
const params = new URLSearchParams({
|
|
324
|
+
response_type: 'code',
|
|
325
|
+
client_id: this.clientId,
|
|
326
|
+
redirect_uri: options.redirectUri,
|
|
327
|
+
state: options.state,
|
|
328
|
+
code_challenge: options.codeChallenge,
|
|
329
|
+
code_challenge_method: 'S256',
|
|
330
|
+
provider,
|
|
331
|
+
});
|
|
332
|
+
if (options.scopes && options.scopes.length > 0) {
|
|
333
|
+
params.set('scope', options.scopes.join(' '));
|
|
334
|
+
}
|
|
335
|
+
if (options.loginHint) {
|
|
336
|
+
params.set('login_hint', options.loginHint);
|
|
337
|
+
}
|
|
338
|
+
return `${this.issuer}/api/v1/auth/authorize?${params.toString()}`;
|
|
339
|
+
}
|
|
340
|
+
getPopupCallbackUrl() {
|
|
341
|
+
return `${window.location.origin}/auth/callback/popup`;
|
|
342
|
+
}
|
|
343
|
+
getPopupFeatures(options) {
|
|
344
|
+
const width = options?.width || 500;
|
|
345
|
+
const height = options?.height || 600;
|
|
346
|
+
const left = Math.max(0, (window.screen.width - width) / 2);
|
|
347
|
+
const top = Math.max(0, (window.screen.height - height) / 2);
|
|
348
|
+
return { width, height, left, top };
|
|
349
|
+
}
|
|
350
|
+
buildPopupFeaturesString(features) {
|
|
351
|
+
return [
|
|
352
|
+
`width=${features.width}`,
|
|
353
|
+
`height=${features.height}`,
|
|
354
|
+
`left=${features.left}`,
|
|
355
|
+
`top=${features.top}`,
|
|
356
|
+
'scrollbars=yes',
|
|
357
|
+
'resizable=yes',
|
|
358
|
+
'status=no',
|
|
359
|
+
'menubar=no',
|
|
360
|
+
'toolbar=no',
|
|
361
|
+
'location=yes',
|
|
362
|
+
].join(',');
|
|
363
|
+
}
|
|
364
|
+
async handlePopupMessage(event) {
|
|
365
|
+
if (event.origin !== window.location.origin) {
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
const data = event.data;
|
|
369
|
+
if (data.type !== 'authrim:social:callback') {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
const resolve = this.popupResolve;
|
|
373
|
+
if (!resolve) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
this.cleanupPopup();
|
|
377
|
+
if (data.error) {
|
|
378
|
+
resolve({
|
|
379
|
+
success: false,
|
|
380
|
+
error: {
|
|
381
|
+
error: data.error,
|
|
382
|
+
error_description: data.error_description || 'Authentication failed',
|
|
383
|
+
code: 'AR004003',
|
|
384
|
+
meta: { retryable: false, severity: 'error' },
|
|
385
|
+
},
|
|
386
|
+
});
|
|
387
|
+
await this.clearStoredState();
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
if (!data.code || !data.state) {
|
|
391
|
+
resolve({
|
|
392
|
+
success: false,
|
|
393
|
+
error: {
|
|
394
|
+
error: 'invalid_response',
|
|
395
|
+
error_description: 'Missing authorization code or state',
|
|
396
|
+
code: 'AR004004',
|
|
397
|
+
meta: { retryable: false, severity: 'error' },
|
|
398
|
+
},
|
|
399
|
+
});
|
|
400
|
+
await this.clearStoredState();
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
const storedState = await this.storage.get(STORAGE_KEYS.STATE);
|
|
404
|
+
const codeVerifier = await this.storage.get(STORAGE_KEYS.CODE_VERIFIER);
|
|
405
|
+
if (data.state !== storedState) {
|
|
406
|
+
resolve({
|
|
407
|
+
success: false,
|
|
408
|
+
error: {
|
|
409
|
+
error: 'state_mismatch',
|
|
410
|
+
error_description: 'State parameter mismatch',
|
|
411
|
+
code: 'AR004005',
|
|
412
|
+
meta: { retryable: false, severity: 'error' },
|
|
413
|
+
},
|
|
414
|
+
});
|
|
415
|
+
await this.clearStoredState();
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (!codeVerifier) {
|
|
419
|
+
resolve({
|
|
420
|
+
success: false,
|
|
421
|
+
error: {
|
|
422
|
+
error: 'invalid_state',
|
|
423
|
+
error_description: 'No code verifier found',
|
|
424
|
+
code: 'AR004006',
|
|
425
|
+
meta: { retryable: false, severity: 'error' },
|
|
426
|
+
},
|
|
427
|
+
});
|
|
428
|
+
await this.clearStoredState();
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
try {
|
|
432
|
+
const { session, user } = await this.exchangeToken(data.code, codeVerifier);
|
|
433
|
+
// Extract redirectTo from state (after validation)
|
|
434
|
+
const stateData = storedState ? decodeStateData(storedState) : null;
|
|
435
|
+
const redirectTo = stateData?.redirectTo && isValidRelativePath(stateData.redirectTo)
|
|
436
|
+
? stateData.redirectTo
|
|
437
|
+
: undefined;
|
|
438
|
+
await this.clearStoredState();
|
|
439
|
+
resolve({
|
|
440
|
+
success: true,
|
|
441
|
+
session,
|
|
442
|
+
user,
|
|
443
|
+
redirectTo,
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
catch (err) {
|
|
447
|
+
await this.clearStoredState();
|
|
448
|
+
resolve({
|
|
449
|
+
success: false,
|
|
450
|
+
error: {
|
|
451
|
+
error: 'token_error',
|
|
452
|
+
error_description: err instanceof Error ? err.message : 'Failed to exchange token',
|
|
453
|
+
code: 'AR004007',
|
|
454
|
+
meta: { retryable: false, severity: 'error' },
|
|
455
|
+
},
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
cleanupPopup() {
|
|
460
|
+
if (this.popupCheckIntervalId) {
|
|
461
|
+
clearInterval(this.popupCheckIntervalId);
|
|
462
|
+
this.popupCheckIntervalId = null;
|
|
463
|
+
}
|
|
464
|
+
if (this.popupWindow && !this.popupWindow.closed) {
|
|
465
|
+
this.popupWindow.close();
|
|
466
|
+
}
|
|
467
|
+
this.popupWindow = null;
|
|
468
|
+
this.popupResolve = null;
|
|
469
|
+
}
|
|
470
|
+
async clearStoredState() {
|
|
471
|
+
await this.storage.remove(STORAGE_KEYS.STATE);
|
|
472
|
+
await this.storage.remove(STORAGE_KEYS.CODE_VERIFIER);
|
|
473
|
+
await this.storage.remove(STORAGE_KEYS.PROVIDER);
|
|
474
|
+
await this.storage.remove(STORAGE_KEYS.REDIRECT_URI);
|
|
475
|
+
}
|
|
476
|
+
clearUrlParams() {
|
|
477
|
+
const url = new URL(window.location.href);
|
|
478
|
+
url.searchParams.delete('code');
|
|
479
|
+
url.searchParams.delete('state');
|
|
480
|
+
url.searchParams.delete('error');
|
|
481
|
+
url.searchParams.delete('error_description');
|
|
482
|
+
window.history.replaceState({}, '', url.toString());
|
|
483
|
+
}
|
|
484
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @authrim/sveltekit - SvelteKit SDK for Authrim
|
|
3
|
+
*/
|
|
4
|
+
export { createAuthrim } from "./client.js";
|
|
5
|
+
export { setAuthContext, getAuthContext, hasAuthContext, AUTH_CONTEXT_KEY, } from "./utils/context.js";
|
|
6
|
+
export type { AuthrimConfig, StorageOptions, StorageType, AuthrimClient, AuthResponse, AuthError, AuthSessionData, PasskeyNamespace, EmailCodeNamespace, SocialNamespace, SessionNamespace, ConsentNamespace, DeviceFlowNamespace, CIBANamespace, LoginChallengeNamespace, SignInShortcuts, SignUpShortcuts, SignOutOptions, AuthEventName, AuthEventPayloads, AuthEventHandler, AuthStores, Session, User, SocialProvider, PasskeyLoginOptions, PasskeySignUpOptions, PasskeyRegisterOptions, PasskeyCredential, EmailCodeSendOptions, EmailCodeSendResult, EmailCodeVerifyOptions, SocialLoginOptions, DirectAuthLogoutOptions, NextAction, AuthLoadingState, } from "./types.js";
|
|
7
|
+
export { createAuthStores, toAuthError as toStoreAuthError, } from "./stores/auth.js";
|
|
8
|
+
export type { AuthError as StoreAuthError, InternalAuthStores, } from "./stores/auth.js";
|
|
9
|
+
export { BrowserHttpClient, type BrowserHttpClientOptions, } from "./providers/http.js";
|
|
10
|
+
export { BrowserCryptoProvider } from "./providers/crypto.js";
|
|
11
|
+
export { createBrowserStorage, type BrowserStorageOptions, } from "./providers/storage.js";
|
|
12
|
+
export type { ConsentScreenData, ConsentClientInfo, ConsentScopeInfo, ConsentUserInfo, ConsentOrgInfo, ConsentActingAsInfo, ConsentFeatureFlags, ConsentSubmitOptions, ConsentSubmitResult, } from "./direct-auth/consent.js";
|
|
13
|
+
export type { DeviceFlowSubmitResult } from "./direct-auth/device-flow.js";
|
|
14
|
+
export { DeviceFlowVerificationError } from "./direct-auth/device-flow.js";
|
|
15
|
+
export type { CIBAPendingRequest, CIBAActionResult, } from "./direct-auth/ciba.js";
|
|
16
|
+
export type { LoginChallengeData, LoginChallengeClientInfo, } from "./direct-auth/login-challenge.js";
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,EACL,cAAc,EACd,cAAc,EACd,cAAc,EACd,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAEV,aAAa,EACb,cAAc,EACd,WAAW,EAEX,aAAa,EAEb,YAAY,EACZ,SAAS,EACT,eAAe,EAEf,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,uBAAuB,EACvB,eAAe,EACf,eAAe,EACf,cAAc,EAEd,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAEhB,UAAU,EAEV,OAAO,EACP,IAAI,EACJ,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,EAClB,uBAAuB,EACvB,UAAU,EACV,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,gBAAgB,EAChB,WAAW,IAAI,gBAAgB,GAChC,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,SAAS,IAAI,cAAc,EAC3B,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,iBAAiB,EACjB,KAAK,wBAAwB,GAC9B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EACL,oBAAoB,EACpB,KAAK,qBAAqB,GAC3B,MAAM,wBAAwB,CAAC;AAGhC,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,YAAY,EACV,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,kCAAkC,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @authrim/sveltekit - SvelteKit SDK for Authrim
|
|
3
|
+
*/
|
|
4
|
+
// Main client
|
|
5
|
+
export { createAuthrim } from "./client.js";
|
|
6
|
+
// Context utilities
|
|
7
|
+
export { setAuthContext, getAuthContext, hasAuthContext, AUTH_CONTEXT_KEY, } from "./utils/context.js";
|
|
8
|
+
// Stores
|
|
9
|
+
export { createAuthStores, toAuthError as toStoreAuthError, } from "./stores/auth.js";
|
|
10
|
+
// Providers (for advanced use)
|
|
11
|
+
export { BrowserHttpClient, } from "./providers/http.js";
|
|
12
|
+
export { BrowserCryptoProvider } from "./providers/crypto.js";
|
|
13
|
+
export { createBrowserStorage, } from "./providers/storage.js";
|
|
14
|
+
export { DeviceFlowVerificationError } from "./direct-auth/device-flow.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser Crypto Provider
|
|
3
|
+
*
|
|
4
|
+
* Web Crypto API を使用したプラットフォーム実装
|
|
5
|
+
*/
|
|
6
|
+
import type { CryptoProvider } from '@authrim/core';
|
|
7
|
+
export declare class BrowserCryptoProvider implements CryptoProvider {
|
|
8
|
+
randomBytes(length: number): Promise<Uint8Array>;
|
|
9
|
+
sha256(data: string): Promise<Uint8Array>;
|
|
10
|
+
generateCodeVerifier(): Promise<string>;
|
|
11
|
+
generateCodeChallenge(verifier: string): Promise<string>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/lib/providers/crypto.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,qBAAa,qBAAsB,YAAW,cAAc;IACpD,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAMhD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAOzC,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;IAKvC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAI/D"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser Crypto Provider
|
|
3
|
+
*
|
|
4
|
+
* Web Crypto API を使用したプラットフォーム実装
|
|
5
|
+
*/
|
|
6
|
+
import { base64urlEncode } from '@authrim/core';
|
|
7
|
+
export class BrowserCryptoProvider {
|
|
8
|
+
async randomBytes(length) {
|
|
9
|
+
const bytes = new Uint8Array(length);
|
|
10
|
+
crypto.getRandomValues(bytes);
|
|
11
|
+
return bytes;
|
|
12
|
+
}
|
|
13
|
+
async sha256(data) {
|
|
14
|
+
const encoder = new TextEncoder();
|
|
15
|
+
const bytes = encoder.encode(data);
|
|
16
|
+
const hash = await crypto.subtle.digest('SHA-256', bytes);
|
|
17
|
+
return new Uint8Array(hash);
|
|
18
|
+
}
|
|
19
|
+
async generateCodeVerifier() {
|
|
20
|
+
const bytes = await this.randomBytes(32);
|
|
21
|
+
return base64urlEncode(bytes);
|
|
22
|
+
}
|
|
23
|
+
async generateCodeChallenge(verifier) {
|
|
24
|
+
const hash = await this.sha256(verifier);
|
|
25
|
+
return base64urlEncode(hash);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser HTTP Client
|
|
3
|
+
*
|
|
4
|
+
* P0: credentials デフォルトは 'omit' - 必要な場合のみ 'include' を明示指定
|
|
5
|
+
* P0: 機密データのログ出力をマスキング
|
|
6
|
+
*/
|
|
7
|
+
import type { HttpClient, HttpOptions, HttpResponse } from '@authrim/core';
|
|
8
|
+
export interface BrowserHttpClientOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Default credentials mode
|
|
11
|
+
* P0: デフォルトは 'omit' - Cookie を送信しない
|
|
12
|
+
*/
|
|
13
|
+
credentials?: RequestCredentials;
|
|
14
|
+
/** Default timeout in ms (default: 30000) */
|
|
15
|
+
timeout?: number;
|
|
16
|
+
/** Enable debug logging (default: false) */
|
|
17
|
+
debug?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface BrowserHttpOptions extends HttpOptions {
|
|
20
|
+
credentials?: RequestCredentials;
|
|
21
|
+
}
|
|
22
|
+
export declare class BrowserHttpClient implements HttpClient {
|
|
23
|
+
private readonly defaultCredentials;
|
|
24
|
+
private readonly defaultTimeout;
|
|
25
|
+
private readonly debug;
|
|
26
|
+
constructor(options?: BrowserHttpClientOptions);
|
|
27
|
+
private debugLog;
|
|
28
|
+
fetch<T = unknown>(url: string, options?: BrowserHttpOptions): Promise<HttpResponse<T>>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/lib/providers/http.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAG3E,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,qBAAa,iBAAkB,YAAW,UAAU;IAClD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAU;gBAEpB,OAAO,CAAC,EAAE,wBAAwB;IAM9C,OAAO,CAAC,QAAQ;IAYV,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;CA0C9F"}
|