@nexusrt/nexus-auth 1.0.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.
@@ -0,0 +1,466 @@
1
+ interface AuthUser {
2
+ email: string;
3
+ avatar_url?: string;
4
+ [key: string]: unknown;
5
+ }
6
+ interface JwtPayload {
7
+ email: string;
8
+ avatar_url?: string;
9
+ [key: string]: unknown;
10
+ }
11
+ interface RefreshTokenResponse {
12
+ access_token: string;
13
+ }
14
+ interface SignInResponse {
15
+ access_token?: string;
16
+ status?: SignInStatus;
17
+ mfa?: string;
18
+ }
19
+ interface MagicLinkResponse {
20
+ status: "MAGIC_LINK";
21
+ mfa: string;
22
+ }
23
+ interface ForgotPasswordResponse {
24
+ status: "RESET_PASSWORD";
25
+ mfa: string;
26
+ }
27
+ interface TotpSetupResponse {
28
+ totp: string;
29
+ }
30
+ interface SsoStartResponse {
31
+ auth_url: string;
32
+ }
33
+ interface GenericSuccessResponse {
34
+ [key: string]: unknown;
35
+ }
36
+ declare const SignInStatus: {
37
+ /** Standard email+password sign-in succeeded — no MFA required */
38
+ readonly SUCCESS: "SUCCESS";
39
+ /** Server requires the user to complete an Email MFA challenge */
40
+ readonly MFA_REQUIRED: "MFA_REQUIRED";
41
+ /** Server requires the user to complete a TOTP challenge */
42
+ readonly TOTP_REQUIRED: "TOTP_REQUIRED";
43
+ /** Server sent a magic link/code to the user's email */
44
+ readonly MAGIC_LINK: "MAGIC_LINK";
45
+ /** Server sent a password-reset code to the user's email */
46
+ readonly RESET_PASSWORD: "RESET_PASSWORD";
47
+ };
48
+ type SignInStatus = (typeof SignInStatus)[keyof typeof SignInStatus];
49
+ interface AuthClientConfig {
50
+ /**
51
+ * Base URL of your auth server.
52
+ * @default "https://auth.jobtrk.com"
53
+ */
54
+ baseUrl?: string;
55
+ }
56
+ interface EmailPasswordCredentials {
57
+ email: string;
58
+ password: string;
59
+ userName?: string;
60
+ firstName?: string;
61
+ lastName?: string;
62
+ }
63
+ interface MfaVerifyInput {
64
+ /** The session ID returned from the initial sign-in / magic-link call */
65
+ sessionId: string;
66
+ /** The one-time code entered by the user */
67
+ code: string;
68
+ }
69
+ interface ResetPasswordInput {
70
+ oldPassword: string;
71
+ newPassword: string;
72
+ }
73
+ interface ForgotPasswordConfirmInput {
74
+ /** The session ID returned from forgotPassword() */
75
+ sessionId: string;
76
+ /** The code emailed to the user */
77
+ code: string;
78
+ /** The new password to set */
79
+ password: string;
80
+ }
81
+ interface SsoRegisterInput {
82
+ providerName: string;
83
+ providerEndEmail: string;
84
+ clientId: string;
85
+ clientSecret: string;
86
+ issuer: string;
87
+ callbackUrl: string;
88
+ }
89
+
90
+ /**
91
+ * Manages the in-memory access token and exposes token-based auth helpers.
92
+ *
93
+ * Storage strategy:
94
+ * - Access tokens are kept in memory only (never localStorage) for security.
95
+ * - Refresh tokens are stored in an HttpOnly cookie by the server.
96
+ */
97
+ declare class TokenManager {
98
+ private accessToken;
99
+ getAccessToken(): string | null;
100
+ setAccessToken(token: string): void;
101
+ clearAccessToken(): void;
102
+ /**
103
+ * Decodes the JWT payload without verifying the signature.
104
+ * Useful for reading user info (email, avatar) on the client side.
105
+ */
106
+ decodeToken(token: string): JwtPayload | null;
107
+ /**
108
+ * Reads user info directly from the stored access token.
109
+ * Returns null if no token is set or it cannot be decoded.
110
+ */
111
+ getUserFromToken(): Pick<AuthUser, "email" | "avatar_url"> | null;
112
+ /**
113
+ * Attempts to get a new access token using the HttpOnly refresh-token cookie.
114
+ * Call this once on app startup to restore an existing session.
115
+ *
116
+ * @returns The decoded user info on success, or null if no refresh token exists.
117
+ */
118
+ refresh(baseUrl: string): Promise<Pick<AuthUser, "email" | "avatar_url"> | null>;
119
+ }
120
+
121
+ /**
122
+ * Session-based auth helpers.
123
+ *
124
+ * When the developer chooses sessions over JWTs, the server sets an
125
+ * HttpOnly session cookie. These methods let you read and verify
126
+ * that session without managing tokens yourself.
127
+ *
128
+ * Note: An access token is still returned by the server even in session
129
+ * mode, so you can use it to authenticate with downstream services if needed.
130
+ */
131
+ declare class SessionManager {
132
+ /**
133
+ * Fetches the currently authenticated user from the server.
134
+ * Relies on the session cookie being present in the browser.
135
+ *
136
+ * Use this instead of decoding the JWT when you want the
137
+ * authoritative user object from your database.
138
+ */
139
+ getUser(baseUrl: string): Promise<AuthUser>;
140
+ /**
141
+ * Verifies that a session is still valid for a given email address.
142
+ * Useful for server-side checks or sensitive operations.
143
+ */
144
+ verifySession(baseUrl: string, email: string): Promise<void>;
145
+ }
146
+
147
+ /**
148
+ * Email + Password authentication methods.
149
+ *
150
+ * Sign-in has three possible outcomes depending on what the user has enabled:
151
+ *
152
+ * 1. Plain sign-in → status is undefined / SUCCESS (no MFA)
153
+ * 2. Email MFA → status === SignInStatus.MFA_REQUIRED
154
+ * 3. TOTP → status === SignInStatus.TOTP_REQUIRED
155
+ *
156
+ * In cases 2 & 3 the response includes a `mfa` session ID that you must
157
+ * pass to the corresponding verify method.
158
+ *
159
+ * Import `SignInStatus` to compare against the status value:
160
+ * import { SignInStatus } from "jobtrk-auth-sdk";
161
+ */
162
+ declare class EmailPasswordAuth {
163
+ /**
164
+ * Creates a new account with an email address and password.
165
+ */
166
+ signUp(baseUrl: string, credentials: EmailPasswordCredentials): Promise<GenericSuccessResponse>;
167
+ /**
168
+ * Signs in with email + password.
169
+ *
170
+ * Check `response.status` to determine the next step:
171
+ *
172
+ * ```ts
173
+ * const result = await auth.email.signIn({ email, password });
174
+ *
175
+ * if (result.status === SignInStatus.MFA_REQUIRED) {
176
+ * // prompt for email OTP, then call auth.email.verifyMfa()
177
+ * } else if (result.status === SignInStatus.TOTP_REQUIRED) {
178
+ * // prompt for TOTP code, then call auth.totp.verifySignIn()
179
+ * } else {
180
+ * // user is signed in — store result.access_token if using JWT mode
181
+ * }
182
+ * ```
183
+ */
184
+ signIn(baseUrl: string, credentials: EmailPasswordCredentials): Promise<SignInResponse>;
185
+ /**
186
+ * Confirms the one-time code sent to the user's email after a sign-in
187
+ * that returned `status === SignInStatus.MFA_REQUIRED`.
188
+ */
189
+ verifyMfa(baseUrl: string, input: MfaVerifyInput): Promise<GenericSuccessResponse>;
190
+ /**
191
+ * Looks up the username associated with an email address.
192
+ */
193
+ getUsername(baseUrl: string, email: string): Promise<GenericSuccessResponse>;
194
+ }
195
+
196
+ /**
197
+ * Email Magic Link authentication.
198
+ *
199
+ * Flow:
200
+ * 1. Call `send(email)` → server emails a one-time code to the user.
201
+ * 2. Response contains a `mfa` session ID.
202
+ * 3. User enters the code; call `verify({ sessionId, code })` to complete sign-in.
203
+ */
204
+ declare class MagicLinkAuth {
205
+ /**
206
+ * Sends a magic-link code to the provided email address.
207
+ *
208
+ * @returns A session ID (`mfa` field) that you must pass to `verify()`.
209
+ *
210
+ * ```ts
211
+ * const { mfa: sessionId } = await auth.magicLink.send(email);
212
+ * // store sessionId, prompt user for code
213
+ * ```
214
+ */
215
+ send(baseUrl: string, email: string): Promise<MagicLinkResponse>;
216
+ /**
217
+ * Verifies the code the user received and completes sign-in.
218
+ */
219
+ verify(baseUrl: string, input: MfaVerifyInput): Promise<GenericSuccessResponse>;
220
+ }
221
+
222
+ /**
223
+ * TOTP (Time-based One-Time Password) MFA management.
224
+ *
225
+ * Setup flow:
226
+ * 1. Call `setup()` → server returns a QR code / TOTP secret.
227
+ * 2. User scans with their authenticator app.
228
+ * 3. Call `confirmSetup(code)` with the first code to activate TOTP.
229
+ *
230
+ * Sign-in flow (when signIn returns `status === SignInStatus.TOTP_REQUIRED`):
231
+ * 1. Prompt user for their TOTP code.
232
+ * 2. Call `verifySignIn({ sessionId: data.mfa, code })` to complete sign-in.
233
+ */
234
+ declare class TotpAuth {
235
+ /**
236
+ * Starts TOTP registration — returns the secret / QR code to display.
237
+ */
238
+ setup(baseUrl: string): Promise<TotpSetupResponse>;
239
+ /**
240
+ * Confirms the TOTP setup by verifying the first code from the
241
+ * authenticator app.
242
+ */
243
+ confirmSetup(baseUrl: string, code: string): Promise<GenericSuccessResponse>;
244
+ /**
245
+ * Completes a TOTP sign-in challenge.
246
+ * Use the `mfa` session ID returned by `emailPassword.signIn()` as `sessionId`.
247
+ */
248
+ verifySignIn(baseUrl: string, input: MfaVerifyInput): Promise<GenericSuccessResponse>;
249
+ /**
250
+ * Removes TOTP from the currently authenticated user's account.
251
+ */
252
+ delete(baseUrl: string): Promise<void>;
253
+ }
254
+
255
+ /**
256
+ * Password management methods.
257
+ *
258
+ * ── Reset password (authenticated user) ──────────────────────────────
259
+ * The user knows their current password and wants to change it.
260
+ * Call `reset({ oldPassword, newPassword })`.
261
+ *
262
+ * ── Forgot password (unauthenticated) ────────────────────────────────
263
+ * 1. Call `forgot(email)` → server emails a code and returns a session ID.
264
+ * 2. User enters the code from their email.
265
+ * 3. Call `confirmForgot({ sessionId, code, password })` to set the new password.
266
+ */
267
+ declare class PasswordAuth {
268
+ /**
269
+ * Changes the password for an already authenticated user.
270
+ */
271
+ reset(baseUrl: string, input: ResetPasswordInput): Promise<GenericSuccessResponse>;
272
+ /**
273
+ * Initiates the forgot-password flow by sending a reset code to the
274
+ * user's email address.
275
+ *
276
+ * @returns A session ID (`mfa` field) required by `confirmForgot()`.
277
+ *
278
+ * ```ts
279
+ * const { mfa: sessionId } = await auth.password.forgot(email);
280
+ * // prompt user for code
281
+ * ```
282
+ */
283
+ forgot(baseUrl: string, email: string): Promise<ForgotPasswordResponse>;
284
+ /**
285
+ * Completes the forgot-password flow by verifying the emailed code
286
+ * and setting the new password.
287
+ */
288
+ confirmForgot(baseUrl: string, input: ForgotPasswordConfirmInput): Promise<GenericSuccessResponse>;
289
+ }
290
+
291
+ /**
292
+ * Multi-tenant SSO (Single Sign-On) methods.
293
+ *
294
+ * Two roles exist:
295
+ *
296
+ * Organization Admin → registers their company IDP via `registerProvider()`.
297
+ * End User → signs in through their company's IDP via `signIn()`.
298
+ *
299
+ * Sign-in flow:
300
+ * 1. Call `signIn(email)` → server resolves the org and returns a redirect URL.
301
+ * 2. Redirect the user to `auth_url` to complete sign-in with their IDP.
302
+ *
303
+ * ```ts
304
+ * const { auth_url } = await auth.sso.signIn(email);
305
+ * window.location.href = auth_url;
306
+ * ```
307
+ */
308
+ declare class SsoAuth {
309
+ /**
310
+ * Registers an organisation's Identity Provider (IDP) with the auth system.
311
+ * This is typically called once by an organisation admin during onboarding.
312
+ */
313
+ registerProvider(baseUrl: string, input: SsoRegisterInput): Promise<GenericSuccessResponse>;
314
+ /**
315
+ * Starts the SSO sign-in flow for an end user.
316
+ *
317
+ * The server resolves the correct IDP from the user's email domain
318
+ * and returns a redirect URL. Redirect the user to that URL to
319
+ * complete sign-in with their organisation's IDP.
320
+ */
321
+ signIn(baseUrl: string, email: string): Promise<SsoStartResponse>;
322
+ }
323
+
324
+ /**
325
+ * Email MFA management.
326
+ *
327
+ * These methods manage whether a user has Email MFA enabled on their account.
328
+ * They are separate from the sign-in verify step (see EmailPasswordAuth.verifyMfa).
329
+ */
330
+ declare class EmailMfaManager {
331
+ /**
332
+ * Enables Email MFA for the currently authenticated user.
333
+ * Once enabled, future sign-ins will require a one-time code sent to email.
334
+ */
335
+ create(baseUrl: string): Promise<void>;
336
+ /**
337
+ * Disables Email MFA for the currently authenticated user.
338
+ */
339
+ delete(baseUrl: string): Promise<void>;
340
+ }
341
+
342
+ /**
343
+ * Social / OAuth provider sign-in methods.
344
+ *
345
+ * Each method redirects the browser to the provider's OAuth flow.
346
+ * After successful authentication the server will redirect back to
347
+ * your application with a session cookie (or access token, depending
348
+ * on your server configuration).
349
+ *
350
+ * These are simple redirects — no async call is needed.
351
+ */
352
+ declare class SocialAuth {
353
+ private readonly baseUrl;
354
+ constructor(baseUrl: string);
355
+ /** Redirects to Google OAuth sign-in. */
356
+ signInWithGoogle(): void;
357
+ /** Redirects to GitHub OAuth sign-in. */
358
+ signInWithGithub(): void;
359
+ /** Redirects to LinkedIn OAuth sign-in. */
360
+ signInWithLinkedIn(): void;
361
+ /** Redirects to Okta OAuth sign-in. */
362
+ signInWithOkta(): void;
363
+ }
364
+
365
+ /**
366
+ * AuthClient
367
+ *
368
+ * The single entry point for the JobTrk auth SDK.
369
+ * Framework-agnostic — works in React, Vue, Svelte, vanilla JS, etc.
370
+ *
371
+ * ── Quick start ──────────────────────────────────────────────────────
372
+ *
373
+ * ```ts
374
+ * import { AuthClient, SignInStatus } from "jobtrk-auth-sdk";
375
+ *
376
+ * const auth = new AuthClient({ baseUrl: "https://auth.yourapp.com" });
377
+ *
378
+ * // Restore session on app startup
379
+ * const user = await auth.token.refresh();
380
+ *
381
+ * // Social sign-in
382
+ * auth.social.signInWithGoogle();
383
+ *
384
+ * // Email + password sign-in (with MFA branching)
385
+ * const result = await auth.email.signIn({ email, password });
386
+ * if (result.status === SignInStatus.MFA_REQUIRED) { ... }
387
+ * if (result.status === SignInStatus.TOTP_REQUIRED) { ... }
388
+ *
389
+ * // Magic link
390
+ * const { mfa: sessionId } = await auth.magicLink.send(email);
391
+ * await auth.magicLink.verify({ sessionId, code });
392
+ *
393
+ * // SSO
394
+ * const { auth_url } = await auth.sso.signIn(email);
395
+ * window.location.href = auth_url;
396
+ * ```
397
+ */
398
+ declare class AuthClient {
399
+ private readonly baseUrl;
400
+ /** JWT access token management and refresh */
401
+ readonly token: TokenManager;
402
+ /** Session-based auth helpers (getUser, verifySession) */
403
+ readonly session: SessionManager;
404
+ /** Social / OAuth redirects (Google, GitHub, LinkedIn, Okta) */
405
+ readonly social: SocialAuth;
406
+ /** Email + password sign-up, sign-in, and MFA verify */
407
+ readonly email: EmailPasswordAuth;
408
+ /** Email magic-link send and verify */
409
+ readonly magicLink: MagicLinkAuth;
410
+ /** TOTP setup, confirm, sign-in verify, and delete */
411
+ readonly totp: TotpAuth;
412
+ /** Email MFA enable / disable */
413
+ readonly emailMfa: EmailMfaManager;
414
+ /** Password reset (authenticated) and forgot-password flow */
415
+ readonly password: PasswordAuth;
416
+ /** Multi-tenant SSO provider registration and sign-in */
417
+ readonly sso: SsoAuth;
418
+ constructor(config?: AuthClientConfig);
419
+ /**
420
+ * Signs the user out of the current session/device.
421
+ * Clears the in-memory access token after a successful server response.
422
+ */
423
+ logout(): Promise<void>;
424
+ /**
425
+ * Signs the user out of ALL active sessions / devices.
426
+ * Clears the in-memory access token after a successful server response.
427
+ */
428
+ logoutAllSessions(): Promise<void>;
429
+ }
430
+ type BoundModule<T extends object> = {
431
+ [K in keyof T]: T[K] extends (baseUrl: string, ...args: infer A) => infer R ? (...args: A) => R : T[K];
432
+ };
433
+ /**
434
+ * Creates an `AuthClient` where all sub-module methods have the `baseUrl`
435
+ * argument pre-bound. This is the recommended way to instantiate the SDK.
436
+ *
437
+ * ```ts
438
+ * const auth = createAuthClient({ baseUrl: "https://auth.yourapp.com" });
439
+ *
440
+ * // No need to pass baseUrl to individual methods:
441
+ * await auth.email.signIn({ email, password });
442
+ * await auth.token.refresh();
443
+ * ```
444
+ */
445
+ declare function createAuthClient(config?: AuthClientConfig): {
446
+ token: BoundModule<TokenManager>;
447
+ session: BoundModule<SessionManager>;
448
+ email: BoundModule<EmailPasswordAuth>;
449
+ magicLink: BoundModule<MagicLinkAuth>;
450
+ totp: BoundModule<TotpAuth>;
451
+ emailMfa: BoundModule<EmailMfaManager>;
452
+ password: BoundModule<PasswordAuth>;
453
+ sso: BoundModule<SsoAuth>;
454
+ social: SocialAuth;
455
+ logout: () => Promise<void>;
456
+ logoutAllSessions: () => Promise<void>;
457
+ };
458
+ type BoundAuthClient = ReturnType<typeof createAuthClient>;
459
+
460
+ declare class AuthError extends Error {
461
+ readonly status: number;
462
+ readonly body: unknown;
463
+ constructor(message: string, status: number, body?: unknown);
464
+ }
465
+
466
+ export { AuthClient, type AuthClientConfig, AuthError, type AuthUser, type BoundAuthClient, type EmailPasswordCredentials, type ForgotPasswordConfirmInput, type ForgotPasswordResponse, type GenericSuccessResponse, type JwtPayload, type MagicLinkResponse, type MfaVerifyInput, type RefreshTokenResponse, type ResetPasswordInput, type SignInResponse, SignInStatus, type SsoRegisterInput, type SsoStartResponse, type TotpSetupResponse, createAuthClient };
@@ -0,0 +1,6 @@
1
+ export { AuthClient, createAuthClient } from "./client";
2
+ export type { BoundAuthClient } from "./client";
3
+ export { AuthError } from "./http";
4
+ export type { AuthUser, JwtPayload, AuthClientConfig, EmailPasswordCredentials, MfaVerifyInput, ResetPasswordInput, ForgotPasswordConfirmInput, SsoRegisterInput, SignInResponse, MagicLinkResponse, ForgotPasswordResponse, TotpSetupResponse, SsoStartResponse, RefreshTokenResponse, GenericSuccessResponse, } from "./types";
5
+ export { SignInStatus } from "./types";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACxD,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAGnC,YAAY,EACV,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,wBAAwB,EACxB,cAAc,EACd,kBAAkB,EAClB,0BAA0B,EAC1B,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}