@smarthivelabs-devs/auth-sdk 1.1.0 → 1.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/README.md CHANGED
@@ -81,6 +81,14 @@ interface SmartHiveAuthConfig {
81
81
 
82
82
  /** Custom temporary storage for PKCE values (default: sessionStorage in browser) */
83
83
  temporaryStorage?: AuthStorage;
84
+
85
+ /**
86
+ * URL of your own backend's social auth proxy (e.g. "https://api.myapp.com").
87
+ * When set, social OAuth initiations route through your domain so Google/Apple
88
+ * consent screens show your domain instead of SmartHive's.
89
+ * See auth-expo README → "Social Auth Proxy" for the full setup guide.
90
+ */
91
+ socialProxyUrl?: string;
84
92
  }
85
93
  ```
86
94
 
@@ -131,6 +139,44 @@ await client.login({ state: "my-custom-state" });
131
139
 
132
140
  ---
133
141
 
142
+ ### `client.loginSocial(provider, options?)`
143
+
144
+ Initiates a per-project social OAuth flow. The browser is redirected to the provider's consent screen using **your project's own** Google/Apple/GitHub credentials — the consent screen shows your app name, not SmartHive's.
145
+
146
+ ```ts
147
+ // Redirect to Google's consent screen
148
+ await client.loginSocial("google");
149
+
150
+ // Override the redirect_uri that receives the tokens
151
+ await client.loginSocial("github", { redirectUri: "https://myapp.com/auth/social/callback" });
152
+ ```
153
+
154
+ Supported providers:
155
+ `google` · `apple` · `github` · `facebook` · `twitter` · `linkedin` · `microsoft` · `discord` · `spotify` · `twitch` · `reddit` · `gitlab` · `slack` · `notion` · `zoom` · `figma`
156
+
157
+ Configure each provider's credentials in your SmartHive dashboard under **Project → OAuth Providers**.
158
+
159
+ ---
160
+
161
+ ### `client.handleSocialCallback(options?)`
162
+
163
+ Called on the page/route that your `redirectUri` points to after a social OAuth flow. Reads `access_token` and `refresh_token` from the URL query params, persists the session, and returns it.
164
+
165
+ ```ts
166
+ // On your /auth/social/callback page — reads window.location automatically
167
+ const session = await client.handleSocialCallback();
168
+
169
+ // Or pass the URL explicitly (SSR / React Native)
170
+ const session = await client.handleSocialCallback({ url: window.location.href });
171
+
172
+ console.log(session.accessToken); // short-lived JWT
173
+ console.log(session.refreshToken); // long-lived session token
174
+ ```
175
+
176
+ Throws `SmartHiveAuthError` with code `social_auth_failed` if the provider returned an error, or `callback_failed` if no `access_token` is present.
177
+
178
+ ---
179
+
134
180
  ### `client.handleCallback(options?)`
135
181
 
136
182
  Completes the OAuth flow on your callback route. Exchanges the authorization code for tokens and persists the session.
@@ -382,6 +428,7 @@ import type {
382
428
  SmartHiveAuthClient,
383
429
  AuthSession,
384
430
  AuthStorage,
431
+ SocialProvider,
385
432
  } from "@smarthivelabs-devs/auth-sdk";
386
433
  ```
387
434
 
package/dist/index.cjs CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  SmartHiveAuthError: () => SmartHiveAuthError,
24
+ envFromPublishableKey: () => envFromPublishableKey,
24
25
  generateCodeChallenge: () => generateCodeChallenge,
25
26
  generateCodeVerifier: () => generateCodeVerifier,
26
27
  initAuth: () => initAuth,
@@ -262,6 +263,39 @@ function initAuth(config) {
262
263
  await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceState);
263
264
  return session;
264
265
  },
266
+ async loginSocial(provider, options) {
267
+ const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;
268
+ if (!redirectUri) throw new SmartHiveAuthError("missing_redirect_uri", "redirectUri is required for social login.");
269
+ let url;
270
+ if (config.socialProxyUrl) {
271
+ url = new URL(`${normalizeBaseUrl(config.socialProxyUrl)}/api/auth/social/${provider}`);
272
+ url.searchParams.set("redirect_uri", redirectUri);
273
+ } else {
274
+ url = new URL(`${authBase}/${environment}/api/auth/social/${provider}`);
275
+ url.searchParams.set("project_id", config.projectId);
276
+ url.searchParams.set("redirect_uri", redirectUri);
277
+ }
278
+ globalThis.location.assign(url.toString());
279
+ },
280
+ async handleSocialCallback(options) {
281
+ const href = options?.url ?? globalThis.location?.href;
282
+ if (!href) throw new SmartHiveAuthError("callback_failed", "No URL available for social callback.");
283
+ const url = new URL(href);
284
+ const error = url.searchParams.get("error");
285
+ if (error) {
286
+ throw new SmartHiveAuthError(error, url.searchParams.get("error_description") ?? error);
287
+ }
288
+ const accessToken = url.searchParams.get("access_token");
289
+ if (!accessToken) throw new SmartHiveAuthError("callback_failed", "No access token in social callback URL.");
290
+ const expiresIn = url.searchParams.get("expires_in");
291
+ const session = {
292
+ accessToken,
293
+ refreshToken: url.searchParams.get("refresh_token") ?? void 0,
294
+ expiresAt: expiresIn ? Date.now() + parseInt(expiresIn, 10) * 1e3 : void 0
295
+ };
296
+ await saveSession(session);
297
+ return session;
298
+ },
265
299
  async logout() {
266
300
  await saveSession(null);
267
301
  await fetch(`${baseUrl}/api/auth/sign-out`, { method: "POST", credentials: "include" });
@@ -336,6 +370,7 @@ function initAuth(config) {
336
370
  // Annotate the CommonJS export names for ESM import in node:
337
371
  0 && (module.exports = {
338
372
  SmartHiveAuthError,
373
+ envFromPublishableKey,
339
374
  generateCodeChallenge,
340
375
  generateCodeVerifier,
341
376
  initAuth,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export interface SmartHiveAuthConfig {\n projectId: string;\n publishableKey: string;\n baseUrl: string;\n /** Custom branded auth domain, e.g. \"https://auth.myapp.com\". Used as the entry point for login/token flows. Falls back to baseUrl. */\n authDomain?: string;\n /** Fallback auth domain if authDomain is unreachable, e.g. \"https://auth.smarthivelabs.dev\". */\n fallbackAuthDomain?: string;\n redirectUri?: string;\n storage?: AuthStorage;\n temporaryStorage?: AuthStorage;\n}\n\nexport interface AuthStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\nexport interface AuthSession {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n user?: unknown;\n}\n\n// ── Headless types ────────────────────────────────────────────────────────────\n\nexport interface HeadlessSignInResult {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n user?: unknown;\n}\n\nexport interface HeadlessSignUpResult extends HeadlessSignInResult {\n /** True when email verification is required before the account can be used. */\n requiresVerification?: boolean;\n}\n\nexport interface HeadlessClient {\n signIn: {\n /**\n * Sign in with email and password. No browser redirect.\n * Returns tokens immediately on success.\n */\n email(params: { email: string; password: string }): Promise<HeadlessSignInResult>;\n\n phone: {\n /**\n * Send a one-time code to a phone number.\n * Call `verify` with the code the user receives.\n */\n sendOtp(params: { phoneNumber: string }): Promise<void>;\n /**\n * Verify the OTP sent to the phone number and return tokens on success.\n */\n verify(params: { phoneNumber: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n emailOtp: {\n /**\n * Send a one-time code to an email address.\n * Call `verify` with the code the user receives.\n */\n send(params: { email: string }): Promise<void>;\n /**\n * Verify the OTP sent to the email address and return tokens on success.\n */\n verify(params: { email: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n magicLink: {\n /**\n * Send a magic link to the given email address.\n * The user clicks the link — no token is returned here.\n */\n send(params: { email: string; callbackURL?: string }): Promise<void>;\n };\n };\n\n signUp: {\n /**\n * Create a new account with email and password. No browser redirect.\n * If email verification is required, `requiresVerification` will be true\n * and no tokens will be present — the user must verify before signing in.\n */\n email(params: { email: string; password: string; name?: string }): Promise<HeadlessSignUpResult>;\n };\n\n /** Refresh an expired access token using the refresh token. */\n refreshToken(params: { refreshToken: string }): Promise<{ accessToken: string; expiresAt: number }>;\n\n /** Sign the user out and invalidate their session on the server. */\n signOut(params?: { refreshToken?: string }): Promise<void>;\n}\n\nexport interface SmartHiveAuthClient {\n initialize(): Promise<void>;\n login(options?: { redirectUri?: string; state?: string }): Promise<void>;\n handleCallback(options?: { url?: string }): Promise<AuthSession>;\n logout(): Promise<void>;\n getSession(): Promise<AuthSession | null>;\n getAccessToken(): Promise<string | null>;\n getAuthorizationHeader(): Promise<Record<string, string>>;\n fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;\n refreshSession(): Promise<AuthSession | null>;\n verifyToken(token: string): Promise<boolean>;\n getUser(): Promise<unknown>;\n /**\n * Direct credential-based authentication — no browser redirect.\n * Use these methods when you want full control of the sign-in UI\n * (e.g. native mobile apps with custom login screens).\n */\n headless: HeadlessClient;\n}\n\nexport class SmartHiveAuthError extends Error {\n constructor(public code: string, message: string) {\n super(message);\n this.name = \"SmartHiveAuthError\";\n }\n}\n\n// ── PKCE helpers (Web Crypto — works in browser + Node 18+) ──────────────────\n\nexport async function generateCodeVerifier(): Promise<string> {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return base64urlEncode(array);\n}\n\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\n return base64urlEncode(new Uint8Array(digest));\n}\n\nfunction base64urlEncode(buffer: Uint8Array): string {\n let str = \"\";\n for (const byte of buffer) str += String.fromCharCode(byte);\n return btoa(str).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n// ── Storage keys ─────────────────────────────────────────────────────────────\n\nexport const smartHiveAuthStorageKeys = {\n session: \"smarthive.auth.session\",\n pkceVerifier: \"smarthive.auth.pkce_verifier\",\n pkceState: \"smarthive.auth.pkce_state\"\n} as const;\n\nfunction browserStorage(): AuthStorage {\n return {\n getItem: (key) => globalThis.localStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.localStorage?.setItem(key, value),\n removeItem: (key) => globalThis.localStorage?.removeItem(key)\n };\n}\n\nfunction sessionStorageAdapter(): Pick<AuthStorage, \"getItem\" | \"setItem\" | \"removeItem\"> {\n return {\n getItem: (key) => globalThis.sessionStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.sessionStorage?.setItem(key, value),\n removeItem: (key) => globalThis.sessionStorage?.removeItem(key)\n };\n}\n\nfunction normalizeBaseUrl(baseUrl: string) {\n return baseUrl.replace(/\\/$/, \"\");\n}\n\n/** Extract the environment prefix from a publishable key (pk_dev_*, pk_staging_*, pk_prod_*). */\nfunction envFromPublishableKey(publishableKey: string): string {\n const match = publishableKey.match(/^pk_(dev|staging|prod)_/);\n return match ? match[1] : \"prod\";\n}\n\n// ── Headless response shape from the backend ──────────────────────────────────\n\ninterface RawHeadlessResponse {\n access_token: string;\n refresh_token: string;\n expires_in: number;\n token_type: string;\n user?: unknown;\n requires_verification?: boolean;\n message?: string;\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\nexport function initAuth(config: SmartHiveAuthConfig): SmartHiveAuthClient {\n const baseUrl = normalizeBaseUrl(config.baseUrl);\n const authBase = normalizeBaseUrl(config.authDomain ?? config.baseUrl);\n const storage = config.storage ?? browserStorage();\n const tempStorage = config.temporaryStorage ?? sessionStorageAdapter();\n const environment = envFromPublishableKey(config.publishableKey);\n const headlessBase = `${baseUrl}/${environment}/api/auth/headless`;\n\n async function saveSession(session: AuthSession | null) {\n if (!session) { await storage.removeItem(smartHiveAuthStorageKeys.session); return; }\n await storage.setItem(smartHiveAuthStorageKeys.session, JSON.stringify(session));\n }\n\n async function readSession(): Promise<AuthSession | null> {\n const raw = await storage.getItem(smartHiveAuthStorageKeys.session);\n return raw ? JSON.parse(raw) as AuthSession : null;\n }\n\n function rawToSession(raw: RawHeadlessResponse): HeadlessSignInResult {\n return {\n accessToken: raw.access_token,\n refreshToken: raw.refresh_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n user: raw.user,\n };\n }\n\n async function headlessPost(path: string, body: Record<string, unknown>): Promise<RawHeadlessResponse> {\n const res = await fetch(`${headlessBase}${path}`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(\n err.error ?? \"request_failed\",\n err.message ?? `Request to ${path} failed.`\n );\n }\n\n return res.json() as Promise<RawHeadlessResponse>;\n }\n\n async function headlessSignInAndSave(path: string, body: Record<string, unknown>): Promise<HeadlessSignInResult> {\n const raw = await headlessPost(path, body);\n const result = rawToSession(raw);\n await saveSession(result);\n return result;\n }\n\n const headless: HeadlessClient = {\n signIn: {\n async email({ email, password }) {\n return headlessSignInAndSave(\"/sign-in/email\", { email, password });\n },\n\n phone: {\n async sendOtp({ phoneNumber }) {\n await headlessPost(\"/phone/send-otp\", { phoneNumber });\n },\n async verify({ phoneNumber, code }) {\n return headlessSignInAndSave(\"/phone/verify\", { phoneNumber, code });\n },\n },\n\n emailOtp: {\n async send({ email }) {\n await headlessPost(\"/email-otp/send\", { email });\n },\n async verify({ email, code }) {\n return headlessSignInAndSave(\"/email-otp/verify\", { email, code });\n },\n },\n\n magicLink: {\n async send({ email, callbackURL }) {\n await headlessPost(\"/magic-link/send\", { email, ...(callbackURL ? { callbackURL } : {}) });\n },\n },\n },\n\n signUp: {\n async email({ email, password, name }) {\n const res = await fetch(`${headlessBase}/sign-up/email`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ email, password, name }),\n });\n\n // 202 = account created but email verification required\n if (res.status === 202) {\n return { accessToken: \"\", refreshToken: \"\", expiresAt: 0, requiresVerification: true };\n }\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(err.error ?? \"sign_up_failed\", err.message ?? \"Sign up failed.\");\n }\n\n const raw = await res.json() as RawHeadlessResponse;\n const result: HeadlessSignUpResult = { ...rawToSession(raw), requiresVerification: false };\n await saveSession(result);\n return result;\n },\n },\n\n async refreshToken({ refreshToken }) {\n const raw = await headlessPost(\"/token/refresh\", { refresh_token: refreshToken });\n const updated: AuthSession = {\n ...(await readSession() ?? {}),\n accessToken: raw.access_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n };\n await saveSession(updated);\n return { accessToken: raw.access_token, expiresAt: updated.expiresAt! };\n },\n\n async signOut({ refreshToken } = {}) {\n const session = await readSession();\n const token = refreshToken ?? session?.refreshToken;\n await saveSession(null);\n if (token) {\n await fetch(`${headlessBase}/sign-out`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ refresh_token: token }),\n }).catch(() => {});\n }\n },\n };\n\n const client: SmartHiveAuthClient = {\n async initialize() {\n const response = await fetch(\n `${baseUrl}/sdk/config?projectId=${encodeURIComponent(config.projectId)}&publishableKey=${encodeURIComponent(config.publishableKey)}`\n );\n if (!response.ok) throw new SmartHiveAuthError(\"project_not_found\", \"Smart Hive Auth project configuration was not found.\");\n },\n\n async login(options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;\n const state = options?.state ?? crypto.randomUUID();\n const verifier = await generateCodeVerifier();\n const challenge = await generateCodeChallenge(verifier);\n\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceVerifier, verifier);\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceState, state);\n\n const url = new URL(`${authBase}/api/auth/oauth2/authorize`);\n url.searchParams.set(\"project_id\", config.projectId);\n url.searchParams.set(\"publishable_key\", config.publishableKey);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"redirect_uri\", redirectUri);\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge\", challenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n\n globalThis.location.assign(url.toString());\n },\n\n async handleCallback(options) {\n const href = options?.url ?? globalThis.location?.href;\n if (!href) throw new SmartHiveAuthError(\"callback_failed\", \"No URL provided for callback handling.\");\n\n const url = new URL(href);\n const code = url.searchParams.get(\"code\");\n const returnedState = url.searchParams.get(\"state\");\n\n if (!code) throw new SmartHiveAuthError(\"callback_failed\", \"No authorization code in callback URL.\");\n\n const storedState = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceState);\n if (!storedState || !returnedState || storedState !== returnedState) {\n throw new SmartHiveAuthError(\"state_mismatch\", \"OAuth state mismatch — possible CSRF attack.\");\n }\n\n const verifier = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceVerifier);\n if (!verifier) {\n throw new SmartHiveAuthError(\"pkce_missing\", \"Missing PKCE verifier for authorization code exchange.\");\n }\n const redirectUri = config.redirectUri ?? (url.origin + url.pathname);\n\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n redirect_uri: redirectUri,\n client_id: config.publishableKey\n });\n body.set(\"code_verifier\", verifier);\n\n const response = await fetch(`${authBase}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body\n });\n\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; error_description?: string };\n throw new SmartHiveAuthError(err.error ?? \"token_error\", err.error_description ?? \"Token exchange failed.\");\n }\n\n const tokenBody = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n token_type?: string;\n };\n\n const session: AuthSession = {\n accessToken: tokenBody.access_token,\n refreshToken: tokenBody.refresh_token,\n expiresAt: tokenBody.expires_in ? Date.now() + tokenBody.expires_in * 1000 : undefined\n };\n\n await saveSession(session);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceVerifier);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceState);\n\n return session;\n },\n\n async logout() {\n await saveSession(null);\n await fetch(`${baseUrl}/api/auth/sign-out`, { method: \"POST\", credentials: \"include\" });\n },\n\n getSession: readSession,\n\n async getAccessToken() {\n const session = await readSession();\n if (!session) return null;\n if (session.expiresAt && Date.now() > session.expiresAt - 30000) {\n return (await client.refreshSession())?.accessToken ?? null;\n }\n return session.accessToken;\n },\n\n async getAuthorizationHeader() {\n const token = await client.getAccessToken();\n const headers: Record<string, string> = {};\n if (token) headers.authorization = `Bearer ${token}`;\n return headers;\n },\n\n async fetch(input, init = {}) {\n const authHeader = await client.getAuthorizationHeader();\n const headers = new Headers(init.headers);\n for (const [key, value] of Object.entries(authHeader)) {\n headers.set(key, value);\n }\n return fetch(input, { ...init, headers });\n },\n\n async refreshSession() {\n const session = await readSession();\n if (!session?.refreshToken) return session;\n const response = await fetch(`${baseUrl}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: session.refreshToken\n })\n });\n if (!response.ok) { await saveSession(null); return null; }\n const body = await response.json() as { access_token: string; refresh_token?: string; expires_in?: number };\n const nextSession: AuthSession = {\n ...session,\n accessToken: body.access_token,\n refreshToken: body.refresh_token ?? session.refreshToken,\n expiresAt: body.expires_in ? Date.now() + body.expires_in * 1000 : session.expiresAt\n };\n await saveSession(nextSession);\n return nextSession;\n },\n\n async verifyToken(token) {\n if (token.split(\".\").length !== 3) return false;\n const response = await fetch(`${authBase}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n return response.ok;\n },\n\n async getUser() {\n const token = await client.getAccessToken();\n if (!token) return null;\n const response = await fetch(`${baseUrl}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n return response.ok ? response.json() : null;\n },\n\n headless,\n };\n\n return client;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export interface SmartHiveAuthConfig {\n projectId: string;\n publishableKey: string;\n baseUrl: string;\n /** Custom branded auth domain, e.g. \"https://auth.myapp.com\". Used as the entry point for login/token flows. Falls back to baseUrl. */\n authDomain?: string;\n /** Fallback auth domain if authDomain is unreachable, e.g. \"https://auth.smarthivelabs.dev\". */\n fallbackAuthDomain?: string;\n redirectUri?: string;\n storage?: AuthStorage;\n temporaryStorage?: AuthStorage;\n /**\n * URL of your own backend's social auth proxy (e.g. \"https://api.myapp.com\").\n * When set, social OAuth initiations route through your domain so Google/Apple\n * consent screens show your domain instead of SmartHive's.\n * Your backend must implement GET /api/auth/social/:provider and\n * GET /api/auth/social/:provider/callback.\n */\n socialProxyUrl?: string;\n}\n\nexport interface AuthStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\nexport interface AuthSession {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n user?: unknown;\n}\n\n// ── Headless types ────────────────────────────────────────────────────────────\n\nexport interface HeadlessSignInResult {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n user?: unknown;\n}\n\nexport interface HeadlessSignUpResult extends HeadlessSignInResult {\n /** True when email verification is required before the account can be used. */\n requiresVerification?: boolean;\n}\n\nexport interface HeadlessClient {\n signIn: {\n /**\n * Sign in with email and password. No browser redirect.\n * Returns tokens immediately on success.\n */\n email(params: { email: string; password: string }): Promise<HeadlessSignInResult>;\n\n phone: {\n /**\n * Send a one-time code to a phone number.\n * Call `verify` with the code the user receives.\n */\n sendOtp(params: { phoneNumber: string }): Promise<void>;\n /**\n * Verify the OTP sent to the phone number and return tokens on success.\n */\n verify(params: { phoneNumber: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n emailOtp: {\n /**\n * Send a one-time code to an email address.\n * Call `verify` with the code the user receives.\n */\n send(params: { email: string }): Promise<void>;\n /**\n * Verify the OTP sent to the email address and return tokens on success.\n */\n verify(params: { email: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n magicLink: {\n /**\n * Send a magic link to the given email address.\n * The user clicks the link — no token is returned here.\n */\n send(params: { email: string; callbackURL?: string }): Promise<void>;\n };\n };\n\n signUp: {\n /**\n * Create a new account with email and password. No browser redirect.\n * If email verification is required, `requiresVerification` will be true\n * and no tokens will be present — the user must verify before signing in.\n */\n email(params: { email: string; password: string; name?: string }): Promise<HeadlessSignUpResult>;\n };\n\n /** Refresh an expired access token using the refresh token. */\n refreshToken(params: { refreshToken: string }): Promise<{ accessToken: string; expiresAt: number }>;\n\n /** Sign the user out and invalidate their session on the server. */\n signOut(params?: { refreshToken?: string }): Promise<void>;\n}\n\nexport interface SmartHiveAuthClient {\n initialize(): Promise<void>;\n login(options?: { redirectUri?: string; state?: string }): Promise<void>;\n handleCallback(options?: { url?: string }): Promise<AuthSession>;\n /**\n * Initiate a social OAuth flow. Redirects the browser (or opens Linking URL\n * on mobile) to the provider's consent screen using the project's own credentials.\n * After the user approves, the provider redirects back with tokens in the redirect URI.\n */\n loginSocial(provider: SocialProvider, options?: { redirectUri?: string }): Promise<void>;\n /**\n * Parse social OAuth callback URL (contains access_token + refresh_token as query params),\n * persist the session, and return it. Call this when the app handles the redirect back from\n * the social flow (e.g. on the callback page, or in a deep link handler on mobile).\n */\n handleSocialCallback(options?: { url?: string }): Promise<AuthSession>;\n logout(): Promise<void>;\n getSession(): Promise<AuthSession | null>;\n getAccessToken(): Promise<string | null>;\n getAuthorizationHeader(): Promise<Record<string, string>>;\n fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;\n refreshSession(): Promise<AuthSession | null>;\n verifyToken(token: string): Promise<boolean>;\n getUser(): Promise<unknown>;\n /**\n * Direct credential-based authentication — no browser redirect.\n * Use these methods when you want full control of the sign-in UI\n * (e.g. native mobile apps with custom login screens).\n */\n headless: HeadlessClient;\n}\n\nexport type SocialProvider =\n | \"google\"\n | \"apple\"\n | \"github\"\n | \"facebook\"\n | \"twitter\"\n | \"linkedin\"\n | \"microsoft\"\n | \"discord\"\n | \"spotify\"\n | \"twitch\"\n | \"reddit\"\n | \"gitlab\"\n | \"slack\"\n | \"notion\"\n | \"zoom\"\n | \"figma\";\n\nexport class SmartHiveAuthError extends Error {\n constructor(public code: string, message: string) {\n super(message);\n this.name = \"SmartHiveAuthError\";\n }\n}\n\n// ── PKCE helpers (Web Crypto — works in browser + Node 18+) ──────────────────\n\nexport async function generateCodeVerifier(): Promise<string> {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return base64urlEncode(array);\n}\n\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\n return base64urlEncode(new Uint8Array(digest));\n}\n\nfunction base64urlEncode(buffer: Uint8Array): string {\n let str = \"\";\n for (const byte of buffer) str += String.fromCharCode(byte);\n return btoa(str).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n// ── Storage keys ─────────────────────────────────────────────────────────────\n\nexport const smartHiveAuthStorageKeys = {\n session: \"smarthive.auth.session\",\n pkceVerifier: \"smarthive.auth.pkce_verifier\",\n pkceState: \"smarthive.auth.pkce_state\"\n} as const;\n\nfunction browserStorage(): AuthStorage {\n return {\n getItem: (key) => globalThis.localStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.localStorage?.setItem(key, value),\n removeItem: (key) => globalThis.localStorage?.removeItem(key)\n };\n}\n\nfunction sessionStorageAdapter(): Pick<AuthStorage, \"getItem\" | \"setItem\" | \"removeItem\"> {\n return {\n getItem: (key) => globalThis.sessionStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.sessionStorage?.setItem(key, value),\n removeItem: (key) => globalThis.sessionStorage?.removeItem(key)\n };\n}\n\nfunction normalizeBaseUrl(baseUrl: string) {\n return baseUrl.replace(/\\/$/, \"\");\n}\n\n/** Extract the environment prefix from a publishable key (pk_dev_*, pk_staging_*, pk_prod_*). */\nexport function envFromPublishableKey(publishableKey: string): string {\n const match = publishableKey.match(/^pk_(dev|staging|prod)_/);\n return match ? match[1] : \"prod\";\n}\n\n// ── Headless response shape from the backend ──────────────────────────────────\n\ninterface RawHeadlessResponse {\n access_token: string;\n refresh_token: string;\n expires_in: number;\n token_type: string;\n user?: unknown;\n requires_verification?: boolean;\n message?: string;\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\nexport function initAuth(config: SmartHiveAuthConfig): SmartHiveAuthClient {\n const baseUrl = normalizeBaseUrl(config.baseUrl);\n const authBase = normalizeBaseUrl(config.authDomain ?? config.baseUrl);\n const storage = config.storage ?? browserStorage();\n const tempStorage = config.temporaryStorage ?? sessionStorageAdapter();\n const environment = envFromPublishableKey(config.publishableKey);\n const headlessBase = `${baseUrl}/${environment}/api/auth/headless`;\n\n async function saveSession(session: AuthSession | null) {\n if (!session) { await storage.removeItem(smartHiveAuthStorageKeys.session); return; }\n await storage.setItem(smartHiveAuthStorageKeys.session, JSON.stringify(session));\n }\n\n async function readSession(): Promise<AuthSession | null> {\n const raw = await storage.getItem(smartHiveAuthStorageKeys.session);\n return raw ? JSON.parse(raw) as AuthSession : null;\n }\n\n function rawToSession(raw: RawHeadlessResponse): HeadlessSignInResult {\n return {\n accessToken: raw.access_token,\n refreshToken: raw.refresh_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n user: raw.user,\n };\n }\n\n async function headlessPost(path: string, body: Record<string, unknown>): Promise<RawHeadlessResponse> {\n const res = await fetch(`${headlessBase}${path}`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(\n err.error ?? \"request_failed\",\n err.message ?? `Request to ${path} failed.`\n );\n }\n\n return res.json() as Promise<RawHeadlessResponse>;\n }\n\n async function headlessSignInAndSave(path: string, body: Record<string, unknown>): Promise<HeadlessSignInResult> {\n const raw = await headlessPost(path, body);\n const result = rawToSession(raw);\n await saveSession(result);\n return result;\n }\n\n const headless: HeadlessClient = {\n signIn: {\n async email({ email, password }) {\n return headlessSignInAndSave(\"/sign-in/email\", { email, password });\n },\n\n phone: {\n async sendOtp({ phoneNumber }) {\n await headlessPost(\"/phone/send-otp\", { phoneNumber });\n },\n async verify({ phoneNumber, code }) {\n return headlessSignInAndSave(\"/phone/verify\", { phoneNumber, code });\n },\n },\n\n emailOtp: {\n async send({ email }) {\n await headlessPost(\"/email-otp/send\", { email });\n },\n async verify({ email, code }) {\n return headlessSignInAndSave(\"/email-otp/verify\", { email, code });\n },\n },\n\n magicLink: {\n async send({ email, callbackURL }) {\n await headlessPost(\"/magic-link/send\", { email, ...(callbackURL ? { callbackURL } : {}) });\n },\n },\n },\n\n signUp: {\n async email({ email, password, name }) {\n const res = await fetch(`${headlessBase}/sign-up/email`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ email, password, name }),\n });\n\n // 202 = account created but email verification required\n if (res.status === 202) {\n return { accessToken: \"\", refreshToken: \"\", expiresAt: 0, requiresVerification: true };\n }\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(err.error ?? \"sign_up_failed\", err.message ?? \"Sign up failed.\");\n }\n\n const raw = await res.json() as RawHeadlessResponse;\n const result: HeadlessSignUpResult = { ...rawToSession(raw), requiresVerification: false };\n await saveSession(result);\n return result;\n },\n },\n\n async refreshToken({ refreshToken }) {\n const raw = await headlessPost(\"/token/refresh\", { refresh_token: refreshToken });\n const updated: AuthSession = {\n ...(await readSession() ?? {}),\n accessToken: raw.access_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n };\n await saveSession(updated);\n return { accessToken: raw.access_token, expiresAt: updated.expiresAt! };\n },\n\n async signOut({ refreshToken } = {}) {\n const session = await readSession();\n const token = refreshToken ?? session?.refreshToken;\n await saveSession(null);\n if (token) {\n await fetch(`${headlessBase}/sign-out`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ refresh_token: token }),\n }).catch(() => {});\n }\n },\n };\n\n const client: SmartHiveAuthClient = {\n async initialize() {\n const response = await fetch(\n `${baseUrl}/sdk/config?projectId=${encodeURIComponent(config.projectId)}&publishableKey=${encodeURIComponent(config.publishableKey)}`\n );\n if (!response.ok) throw new SmartHiveAuthError(\"project_not_found\", \"Smart Hive Auth project configuration was not found.\");\n },\n\n async login(options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;\n const state = options?.state ?? crypto.randomUUID();\n const verifier = await generateCodeVerifier();\n const challenge = await generateCodeChallenge(verifier);\n\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceVerifier, verifier);\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceState, state);\n\n const url = new URL(`${authBase}/api/auth/oauth2/authorize`);\n url.searchParams.set(\"project_id\", config.projectId);\n url.searchParams.set(\"publishable_key\", config.publishableKey);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"redirect_uri\", redirectUri);\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge\", challenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n\n globalThis.location.assign(url.toString());\n },\n\n async handleCallback(options) {\n const href = options?.url ?? globalThis.location?.href;\n if (!href) throw new SmartHiveAuthError(\"callback_failed\", \"No URL provided for callback handling.\");\n\n const url = new URL(href);\n const code = url.searchParams.get(\"code\");\n const returnedState = url.searchParams.get(\"state\");\n\n if (!code) throw new SmartHiveAuthError(\"callback_failed\", \"No authorization code in callback URL.\");\n\n const storedState = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceState);\n if (!storedState || !returnedState || storedState !== returnedState) {\n throw new SmartHiveAuthError(\"state_mismatch\", \"OAuth state mismatch — possible CSRF attack.\");\n }\n\n const verifier = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceVerifier);\n if (!verifier) {\n throw new SmartHiveAuthError(\"pkce_missing\", \"Missing PKCE verifier for authorization code exchange.\");\n }\n const redirectUri = config.redirectUri ?? (url.origin + url.pathname);\n\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n redirect_uri: redirectUri,\n client_id: config.publishableKey\n });\n body.set(\"code_verifier\", verifier);\n\n const response = await fetch(`${authBase}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body\n });\n\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; error_description?: string };\n throw new SmartHiveAuthError(err.error ?? \"token_error\", err.error_description ?? \"Token exchange failed.\");\n }\n\n const tokenBody = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n token_type?: string;\n };\n\n const session: AuthSession = {\n accessToken: tokenBody.access_token,\n refreshToken: tokenBody.refresh_token,\n expiresAt: tokenBody.expires_in ? Date.now() + tokenBody.expires_in * 1000 : undefined\n };\n\n await saveSession(session);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceVerifier);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceState);\n\n return session;\n },\n\n async loginSocial(provider, options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;\n if (!redirectUri) throw new SmartHiveAuthError(\"missing_redirect_uri\", \"redirectUri is required for social login.\");\n let url: URL;\n if (config.socialProxyUrl) {\n // Route through the app's own backend proxy — provider shows app's domain\n url = new URL(`${normalizeBaseUrl(config.socialProxyUrl)}/api/auth/social/${provider}`);\n url.searchParams.set(\"redirect_uri\", redirectUri);\n // project_id is injected server-side by the backend proxy\n } else {\n url = new URL(`${authBase}/${environment}/api/auth/social/${provider}`);\n url.searchParams.set(\"project_id\", config.projectId);\n url.searchParams.set(\"redirect_uri\", redirectUri);\n }\n globalThis.location.assign(url.toString());\n },\n\n async handleSocialCallback(options) {\n const href = options?.url ?? globalThis.location?.href;\n if (!href) throw new SmartHiveAuthError(\"callback_failed\", \"No URL available for social callback.\");\n const url = new URL(href);\n const error = url.searchParams.get(\"error\");\n if (error) {\n throw new SmartHiveAuthError(error, url.searchParams.get(\"error_description\") ?? error);\n }\n const accessToken = url.searchParams.get(\"access_token\");\n if (!accessToken) throw new SmartHiveAuthError(\"callback_failed\", \"No access token in social callback URL.\");\n const expiresIn = url.searchParams.get(\"expires_in\");\n const session: AuthSession = {\n accessToken,\n refreshToken: url.searchParams.get(\"refresh_token\") ?? undefined,\n expiresAt: expiresIn ? Date.now() + parseInt(expiresIn, 10) * 1000 : undefined,\n };\n await saveSession(session);\n return session;\n },\n\n async logout() {\n await saveSession(null);\n await fetch(`${baseUrl}/api/auth/sign-out`, { method: \"POST\", credentials: \"include\" });\n },\n\n getSession: readSession,\n\n async getAccessToken() {\n const session = await readSession();\n if (!session) return null;\n if (session.expiresAt && Date.now() > session.expiresAt - 30000) {\n return (await client.refreshSession())?.accessToken ?? null;\n }\n return session.accessToken;\n },\n\n async getAuthorizationHeader() {\n const token = await client.getAccessToken();\n const headers: Record<string, string> = {};\n if (token) headers.authorization = `Bearer ${token}`;\n return headers;\n },\n\n async fetch(input, init = {}) {\n const authHeader = await client.getAuthorizationHeader();\n const headers = new Headers(init.headers);\n for (const [key, value] of Object.entries(authHeader)) {\n headers.set(key, value);\n }\n return fetch(input, { ...init, headers });\n },\n\n async refreshSession() {\n const session = await readSession();\n if (!session?.refreshToken) return session;\n const response = await fetch(`${baseUrl}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: session.refreshToken\n })\n });\n if (!response.ok) { await saveSession(null); return null; }\n const body = await response.json() as { access_token: string; refresh_token?: string; expires_in?: number };\n const nextSession: AuthSession = {\n ...session,\n accessToken: body.access_token,\n refreshToken: body.refresh_token ?? session.refreshToken,\n expiresAt: body.expires_in ? Date.now() + body.expires_in * 1000 : session.expiresAt\n };\n await saveSession(nextSession);\n return nextSession;\n },\n\n async verifyToken(token) {\n if (token.split(\".\").length !== 3) return false;\n const response = await fetch(`${authBase}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n return response.ok;\n },\n\n async getUser() {\n const token = await client.getAccessToken();\n if (!token) return null;\n const response = await fetch(`${baseUrl}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n return response.ok ? response.json() : null;\n },\n\n headless,\n };\n\n return client;\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -9,6 +9,14 @@ interface SmartHiveAuthConfig {
9
9
  redirectUri?: string;
10
10
  storage?: AuthStorage;
11
11
  temporaryStorage?: AuthStorage;
12
+ /**
13
+ * URL of your own backend's social auth proxy (e.g. "https://api.myapp.com").
14
+ * When set, social OAuth initiations route through your domain so Google/Apple
15
+ * consent screens show your domain instead of SmartHive's.
16
+ * Your backend must implement GET /api/auth/social/:provider and
17
+ * GET /api/auth/social/:provider/callback.
18
+ */
19
+ socialProxyUrl?: string;
12
20
  }
13
21
  interface AuthStorage {
14
22
  getItem(key: string): string | null | Promise<string | null>;
@@ -117,6 +125,22 @@ interface SmartHiveAuthClient {
117
125
  handleCallback(options?: {
118
126
  url?: string;
119
127
  }): Promise<AuthSession>;
128
+ /**
129
+ * Initiate a social OAuth flow. Redirects the browser (or opens Linking URL
130
+ * on mobile) to the provider's consent screen using the project's own credentials.
131
+ * After the user approves, the provider redirects back with tokens in the redirect URI.
132
+ */
133
+ loginSocial(provider: SocialProvider, options?: {
134
+ redirectUri?: string;
135
+ }): Promise<void>;
136
+ /**
137
+ * Parse social OAuth callback URL (contains access_token + refresh_token as query params),
138
+ * persist the session, and return it. Call this when the app handles the redirect back from
139
+ * the social flow (e.g. on the callback page, or in a deep link handler on mobile).
140
+ */
141
+ handleSocialCallback(options?: {
142
+ url?: string;
143
+ }): Promise<AuthSession>;
120
144
  logout(): Promise<void>;
121
145
  getSession(): Promise<AuthSession | null>;
122
146
  getAccessToken(): Promise<string | null>;
@@ -132,6 +156,7 @@ interface SmartHiveAuthClient {
132
156
  */
133
157
  headless: HeadlessClient;
134
158
  }
159
+ type SocialProvider = "google" | "apple" | "github" | "facebook" | "twitter" | "linkedin" | "microsoft" | "discord" | "spotify" | "twitch" | "reddit" | "gitlab" | "slack" | "notion" | "zoom" | "figma";
135
160
  declare class SmartHiveAuthError extends Error {
136
161
  code: string;
137
162
  constructor(code: string, message: string);
@@ -143,6 +168,8 @@ declare const smartHiveAuthStorageKeys: {
143
168
  readonly pkceVerifier: "smarthive.auth.pkce_verifier";
144
169
  readonly pkceState: "smarthive.auth.pkce_state";
145
170
  };
171
+ /** Extract the environment prefix from a publishable key (pk_dev_*, pk_staging_*, pk_prod_*). */
172
+ declare function envFromPublishableKey(publishableKey: string): string;
146
173
  declare function initAuth(config: SmartHiveAuthConfig): SmartHiveAuthClient;
147
174
 
148
- export { type AuthSession, type AuthStorage, type HeadlessClient, type HeadlessSignInResult, type HeadlessSignUpResult, type SmartHiveAuthClient, type SmartHiveAuthConfig, SmartHiveAuthError, generateCodeChallenge, generateCodeVerifier, initAuth, smartHiveAuthStorageKeys };
175
+ export { type AuthSession, type AuthStorage, type HeadlessClient, type HeadlessSignInResult, type HeadlessSignUpResult, type SmartHiveAuthClient, type SmartHiveAuthConfig, SmartHiveAuthError, type SocialProvider, envFromPublishableKey, generateCodeChallenge, generateCodeVerifier, initAuth, smartHiveAuthStorageKeys };
package/dist/index.d.ts CHANGED
@@ -9,6 +9,14 @@ interface SmartHiveAuthConfig {
9
9
  redirectUri?: string;
10
10
  storage?: AuthStorage;
11
11
  temporaryStorage?: AuthStorage;
12
+ /**
13
+ * URL of your own backend's social auth proxy (e.g. "https://api.myapp.com").
14
+ * When set, social OAuth initiations route through your domain so Google/Apple
15
+ * consent screens show your domain instead of SmartHive's.
16
+ * Your backend must implement GET /api/auth/social/:provider and
17
+ * GET /api/auth/social/:provider/callback.
18
+ */
19
+ socialProxyUrl?: string;
12
20
  }
13
21
  interface AuthStorage {
14
22
  getItem(key: string): string | null | Promise<string | null>;
@@ -117,6 +125,22 @@ interface SmartHiveAuthClient {
117
125
  handleCallback(options?: {
118
126
  url?: string;
119
127
  }): Promise<AuthSession>;
128
+ /**
129
+ * Initiate a social OAuth flow. Redirects the browser (or opens Linking URL
130
+ * on mobile) to the provider's consent screen using the project's own credentials.
131
+ * After the user approves, the provider redirects back with tokens in the redirect URI.
132
+ */
133
+ loginSocial(provider: SocialProvider, options?: {
134
+ redirectUri?: string;
135
+ }): Promise<void>;
136
+ /**
137
+ * Parse social OAuth callback URL (contains access_token + refresh_token as query params),
138
+ * persist the session, and return it. Call this when the app handles the redirect back from
139
+ * the social flow (e.g. on the callback page, or in a deep link handler on mobile).
140
+ */
141
+ handleSocialCallback(options?: {
142
+ url?: string;
143
+ }): Promise<AuthSession>;
120
144
  logout(): Promise<void>;
121
145
  getSession(): Promise<AuthSession | null>;
122
146
  getAccessToken(): Promise<string | null>;
@@ -132,6 +156,7 @@ interface SmartHiveAuthClient {
132
156
  */
133
157
  headless: HeadlessClient;
134
158
  }
159
+ type SocialProvider = "google" | "apple" | "github" | "facebook" | "twitter" | "linkedin" | "microsoft" | "discord" | "spotify" | "twitch" | "reddit" | "gitlab" | "slack" | "notion" | "zoom" | "figma";
135
160
  declare class SmartHiveAuthError extends Error {
136
161
  code: string;
137
162
  constructor(code: string, message: string);
@@ -143,6 +168,8 @@ declare const smartHiveAuthStorageKeys: {
143
168
  readonly pkceVerifier: "smarthive.auth.pkce_verifier";
144
169
  readonly pkceState: "smarthive.auth.pkce_state";
145
170
  };
171
+ /** Extract the environment prefix from a publishable key (pk_dev_*, pk_staging_*, pk_prod_*). */
172
+ declare function envFromPublishableKey(publishableKey: string): string;
146
173
  declare function initAuth(config: SmartHiveAuthConfig): SmartHiveAuthClient;
147
174
 
148
- export { type AuthSession, type AuthStorage, type HeadlessClient, type HeadlessSignInResult, type HeadlessSignUpResult, type SmartHiveAuthClient, type SmartHiveAuthConfig, SmartHiveAuthError, generateCodeChallenge, generateCodeVerifier, initAuth, smartHiveAuthStorageKeys };
175
+ export { type AuthSession, type AuthStorage, type HeadlessClient, type HeadlessSignInResult, type HeadlessSignUpResult, type SmartHiveAuthClient, type SmartHiveAuthConfig, SmartHiveAuthError, type SocialProvider, envFromPublishableKey, generateCodeChallenge, generateCodeVerifier, initAuth, smartHiveAuthStorageKeys };
package/dist/index.js CHANGED
@@ -234,6 +234,39 @@ function initAuth(config) {
234
234
  await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceState);
235
235
  return session;
236
236
  },
237
+ async loginSocial(provider, options) {
238
+ const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;
239
+ if (!redirectUri) throw new SmartHiveAuthError("missing_redirect_uri", "redirectUri is required for social login.");
240
+ let url;
241
+ if (config.socialProxyUrl) {
242
+ url = new URL(`${normalizeBaseUrl(config.socialProxyUrl)}/api/auth/social/${provider}`);
243
+ url.searchParams.set("redirect_uri", redirectUri);
244
+ } else {
245
+ url = new URL(`${authBase}/${environment}/api/auth/social/${provider}`);
246
+ url.searchParams.set("project_id", config.projectId);
247
+ url.searchParams.set("redirect_uri", redirectUri);
248
+ }
249
+ globalThis.location.assign(url.toString());
250
+ },
251
+ async handleSocialCallback(options) {
252
+ const href = options?.url ?? globalThis.location?.href;
253
+ if (!href) throw new SmartHiveAuthError("callback_failed", "No URL available for social callback.");
254
+ const url = new URL(href);
255
+ const error = url.searchParams.get("error");
256
+ if (error) {
257
+ throw new SmartHiveAuthError(error, url.searchParams.get("error_description") ?? error);
258
+ }
259
+ const accessToken = url.searchParams.get("access_token");
260
+ if (!accessToken) throw new SmartHiveAuthError("callback_failed", "No access token in social callback URL.");
261
+ const expiresIn = url.searchParams.get("expires_in");
262
+ const session = {
263
+ accessToken,
264
+ refreshToken: url.searchParams.get("refresh_token") ?? void 0,
265
+ expiresAt: expiresIn ? Date.now() + parseInt(expiresIn, 10) * 1e3 : void 0
266
+ };
267
+ await saveSession(session);
268
+ return session;
269
+ },
237
270
  async logout() {
238
271
  await saveSession(null);
239
272
  await fetch(`${baseUrl}/api/auth/sign-out`, { method: "POST", credentials: "include" });
@@ -307,6 +340,7 @@ function initAuth(config) {
307
340
  }
308
341
  export {
309
342
  SmartHiveAuthError,
343
+ envFromPublishableKey,
310
344
  generateCodeChallenge,
311
345
  generateCodeVerifier,
312
346
  initAuth,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export interface SmartHiveAuthConfig {\n projectId: string;\n publishableKey: string;\n baseUrl: string;\n /** Custom branded auth domain, e.g. \"https://auth.myapp.com\". Used as the entry point for login/token flows. Falls back to baseUrl. */\n authDomain?: string;\n /** Fallback auth domain if authDomain is unreachable, e.g. \"https://auth.smarthivelabs.dev\". */\n fallbackAuthDomain?: string;\n redirectUri?: string;\n storage?: AuthStorage;\n temporaryStorage?: AuthStorage;\n}\n\nexport interface AuthStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\nexport interface AuthSession {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n user?: unknown;\n}\n\n// ── Headless types ────────────────────────────────────────────────────────────\n\nexport interface HeadlessSignInResult {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n user?: unknown;\n}\n\nexport interface HeadlessSignUpResult extends HeadlessSignInResult {\n /** True when email verification is required before the account can be used. */\n requiresVerification?: boolean;\n}\n\nexport interface HeadlessClient {\n signIn: {\n /**\n * Sign in with email and password. No browser redirect.\n * Returns tokens immediately on success.\n */\n email(params: { email: string; password: string }): Promise<HeadlessSignInResult>;\n\n phone: {\n /**\n * Send a one-time code to a phone number.\n * Call `verify` with the code the user receives.\n */\n sendOtp(params: { phoneNumber: string }): Promise<void>;\n /**\n * Verify the OTP sent to the phone number and return tokens on success.\n */\n verify(params: { phoneNumber: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n emailOtp: {\n /**\n * Send a one-time code to an email address.\n * Call `verify` with the code the user receives.\n */\n send(params: { email: string }): Promise<void>;\n /**\n * Verify the OTP sent to the email address and return tokens on success.\n */\n verify(params: { email: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n magicLink: {\n /**\n * Send a magic link to the given email address.\n * The user clicks the link — no token is returned here.\n */\n send(params: { email: string; callbackURL?: string }): Promise<void>;\n };\n };\n\n signUp: {\n /**\n * Create a new account with email and password. No browser redirect.\n * If email verification is required, `requiresVerification` will be true\n * and no tokens will be present — the user must verify before signing in.\n */\n email(params: { email: string; password: string; name?: string }): Promise<HeadlessSignUpResult>;\n };\n\n /** Refresh an expired access token using the refresh token. */\n refreshToken(params: { refreshToken: string }): Promise<{ accessToken: string; expiresAt: number }>;\n\n /** Sign the user out and invalidate their session on the server. */\n signOut(params?: { refreshToken?: string }): Promise<void>;\n}\n\nexport interface SmartHiveAuthClient {\n initialize(): Promise<void>;\n login(options?: { redirectUri?: string; state?: string }): Promise<void>;\n handleCallback(options?: { url?: string }): Promise<AuthSession>;\n logout(): Promise<void>;\n getSession(): Promise<AuthSession | null>;\n getAccessToken(): Promise<string | null>;\n getAuthorizationHeader(): Promise<Record<string, string>>;\n fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;\n refreshSession(): Promise<AuthSession | null>;\n verifyToken(token: string): Promise<boolean>;\n getUser(): Promise<unknown>;\n /**\n * Direct credential-based authentication — no browser redirect.\n * Use these methods when you want full control of the sign-in UI\n * (e.g. native mobile apps with custom login screens).\n */\n headless: HeadlessClient;\n}\n\nexport class SmartHiveAuthError extends Error {\n constructor(public code: string, message: string) {\n super(message);\n this.name = \"SmartHiveAuthError\";\n }\n}\n\n// ── PKCE helpers (Web Crypto — works in browser + Node 18+) ──────────────────\n\nexport async function generateCodeVerifier(): Promise<string> {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return base64urlEncode(array);\n}\n\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\n return base64urlEncode(new Uint8Array(digest));\n}\n\nfunction base64urlEncode(buffer: Uint8Array): string {\n let str = \"\";\n for (const byte of buffer) str += String.fromCharCode(byte);\n return btoa(str).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n// ── Storage keys ─────────────────────────────────────────────────────────────\n\nexport const smartHiveAuthStorageKeys = {\n session: \"smarthive.auth.session\",\n pkceVerifier: \"smarthive.auth.pkce_verifier\",\n pkceState: \"smarthive.auth.pkce_state\"\n} as const;\n\nfunction browserStorage(): AuthStorage {\n return {\n getItem: (key) => globalThis.localStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.localStorage?.setItem(key, value),\n removeItem: (key) => globalThis.localStorage?.removeItem(key)\n };\n}\n\nfunction sessionStorageAdapter(): Pick<AuthStorage, \"getItem\" | \"setItem\" | \"removeItem\"> {\n return {\n getItem: (key) => globalThis.sessionStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.sessionStorage?.setItem(key, value),\n removeItem: (key) => globalThis.sessionStorage?.removeItem(key)\n };\n}\n\nfunction normalizeBaseUrl(baseUrl: string) {\n return baseUrl.replace(/\\/$/, \"\");\n}\n\n/** Extract the environment prefix from a publishable key (pk_dev_*, pk_staging_*, pk_prod_*). */\nfunction envFromPublishableKey(publishableKey: string): string {\n const match = publishableKey.match(/^pk_(dev|staging|prod)_/);\n return match ? match[1] : \"prod\";\n}\n\n// ── Headless response shape from the backend ──────────────────────────────────\n\ninterface RawHeadlessResponse {\n access_token: string;\n refresh_token: string;\n expires_in: number;\n token_type: string;\n user?: unknown;\n requires_verification?: boolean;\n message?: string;\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\nexport function initAuth(config: SmartHiveAuthConfig): SmartHiveAuthClient {\n const baseUrl = normalizeBaseUrl(config.baseUrl);\n const authBase = normalizeBaseUrl(config.authDomain ?? config.baseUrl);\n const storage = config.storage ?? browserStorage();\n const tempStorage = config.temporaryStorage ?? sessionStorageAdapter();\n const environment = envFromPublishableKey(config.publishableKey);\n const headlessBase = `${baseUrl}/${environment}/api/auth/headless`;\n\n async function saveSession(session: AuthSession | null) {\n if (!session) { await storage.removeItem(smartHiveAuthStorageKeys.session); return; }\n await storage.setItem(smartHiveAuthStorageKeys.session, JSON.stringify(session));\n }\n\n async function readSession(): Promise<AuthSession | null> {\n const raw = await storage.getItem(smartHiveAuthStorageKeys.session);\n return raw ? JSON.parse(raw) as AuthSession : null;\n }\n\n function rawToSession(raw: RawHeadlessResponse): HeadlessSignInResult {\n return {\n accessToken: raw.access_token,\n refreshToken: raw.refresh_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n user: raw.user,\n };\n }\n\n async function headlessPost(path: string, body: Record<string, unknown>): Promise<RawHeadlessResponse> {\n const res = await fetch(`${headlessBase}${path}`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(\n err.error ?? \"request_failed\",\n err.message ?? `Request to ${path} failed.`\n );\n }\n\n return res.json() as Promise<RawHeadlessResponse>;\n }\n\n async function headlessSignInAndSave(path: string, body: Record<string, unknown>): Promise<HeadlessSignInResult> {\n const raw = await headlessPost(path, body);\n const result = rawToSession(raw);\n await saveSession(result);\n return result;\n }\n\n const headless: HeadlessClient = {\n signIn: {\n async email({ email, password }) {\n return headlessSignInAndSave(\"/sign-in/email\", { email, password });\n },\n\n phone: {\n async sendOtp({ phoneNumber }) {\n await headlessPost(\"/phone/send-otp\", { phoneNumber });\n },\n async verify({ phoneNumber, code }) {\n return headlessSignInAndSave(\"/phone/verify\", { phoneNumber, code });\n },\n },\n\n emailOtp: {\n async send({ email }) {\n await headlessPost(\"/email-otp/send\", { email });\n },\n async verify({ email, code }) {\n return headlessSignInAndSave(\"/email-otp/verify\", { email, code });\n },\n },\n\n magicLink: {\n async send({ email, callbackURL }) {\n await headlessPost(\"/magic-link/send\", { email, ...(callbackURL ? { callbackURL } : {}) });\n },\n },\n },\n\n signUp: {\n async email({ email, password, name }) {\n const res = await fetch(`${headlessBase}/sign-up/email`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ email, password, name }),\n });\n\n // 202 = account created but email verification required\n if (res.status === 202) {\n return { accessToken: \"\", refreshToken: \"\", expiresAt: 0, requiresVerification: true };\n }\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(err.error ?? \"sign_up_failed\", err.message ?? \"Sign up failed.\");\n }\n\n const raw = await res.json() as RawHeadlessResponse;\n const result: HeadlessSignUpResult = { ...rawToSession(raw), requiresVerification: false };\n await saveSession(result);\n return result;\n },\n },\n\n async refreshToken({ refreshToken }) {\n const raw = await headlessPost(\"/token/refresh\", { refresh_token: refreshToken });\n const updated: AuthSession = {\n ...(await readSession() ?? {}),\n accessToken: raw.access_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n };\n await saveSession(updated);\n return { accessToken: raw.access_token, expiresAt: updated.expiresAt! };\n },\n\n async signOut({ refreshToken } = {}) {\n const session = await readSession();\n const token = refreshToken ?? session?.refreshToken;\n await saveSession(null);\n if (token) {\n await fetch(`${headlessBase}/sign-out`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ refresh_token: token }),\n }).catch(() => {});\n }\n },\n };\n\n const client: SmartHiveAuthClient = {\n async initialize() {\n const response = await fetch(\n `${baseUrl}/sdk/config?projectId=${encodeURIComponent(config.projectId)}&publishableKey=${encodeURIComponent(config.publishableKey)}`\n );\n if (!response.ok) throw new SmartHiveAuthError(\"project_not_found\", \"Smart Hive Auth project configuration was not found.\");\n },\n\n async login(options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;\n const state = options?.state ?? crypto.randomUUID();\n const verifier = await generateCodeVerifier();\n const challenge = await generateCodeChallenge(verifier);\n\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceVerifier, verifier);\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceState, state);\n\n const url = new URL(`${authBase}/api/auth/oauth2/authorize`);\n url.searchParams.set(\"project_id\", config.projectId);\n url.searchParams.set(\"publishable_key\", config.publishableKey);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"redirect_uri\", redirectUri);\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge\", challenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n\n globalThis.location.assign(url.toString());\n },\n\n async handleCallback(options) {\n const href = options?.url ?? globalThis.location?.href;\n if (!href) throw new SmartHiveAuthError(\"callback_failed\", \"No URL provided for callback handling.\");\n\n const url = new URL(href);\n const code = url.searchParams.get(\"code\");\n const returnedState = url.searchParams.get(\"state\");\n\n if (!code) throw new SmartHiveAuthError(\"callback_failed\", \"No authorization code in callback URL.\");\n\n const storedState = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceState);\n if (!storedState || !returnedState || storedState !== returnedState) {\n throw new SmartHiveAuthError(\"state_mismatch\", \"OAuth state mismatch — possible CSRF attack.\");\n }\n\n const verifier = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceVerifier);\n if (!verifier) {\n throw new SmartHiveAuthError(\"pkce_missing\", \"Missing PKCE verifier for authorization code exchange.\");\n }\n const redirectUri = config.redirectUri ?? (url.origin + url.pathname);\n\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n redirect_uri: redirectUri,\n client_id: config.publishableKey\n });\n body.set(\"code_verifier\", verifier);\n\n const response = await fetch(`${authBase}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body\n });\n\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; error_description?: string };\n throw new SmartHiveAuthError(err.error ?? \"token_error\", err.error_description ?? \"Token exchange failed.\");\n }\n\n const tokenBody = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n token_type?: string;\n };\n\n const session: AuthSession = {\n accessToken: tokenBody.access_token,\n refreshToken: tokenBody.refresh_token,\n expiresAt: tokenBody.expires_in ? Date.now() + tokenBody.expires_in * 1000 : undefined\n };\n\n await saveSession(session);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceVerifier);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceState);\n\n return session;\n },\n\n async logout() {\n await saveSession(null);\n await fetch(`${baseUrl}/api/auth/sign-out`, { method: \"POST\", credentials: \"include\" });\n },\n\n getSession: readSession,\n\n async getAccessToken() {\n const session = await readSession();\n if (!session) return null;\n if (session.expiresAt && Date.now() > session.expiresAt - 30000) {\n return (await client.refreshSession())?.accessToken ?? null;\n }\n return session.accessToken;\n },\n\n async getAuthorizationHeader() {\n const token = await client.getAccessToken();\n const headers: Record<string, string> = {};\n if (token) headers.authorization = `Bearer ${token}`;\n return headers;\n },\n\n async fetch(input, init = {}) {\n const authHeader = await client.getAuthorizationHeader();\n const headers = new Headers(init.headers);\n for (const [key, value] of Object.entries(authHeader)) {\n headers.set(key, value);\n }\n return fetch(input, { ...init, headers });\n },\n\n async refreshSession() {\n const session = await readSession();\n if (!session?.refreshToken) return session;\n const response = await fetch(`${baseUrl}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: session.refreshToken\n })\n });\n if (!response.ok) { await saveSession(null); return null; }\n const body = await response.json() as { access_token: string; refresh_token?: string; expires_in?: number };\n const nextSession: AuthSession = {\n ...session,\n accessToken: body.access_token,\n refreshToken: body.refresh_token ?? session.refreshToken,\n expiresAt: body.expires_in ? Date.now() + body.expires_in * 1000 : session.expiresAt\n };\n await saveSession(nextSession);\n return nextSession;\n },\n\n async verifyToken(token) {\n if (token.split(\".\").length !== 3) return false;\n const response = await fetch(`${authBase}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n return response.ok;\n },\n\n async getUser() {\n const token = await client.getAccessToken();\n if (!token) return null;\n const response = await fetch(`${baseUrl}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n return response.ok ? response.json() : null;\n },\n\n headless,\n };\n\n return client;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export interface SmartHiveAuthConfig {\n projectId: string;\n publishableKey: string;\n baseUrl: string;\n /** Custom branded auth domain, e.g. \"https://auth.myapp.com\". Used as the entry point for login/token flows. Falls back to baseUrl. */\n authDomain?: string;\n /** Fallback auth domain if authDomain is unreachable, e.g. \"https://auth.smarthivelabs.dev\". */\n fallbackAuthDomain?: string;\n redirectUri?: string;\n storage?: AuthStorage;\n temporaryStorage?: AuthStorage;\n /**\n * URL of your own backend's social auth proxy (e.g. \"https://api.myapp.com\").\n * When set, social OAuth initiations route through your domain so Google/Apple\n * consent screens show your domain instead of SmartHive's.\n * Your backend must implement GET /api/auth/social/:provider and\n * GET /api/auth/social/:provider/callback.\n */\n socialProxyUrl?: string;\n}\n\nexport interface AuthStorage {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<void>;\n removeItem(key: string): void | Promise<void>;\n}\n\nexport interface AuthSession {\n accessToken: string;\n refreshToken?: string;\n expiresAt?: number;\n user?: unknown;\n}\n\n// ── Headless types ────────────────────────────────────────────────────────────\n\nexport interface HeadlessSignInResult {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n user?: unknown;\n}\n\nexport interface HeadlessSignUpResult extends HeadlessSignInResult {\n /** True when email verification is required before the account can be used. */\n requiresVerification?: boolean;\n}\n\nexport interface HeadlessClient {\n signIn: {\n /**\n * Sign in with email and password. No browser redirect.\n * Returns tokens immediately on success.\n */\n email(params: { email: string; password: string }): Promise<HeadlessSignInResult>;\n\n phone: {\n /**\n * Send a one-time code to a phone number.\n * Call `verify` with the code the user receives.\n */\n sendOtp(params: { phoneNumber: string }): Promise<void>;\n /**\n * Verify the OTP sent to the phone number and return tokens on success.\n */\n verify(params: { phoneNumber: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n emailOtp: {\n /**\n * Send a one-time code to an email address.\n * Call `verify` with the code the user receives.\n */\n send(params: { email: string }): Promise<void>;\n /**\n * Verify the OTP sent to the email address and return tokens on success.\n */\n verify(params: { email: string; code: string }): Promise<HeadlessSignInResult>;\n };\n\n magicLink: {\n /**\n * Send a magic link to the given email address.\n * The user clicks the link — no token is returned here.\n */\n send(params: { email: string; callbackURL?: string }): Promise<void>;\n };\n };\n\n signUp: {\n /**\n * Create a new account with email and password. No browser redirect.\n * If email verification is required, `requiresVerification` will be true\n * and no tokens will be present — the user must verify before signing in.\n */\n email(params: { email: string; password: string; name?: string }): Promise<HeadlessSignUpResult>;\n };\n\n /** Refresh an expired access token using the refresh token. */\n refreshToken(params: { refreshToken: string }): Promise<{ accessToken: string; expiresAt: number }>;\n\n /** Sign the user out and invalidate their session on the server. */\n signOut(params?: { refreshToken?: string }): Promise<void>;\n}\n\nexport interface SmartHiveAuthClient {\n initialize(): Promise<void>;\n login(options?: { redirectUri?: string; state?: string }): Promise<void>;\n handleCallback(options?: { url?: string }): Promise<AuthSession>;\n /**\n * Initiate a social OAuth flow. Redirects the browser (or opens Linking URL\n * on mobile) to the provider's consent screen using the project's own credentials.\n * After the user approves, the provider redirects back with tokens in the redirect URI.\n */\n loginSocial(provider: SocialProvider, options?: { redirectUri?: string }): Promise<void>;\n /**\n * Parse social OAuth callback URL (contains access_token + refresh_token as query params),\n * persist the session, and return it. Call this when the app handles the redirect back from\n * the social flow (e.g. on the callback page, or in a deep link handler on mobile).\n */\n handleSocialCallback(options?: { url?: string }): Promise<AuthSession>;\n logout(): Promise<void>;\n getSession(): Promise<AuthSession | null>;\n getAccessToken(): Promise<string | null>;\n getAuthorizationHeader(): Promise<Record<string, string>>;\n fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;\n refreshSession(): Promise<AuthSession | null>;\n verifyToken(token: string): Promise<boolean>;\n getUser(): Promise<unknown>;\n /**\n * Direct credential-based authentication — no browser redirect.\n * Use these methods when you want full control of the sign-in UI\n * (e.g. native mobile apps with custom login screens).\n */\n headless: HeadlessClient;\n}\n\nexport type SocialProvider =\n | \"google\"\n | \"apple\"\n | \"github\"\n | \"facebook\"\n | \"twitter\"\n | \"linkedin\"\n | \"microsoft\"\n | \"discord\"\n | \"spotify\"\n | \"twitch\"\n | \"reddit\"\n | \"gitlab\"\n | \"slack\"\n | \"notion\"\n | \"zoom\"\n | \"figma\";\n\nexport class SmartHiveAuthError extends Error {\n constructor(public code: string, message: string) {\n super(message);\n this.name = \"SmartHiveAuthError\";\n }\n}\n\n// ── PKCE helpers (Web Crypto — works in browser + Node 18+) ──────────────────\n\nexport async function generateCodeVerifier(): Promise<string> {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return base64urlEncode(array);\n}\n\nexport async function generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const digest = await crypto.subtle.digest(\"SHA-256\", data);\n return base64urlEncode(new Uint8Array(digest));\n}\n\nfunction base64urlEncode(buffer: Uint8Array): string {\n let str = \"\";\n for (const byte of buffer) str += String.fromCharCode(byte);\n return btoa(str).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n// ── Storage keys ─────────────────────────────────────────────────────────────\n\nexport const smartHiveAuthStorageKeys = {\n session: \"smarthive.auth.session\",\n pkceVerifier: \"smarthive.auth.pkce_verifier\",\n pkceState: \"smarthive.auth.pkce_state\"\n} as const;\n\nfunction browserStorage(): AuthStorage {\n return {\n getItem: (key) => globalThis.localStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.localStorage?.setItem(key, value),\n removeItem: (key) => globalThis.localStorage?.removeItem(key)\n };\n}\n\nfunction sessionStorageAdapter(): Pick<AuthStorage, \"getItem\" | \"setItem\" | \"removeItem\"> {\n return {\n getItem: (key) => globalThis.sessionStorage?.getItem(key) ?? null,\n setItem: (key, value) => globalThis.sessionStorage?.setItem(key, value),\n removeItem: (key) => globalThis.sessionStorage?.removeItem(key)\n };\n}\n\nfunction normalizeBaseUrl(baseUrl: string) {\n return baseUrl.replace(/\\/$/, \"\");\n}\n\n/** Extract the environment prefix from a publishable key (pk_dev_*, pk_staging_*, pk_prod_*). */\nexport function envFromPublishableKey(publishableKey: string): string {\n const match = publishableKey.match(/^pk_(dev|staging|prod)_/);\n return match ? match[1] : \"prod\";\n}\n\n// ── Headless response shape from the backend ──────────────────────────────────\n\ninterface RawHeadlessResponse {\n access_token: string;\n refresh_token: string;\n expires_in: number;\n token_type: string;\n user?: unknown;\n requires_verification?: boolean;\n message?: string;\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\nexport function initAuth(config: SmartHiveAuthConfig): SmartHiveAuthClient {\n const baseUrl = normalizeBaseUrl(config.baseUrl);\n const authBase = normalizeBaseUrl(config.authDomain ?? config.baseUrl);\n const storage = config.storage ?? browserStorage();\n const tempStorage = config.temporaryStorage ?? sessionStorageAdapter();\n const environment = envFromPublishableKey(config.publishableKey);\n const headlessBase = `${baseUrl}/${environment}/api/auth/headless`;\n\n async function saveSession(session: AuthSession | null) {\n if (!session) { await storage.removeItem(smartHiveAuthStorageKeys.session); return; }\n await storage.setItem(smartHiveAuthStorageKeys.session, JSON.stringify(session));\n }\n\n async function readSession(): Promise<AuthSession | null> {\n const raw = await storage.getItem(smartHiveAuthStorageKeys.session);\n return raw ? JSON.parse(raw) as AuthSession : null;\n }\n\n function rawToSession(raw: RawHeadlessResponse): HeadlessSignInResult {\n return {\n accessToken: raw.access_token,\n refreshToken: raw.refresh_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n user: raw.user,\n };\n }\n\n async function headlessPost(path: string, body: Record<string, unknown>): Promise<RawHeadlessResponse> {\n const res = await fetch(`${headlessBase}${path}`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(\n err.error ?? \"request_failed\",\n err.message ?? `Request to ${path} failed.`\n );\n }\n\n return res.json() as Promise<RawHeadlessResponse>;\n }\n\n async function headlessSignInAndSave(path: string, body: Record<string, unknown>): Promise<HeadlessSignInResult> {\n const raw = await headlessPost(path, body);\n const result = rawToSession(raw);\n await saveSession(result);\n return result;\n }\n\n const headless: HeadlessClient = {\n signIn: {\n async email({ email, password }) {\n return headlessSignInAndSave(\"/sign-in/email\", { email, password });\n },\n\n phone: {\n async sendOtp({ phoneNumber }) {\n await headlessPost(\"/phone/send-otp\", { phoneNumber });\n },\n async verify({ phoneNumber, code }) {\n return headlessSignInAndSave(\"/phone/verify\", { phoneNumber, code });\n },\n },\n\n emailOtp: {\n async send({ email }) {\n await headlessPost(\"/email-otp/send\", { email });\n },\n async verify({ email, code }) {\n return headlessSignInAndSave(\"/email-otp/verify\", { email, code });\n },\n },\n\n magicLink: {\n async send({ email, callbackURL }) {\n await headlessPost(\"/magic-link/send\", { email, ...(callbackURL ? { callbackURL } : {}) });\n },\n },\n },\n\n signUp: {\n async email({ email, password, name }) {\n const res = await fetch(`${headlessBase}/sign-up/email`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ email, password, name }),\n });\n\n // 202 = account created but email verification required\n if (res.status === 202) {\n return { accessToken: \"\", refreshToken: \"\", expiresAt: 0, requiresVerification: true };\n }\n\n if (!res.ok) {\n const err = await res.json().catch(() => ({})) as { error?: string; message?: string };\n throw new SmartHiveAuthError(err.error ?? \"sign_up_failed\", err.message ?? \"Sign up failed.\");\n }\n\n const raw = await res.json() as RawHeadlessResponse;\n const result: HeadlessSignUpResult = { ...rawToSession(raw), requiresVerification: false };\n await saveSession(result);\n return result;\n },\n },\n\n async refreshToken({ refreshToken }) {\n const raw = await headlessPost(\"/token/refresh\", { refresh_token: refreshToken });\n const updated: AuthSession = {\n ...(await readSession() ?? {}),\n accessToken: raw.access_token,\n expiresAt: Date.now() + raw.expires_in * 1000,\n };\n await saveSession(updated);\n return { accessToken: raw.access_token, expiresAt: updated.expiresAt! };\n },\n\n async signOut({ refreshToken } = {}) {\n const session = await readSession();\n const token = refreshToken ?? session?.refreshToken;\n await saveSession(null);\n if (token) {\n await fetch(`${headlessBase}/sign-out`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ refresh_token: token }),\n }).catch(() => {});\n }\n },\n };\n\n const client: SmartHiveAuthClient = {\n async initialize() {\n const response = await fetch(\n `${baseUrl}/sdk/config?projectId=${encodeURIComponent(config.projectId)}&publishableKey=${encodeURIComponent(config.publishableKey)}`\n );\n if (!response.ok) throw new SmartHiveAuthError(\"project_not_found\", \"Smart Hive Auth project configuration was not found.\");\n },\n\n async login(options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;\n const state = options?.state ?? crypto.randomUUID();\n const verifier = await generateCodeVerifier();\n const challenge = await generateCodeChallenge(verifier);\n\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceVerifier, verifier);\n await tempStorage.setItem(smartHiveAuthStorageKeys.pkceState, state);\n\n const url = new URL(`${authBase}/api/auth/oauth2/authorize`);\n url.searchParams.set(\"project_id\", config.projectId);\n url.searchParams.set(\"publishable_key\", config.publishableKey);\n url.searchParams.set(\"response_type\", \"code\");\n url.searchParams.set(\"redirect_uri\", redirectUri);\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge\", challenge);\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n\n globalThis.location.assign(url.toString());\n },\n\n async handleCallback(options) {\n const href = options?.url ?? globalThis.location?.href;\n if (!href) throw new SmartHiveAuthError(\"callback_failed\", \"No URL provided for callback handling.\");\n\n const url = new URL(href);\n const code = url.searchParams.get(\"code\");\n const returnedState = url.searchParams.get(\"state\");\n\n if (!code) throw new SmartHiveAuthError(\"callback_failed\", \"No authorization code in callback URL.\");\n\n const storedState = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceState);\n if (!storedState || !returnedState || storedState !== returnedState) {\n throw new SmartHiveAuthError(\"state_mismatch\", \"OAuth state mismatch — possible CSRF attack.\");\n }\n\n const verifier = await tempStorage.getItem(smartHiveAuthStorageKeys.pkceVerifier);\n if (!verifier) {\n throw new SmartHiveAuthError(\"pkce_missing\", \"Missing PKCE verifier for authorization code exchange.\");\n }\n const redirectUri = config.redirectUri ?? (url.origin + url.pathname);\n\n const body = new URLSearchParams({\n grant_type: \"authorization_code\",\n code,\n redirect_uri: redirectUri,\n client_id: config.publishableKey\n });\n body.set(\"code_verifier\", verifier);\n\n const response = await fetch(`${authBase}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body\n });\n\n if (!response.ok) {\n const err = await response.json().catch(() => ({})) as { error?: string; error_description?: string };\n throw new SmartHiveAuthError(err.error ?? \"token_error\", err.error_description ?? \"Token exchange failed.\");\n }\n\n const tokenBody = await response.json() as {\n access_token: string;\n refresh_token?: string;\n expires_in?: number;\n token_type?: string;\n };\n\n const session: AuthSession = {\n accessToken: tokenBody.access_token,\n refreshToken: tokenBody.refresh_token,\n expiresAt: tokenBody.expires_in ? Date.now() + tokenBody.expires_in * 1000 : undefined\n };\n\n await saveSession(session);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceVerifier);\n await tempStorage.removeItem(smartHiveAuthStorageKeys.pkceState);\n\n return session;\n },\n\n async loginSocial(provider, options) {\n const redirectUri = options?.redirectUri ?? config.redirectUri ?? globalThis.location?.href;\n if (!redirectUri) throw new SmartHiveAuthError(\"missing_redirect_uri\", \"redirectUri is required for social login.\");\n let url: URL;\n if (config.socialProxyUrl) {\n // Route through the app's own backend proxy — provider shows app's domain\n url = new URL(`${normalizeBaseUrl(config.socialProxyUrl)}/api/auth/social/${provider}`);\n url.searchParams.set(\"redirect_uri\", redirectUri);\n // project_id is injected server-side by the backend proxy\n } else {\n url = new URL(`${authBase}/${environment}/api/auth/social/${provider}`);\n url.searchParams.set(\"project_id\", config.projectId);\n url.searchParams.set(\"redirect_uri\", redirectUri);\n }\n globalThis.location.assign(url.toString());\n },\n\n async handleSocialCallback(options) {\n const href = options?.url ?? globalThis.location?.href;\n if (!href) throw new SmartHiveAuthError(\"callback_failed\", \"No URL available for social callback.\");\n const url = new URL(href);\n const error = url.searchParams.get(\"error\");\n if (error) {\n throw new SmartHiveAuthError(error, url.searchParams.get(\"error_description\") ?? error);\n }\n const accessToken = url.searchParams.get(\"access_token\");\n if (!accessToken) throw new SmartHiveAuthError(\"callback_failed\", \"No access token in social callback URL.\");\n const expiresIn = url.searchParams.get(\"expires_in\");\n const session: AuthSession = {\n accessToken,\n refreshToken: url.searchParams.get(\"refresh_token\") ?? undefined,\n expiresAt: expiresIn ? Date.now() + parseInt(expiresIn, 10) * 1000 : undefined,\n };\n await saveSession(session);\n return session;\n },\n\n async logout() {\n await saveSession(null);\n await fetch(`${baseUrl}/api/auth/sign-out`, { method: \"POST\", credentials: \"include\" });\n },\n\n getSession: readSession,\n\n async getAccessToken() {\n const session = await readSession();\n if (!session) return null;\n if (session.expiresAt && Date.now() > session.expiresAt - 30000) {\n return (await client.refreshSession())?.accessToken ?? null;\n }\n return session.accessToken;\n },\n\n async getAuthorizationHeader() {\n const token = await client.getAccessToken();\n const headers: Record<string, string> = {};\n if (token) headers.authorization = `Bearer ${token}`;\n return headers;\n },\n\n async fetch(input, init = {}) {\n const authHeader = await client.getAuthorizationHeader();\n const headers = new Headers(init.headers);\n for (const [key, value] of Object.entries(authHeader)) {\n headers.set(key, value);\n }\n return fetch(input, { ...init, headers });\n },\n\n async refreshSession() {\n const session = await readSession();\n if (!session?.refreshToken) return session;\n const response = await fetch(`${baseUrl}/api/auth/oauth2/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: session.refreshToken\n })\n });\n if (!response.ok) { await saveSession(null); return null; }\n const body = await response.json() as { access_token: string; refresh_token?: string; expires_in?: number };\n const nextSession: AuthSession = {\n ...session,\n accessToken: body.access_token,\n refreshToken: body.refresh_token ?? session.refreshToken,\n expiresAt: body.expires_in ? Date.now() + body.expires_in * 1000 : session.expiresAt\n };\n await saveSession(nextSession);\n return nextSession;\n },\n\n async verifyToken(token) {\n if (token.split(\".\").length !== 3) return false;\n const response = await fetch(`${authBase}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n return response.ok;\n },\n\n async getUser() {\n const token = await client.getAccessToken();\n if (!token) return null;\n const response = await fetch(`${baseUrl}/api/auth/oauth2/userinfo`, {\n headers: { authorization: `Bearer ${token}` }\n });\n return response.ok ? response.json() : null;\n },\n\n headless,\n };\n\n return client;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smarthivelabs-devs/auth-sdk",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "SmartHive Auth JavaScript/TypeScript SDK — core client for browser, Node.js, and React Native",
5
5
  "license": "MIT",
6
6
  "repository": {