@erpgulf/auth-sdk 0.1.0-beta.1
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 +357 -0
- package/dist/index.d.ts +125 -0
- package/dist/index.js +756 -0
- package/dist/index.js.map +1 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
# `@erpgulf/auth-sdk`
|
|
2
|
+
|
|
3
|
+
Framework-independent TypeScript SDK for the shared ERPGulf authentication flow.
|
|
4
|
+
It hides Frappe endpoints, master-token handling, response formats, and policy
|
|
5
|
+
terminology from consuming applications.
|
|
6
|
+
|
|
7
|
+
The package has no React, React Native, or Expo dependency. It uses global
|
|
8
|
+
`fetch` by default and can accept a custom transport for compatible runtimes and
|
|
9
|
+
tests.
|
|
10
|
+
|
|
11
|
+
> `@erpgulf/auth-sdk` does **not** manage user token refresh or session
|
|
12
|
+
> persistence.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
The beta is distributed publicly through npmjs.org. After publication succeeds,
|
|
17
|
+
install the exact version without registry credentials:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npm install --save-exact @erpgulf/auth-sdk@0.1.0-beta.1
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Or with pnpm:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
pnpm add --save-exact @erpgulf/auth-sdk@0.1.0-beta.1
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
If you previously configured `@erpgulf` for GitHub Packages, replace that scope
|
|
30
|
+
mapping in the consuming project's `.npmrc` so it overrides any old user-level
|
|
31
|
+
configuration:
|
|
32
|
+
|
|
33
|
+
```ini
|
|
34
|
+
@erpgulf:registry=https://registry.npmjs.org
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
New projects using the default npm registry need no `.npmrc` setup. Public
|
|
38
|
+
distribution does not grant access to ERPGulf backend tenants.
|
|
39
|
+
|
|
40
|
+
This prerelease is for integration testing. Consumer and staging validation
|
|
41
|
+
remain outstanding; public availability does not make it a stable release. The
|
|
42
|
+
package provides ESM JavaScript and TypeScript declarations and requires Node.js
|
|
43
|
+
20 or newer for Node consumers.
|
|
44
|
+
|
|
45
|
+
## Create a client
|
|
46
|
+
|
|
47
|
+
Supply the backend URL at runtime. Each client owns an independent normalized
|
|
48
|
+
URL and in-memory master-token cache.
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { createAuthClient } from "@erpgulf/auth-sdk";
|
|
52
|
+
|
|
53
|
+
const auth = createAuthClient({
|
|
54
|
+
baseUrl: "https://customer.example.com",
|
|
55
|
+
timeoutMs: 10_000,
|
|
56
|
+
metadata: {
|
|
57
|
+
appId: "employee-app",
|
|
58
|
+
appVersion: "2.4.0",
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
HTTPS is required by default. Local development over HTTP must be explicitly
|
|
64
|
+
enabled with `allowInsecureHttp: true`. Base URLs may include custom ports, but
|
|
65
|
+
credentials, query strings, fragments, and non-root paths are rejected.
|
|
66
|
+
|
|
67
|
+
Server discovery, QR scanning, and company-code lookup happen before client
|
|
68
|
+
creation and are outside this package.
|
|
69
|
+
|
|
70
|
+
## Authentication flow
|
|
71
|
+
|
|
72
|
+
`begin` fetches and normalizes login policy, then runs the single authoritative
|
|
73
|
+
flow resolver:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
const flow = await auth.begin({ mobileNumber: "5550001" });
|
|
77
|
+
|
|
78
|
+
flow.action; // "SIGN_UP" | "SIGN_IN"
|
|
79
|
+
flow.nextStep;
|
|
80
|
+
flow.credentials.password; // "required" | "optional" | "disabled"
|
|
81
|
+
flow.credentials.otp; // "required" | "optional" | "disabled"
|
|
82
|
+
flow.credentials.atLeastOneOf; // e.g. ["password", "otp"]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`atLeastOneOf` describes enabled optional credentials when the backend does not
|
|
86
|
+
mark either one mandatory. This preserves `Optional` OTP semantics instead of
|
|
87
|
+
silently converting it to required. Contradictory or credential-free policies
|
|
88
|
+
fail with `UNSUPPORTED_POLICY`.
|
|
89
|
+
|
|
90
|
+
Applications can use `nextStep` for common UI routing and the full credential
|
|
91
|
+
requirements for optional inputs. Presentation remains entirely app-owned.
|
|
92
|
+
`nextStep` is a hint, not a complete form definition: inspect `credentials` for
|
|
93
|
+
optional fields and `policy.employeeHasExistingPassword` to distinguish creating
|
|
94
|
+
a password from verifying one, including when both credentials are required.
|
|
95
|
+
|
|
96
|
+
Prefer `begin` for policy-guided integration. `getLoginPolicy` is the
|
|
97
|
+
lower-level alternative for apps with their own resolver; calling both is
|
|
98
|
+
unnecessary. Neither flow hints nor low-level operations enforce backend
|
|
99
|
+
authorization. The full policy matrix, especially password-only flows without an
|
|
100
|
+
existing password, requires backend confirmation before rollout. Unit tests
|
|
101
|
+
describe the current resolver, not proof that every combination is supported by
|
|
102
|
+
the server.
|
|
103
|
+
|
|
104
|
+
## Login policy
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
const policy = await auth.getLoginPolicy({ mobileNumber: "5550001" });
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Backend values `Mandatory`, `Optional`, and `No` become `required`, `optional`,
|
|
111
|
+
and `disabled`. Raw Frappe payloads and strings are not returned.
|
|
112
|
+
|
|
113
|
+
The supplied backend example uses a GET request with a form body.
|
|
114
|
+
Standards-based `fetch` does not support GET bodies, so the default adapter
|
|
115
|
+
sends the safely encoded mobile number as `?mobile=...`, while preserving GET
|
|
116
|
+
and the documented content-type. The existing `origin/expo-auth-starter` example
|
|
117
|
+
at commit `fd8b565` sends POST form data; it does not prove GET-query support.
|
|
118
|
+
Verify query-parameter compatibility against an authorized staging backend
|
|
119
|
+
before rollout. The SDK has not switched methods based on that conflicting
|
|
120
|
+
example.
|
|
121
|
+
|
|
122
|
+
## Master token behavior
|
|
123
|
+
|
|
124
|
+
The SDK automatically acquires a master access token for login policy, OTP, and
|
|
125
|
+
sign-in requests. It:
|
|
126
|
+
|
|
127
|
+
- validates the confirmed response with Zod;
|
|
128
|
+
- caches the access token only in the client instance's memory;
|
|
129
|
+
- calculates expiry from `expires_in` and uses a 30-second safety skew;
|
|
130
|
+
- deduplicates simultaneous acquisition into one request;
|
|
131
|
+
- never logs, persists, or publicly exposes the credential;
|
|
132
|
+
- ignores the returned master refresh token and calls the master-token endpoint
|
|
133
|
+
again when required.
|
|
134
|
+
|
|
135
|
+
Only HTTP 401 with `exc_type: "AuthenticationError"` and without a
|
|
136
|
+
`status: "error"` business-error marker triggers invalidation, fresh
|
|
137
|
+
acquisition, and one retry. This middleware signal comes from the existing app
|
|
138
|
+
example, not a live-backend test. Bare 401, all 403 responses, and credential
|
|
139
|
+
errors do not trigger automatic replay. A second matching rejection is
|
|
140
|
+
`MASTER_TOKEN_REJECTED`. There are no general network, timeout,
|
|
141
|
+
malformed-response, or 5xx retries.
|
|
142
|
+
|
|
143
|
+
Safe replay of OTP/sign-in still requires the backend to emit that middleware
|
|
144
|
+
signal **before processing the operation**. Confirm this contract in staging.
|
|
145
|
+
Client serialization does not expose the internal master-token cache. This is
|
|
146
|
+
accidental-disclosure protection, not isolation from malicious application code.
|
|
147
|
+
|
|
148
|
+
## Send OTP
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
const otp = await auth.sendOtp({ mobileNumber: "5550001" });
|
|
152
|
+
otp.expiresIn; // seconds
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The backend success message is not used for business logic. A timeout or unknown
|
|
156
|
+
network outcome is not automatically replayed, avoiding duplicate OTP actions.
|
|
157
|
+
|
|
158
|
+
## Sign up
|
|
159
|
+
|
|
160
|
+
Sign-up is not sent with master Authorization under the confirmed contract.
|
|
161
|
+
Optional credentials are omitted rather than encoded as `undefined`. The
|
|
162
|
+
existing app example does send master Authorization for sign-up; reconcile this
|
|
163
|
+
discrepancy in staging. The SDK retains the supplied contract for now.
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
const result = await auth.signUp({
|
|
167
|
+
mobileNumber: "5550001",
|
|
168
|
+
otp: "<OTP>",
|
|
169
|
+
password: "<PASSWORD>", // omit when policy allows
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
At least one credential must be present. The SDK does not retain either value or
|
|
174
|
+
compare the returned phone number with the submitted number.
|
|
175
|
+
|
|
176
|
+
## Sign in
|
|
177
|
+
|
|
178
|
+
Sign-in is master-token authenticated. Its confirmed credential combinations
|
|
179
|
+
are:
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
await auth.signIn({ mobileNumber, password });
|
|
183
|
+
await auth.signIn({ mobileNumber, otp });
|
|
184
|
+
await auth.signIn({ mobileNumber, password, otp });
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Calling sign-in with neither password nor OTP fails locally with
|
|
188
|
+
`INVALID_SIGN_IN_INPUT`. Values are form encoded, and absent fields are omitted.
|
|
189
|
+
Sign-in is never replayed after an ambiguous network failure because a submitted
|
|
190
|
+
OTP may already have been consumed. The only automatic retry is the bounded
|
|
191
|
+
explicit master-auth rejection path described above.
|
|
192
|
+
|
|
193
|
+
These are low-level operations: they do not fetch or enforce policy implicitly.
|
|
194
|
+
Passwords are not trimmed. If the employee has no self-chosen password, a
|
|
195
|
+
supplied password may **set** it rather than verify identity. Do not treat a
|
|
196
|
+
password-only request in that state as verified proof of identity; confirm the
|
|
197
|
+
backend's onboarding rules and enforce authorization on the server.
|
|
198
|
+
|
|
199
|
+
## Results and app-owned session state
|
|
200
|
+
|
|
201
|
+
Sign-up returns `AuthResult`; sign-in returns `SignInResult`, which adds the
|
|
202
|
+
normalized password and OTP policies reported by sign-in.
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
const result = await auth.signIn({ mobileNumber, password });
|
|
206
|
+
|
|
207
|
+
result.token.accessToken;
|
|
208
|
+
result.token.refreshToken;
|
|
209
|
+
result.token.expiresIn;
|
|
210
|
+
result.employee;
|
|
211
|
+
result.authenticatedAt;
|
|
212
|
+
result.passwordPolicy;
|
|
213
|
+
result.otpPolicy;
|
|
214
|
+
|
|
215
|
+
// SDK responsibility ends here.
|
|
216
|
+
await appSessionManager.save({
|
|
217
|
+
accessToken: result.token.accessToken,
|
|
218
|
+
refreshToken: result.token.refreshToken,
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Token type casing from the backend is normalized to `Bearer` when it is a
|
|
223
|
+
case-insensitive bearer value. The SDK returns user tokens but never stores,
|
|
224
|
+
refreshes, or rotates them.
|
|
225
|
+
|
|
226
|
+
## Errors
|
|
227
|
+
|
|
228
|
+
All SDK failures use `AuthError`:
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
import { AuthError } from "@erpgulf/auth-sdk";
|
|
232
|
+
|
|
233
|
+
try {
|
|
234
|
+
await auth.signIn({ mobileNumber, otp });
|
|
235
|
+
} catch (error: unknown) {
|
|
236
|
+
if (error instanceof AuthError) {
|
|
237
|
+
console.log(error.code, error.retryable, error.httpStatus);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Confirmed sign-in errors are normalized as follows:
|
|
243
|
+
|
|
244
|
+
| Backend meaning | SDK code |
|
|
245
|
+
| ------------------------------ | ------------------------ |
|
|
246
|
+
| Invalid or expired OTP | `INVALID_OR_EXPIRED_OTP` |
|
|
247
|
+
| Invalid password | `INVALID_PASSWORD` |
|
|
248
|
+
| Unknown authentication failure | `AUTHENTICATION_FAILED` |
|
|
249
|
+
|
|
250
|
+
Malformed confirmed responses use `INVALID_RESPONSE`; network and timeout errors
|
|
251
|
+
use `NETWORK_ERROR` and `TIMEOUT`. Error messages never include response
|
|
252
|
+
payloads, credentials, or Authorization headers. Native/custom transport
|
|
253
|
+
exceptions are replaced with safe messages; their raw causes are not attached
|
|
254
|
+
because they can contain request credentials. Custom transports must return HTTP
|
|
255
|
+
errors as responses, not throw them.
|
|
256
|
+
|
|
257
|
+
For dispatched `sendOtp`, `signUp`, and `signIn` requests, network failures,
|
|
258
|
+
timeouts, 5xx responses, and malformed successes have `retryable: false`: the
|
|
259
|
+
operation may already have taken effect. Do not automatically repeat it. A
|
|
260
|
+
retryable acquisition failure can occur before the protected mutation is sent;
|
|
261
|
+
read-only policy failures may also be retryable. The flag does not promise that
|
|
262
|
+
an error will resolve on retry.
|
|
263
|
+
|
|
264
|
+
Response schemas validate required fields, success markers, and known policy
|
|
265
|
+
values while stripping extra object fields. Additive backend metadata is
|
|
266
|
+
accepted but is not exposed to consumers; unknown policy enum values still fail
|
|
267
|
+
closed.
|
|
268
|
+
|
|
269
|
+
## Custom transport
|
|
270
|
+
|
|
271
|
+
`HttpTransport` and its request/response types are public only to support
|
|
272
|
+
runtimes without compatible global `fetch` and deterministic tests. It
|
|
273
|
+
transports data; it must not implement user-session token storage or refresh.
|
|
274
|
+
The default transport requests `redirect: "error"`, `cache: "no-store"`, and
|
|
275
|
+
`credentials: "omit"`. It does not follow redirects or opt into browser cookies
|
|
276
|
+
or HTTP caching. Custom transports must provide equivalent protection and must
|
|
277
|
+
not automatically retry requests. They receive sensitive headers and bodies and
|
|
278
|
+
are part of the trusted application boundary. Throw `AuthError` with code
|
|
279
|
+
`TIMEOUT` for timeouts; other thrown values become `NETWORK_ERROR`.
|
|
280
|
+
|
|
281
|
+
Browser/Node fetch behavior does not prove React Native/Expo adapter behavior.
|
|
282
|
+
Verify these options on each target runtime; use a conforming transport where
|
|
283
|
+
the runtime ignores them. The backend must also return `Cache-Control: no-store`
|
|
284
|
+
for authentication responses to protect intermediaries and native caches.
|
|
285
|
+
|
|
286
|
+
## Security and explicit non-goals
|
|
287
|
+
|
|
288
|
+
The SDK does not log authentication data. Do not log request bodies or returned
|
|
289
|
+
results in consuming apps. Validate/allowlist URLs from untrusted QR codes or
|
|
290
|
+
company lookup before client creation: HTTPS and URL syntax checks cannot
|
|
291
|
+
establish a server's trustworthiness.
|
|
292
|
+
|
|
293
|
+
This package intentionally does not implement:
|
|
294
|
+
|
|
295
|
+
- user access/refresh-token storage, refresh, or rotation;
|
|
296
|
+
- session restoration, global auth state, logout, or business API interception;
|
|
297
|
+
- SecureStore, Keychain, or AsyncStorage;
|
|
298
|
+
- React, React Native, Expo, hooks, navigation, or UI;
|
|
299
|
+
- server/company/tenant discovery or app-specific branches.
|
|
300
|
+
|
|
301
|
+
## Development
|
|
302
|
+
|
|
303
|
+
From the repository root:
|
|
304
|
+
|
|
305
|
+
```sh
|
|
306
|
+
pnpm install
|
|
307
|
+
pnpm lint
|
|
308
|
+
pnpm format:check
|
|
309
|
+
pnpm typecheck
|
|
310
|
+
pnpm test
|
|
311
|
+
pnpm build
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Tests use fake credentials and mock transports, plus an ephemeral loopback HTTP
|
|
315
|
+
server to verify native-fetch redirect rejection. They never contact a live
|
|
316
|
+
backend. Running the suite requires permission to bind a loopback port.
|
|
317
|
+
|
|
318
|
+
## Versioning
|
|
319
|
+
|
|
320
|
+
The initial public npm testing version is `0.1.0-beta.1`, published with the
|
|
321
|
+
`beta` dist-tag. The first release uses an authenticated npm maintainer;
|
|
322
|
+
subsequent releases can use the repository's manually dispatched
|
|
323
|
+
trusted-publishing workflow. Fixes use `0.1.0-beta.2`, `0.1.0-beta.3`, and
|
|
324
|
+
subsequent beta increments. Record consumer-visible changes with
|
|
325
|
+
`pnpm changeset`. Stable `0.1.0` must wait for validation in real consuming
|
|
326
|
+
applications; the beta workflow rejects stable versions and never publishes with
|
|
327
|
+
`latest`.
|
|
328
|
+
|
|
329
|
+
## Backend contracts still needed
|
|
330
|
+
|
|
331
|
+
Success shapes are validated against supplied contract examples, not live calls,
|
|
332
|
+
and sign-in's two known credential errors are mapped. Representative error
|
|
333
|
+
responses are still needed for invalid mobile, OTP generation rate limiting,
|
|
334
|
+
invalid/expired master token, sign-up failures (including already signed up),
|
|
335
|
+
and login-policy failures. Until confirmed, those cases use safe generic errors.
|
|
336
|
+
|
|
337
|
+
Before rollout, use an authorized staging tenant and disposable test employees:
|
|
338
|
+
|
|
339
|
+
- Verify GET `?mobile=...` policy lookup with a known test number, including a
|
|
340
|
+
leading `+`; compare with an approved POST-form control if GET fails. Never
|
|
341
|
+
send a GET body with standards-based fetch.
|
|
342
|
+
- Capture sanitized expired-master, invalid-OTP, invalid-password, and
|
|
343
|
+
permission errors. Confirm the exact middleware discriminator and that
|
|
344
|
+
rejected master authentication cannot generate OTPs, consume OTPs, or set
|
|
345
|
+
passwords.
|
|
346
|
+
- Reconcile sign-up Authorization requirements and all supported combinations of
|
|
347
|
+
signed-up/existing-password flags and password/OTP policies. Include Optional
|
|
348
|
+
OTP, disabled credentials, and password creation versus verification.
|
|
349
|
+
- Verify OTP-only, password-only, and combined sign-in with disposable accounts;
|
|
350
|
+
confirm expiry units, token casing, nullable email, and normalized results.
|
|
351
|
+
- Confirm the server sends no-store headers. Check redirect rejection, cookie
|
|
352
|
+
omission, caching, timeout behavior, and browser CORS on each deployment
|
|
353
|
+
runtime, especially React Native/Expo. Never use real credentials in redirect
|
|
354
|
+
tests.
|
|
355
|
+
|
|
356
|
+
Unit and loopback tests verify SDK behavior; supplied examples verify documented
|
|
357
|
+
shapes; none of these replace the staging checks above.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
type PasswordPolicy = "required" | "optional" | "disabled";
|
|
2
|
+
type OtpPolicy = "required" | "optional" | "disabled";
|
|
3
|
+
interface AuthPolicy {
|
|
4
|
+
readonly employeeId: string;
|
|
5
|
+
readonly employeeHasExistingPassword: boolean;
|
|
6
|
+
readonly employeeHasSignedUp: boolean;
|
|
7
|
+
readonly passwordPolicy: PasswordPolicy;
|
|
8
|
+
readonly otpPolicy: OtpPolicy;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface AuthToken {
|
|
12
|
+
readonly accessToken: string;
|
|
13
|
+
readonly refreshToken: string;
|
|
14
|
+
readonly expiresIn: number;
|
|
15
|
+
readonly tokenType: string;
|
|
16
|
+
readonly scope: string;
|
|
17
|
+
}
|
|
18
|
+
interface AuthEmployee {
|
|
19
|
+
readonly id: string;
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly phone: string;
|
|
22
|
+
readonly email: string | null;
|
|
23
|
+
}
|
|
24
|
+
interface AuthResult {
|
|
25
|
+
readonly token: AuthToken;
|
|
26
|
+
readonly employee: AuthEmployee;
|
|
27
|
+
readonly authenticatedAt: string;
|
|
28
|
+
}
|
|
29
|
+
interface SignInResult extends AuthResult {
|
|
30
|
+
readonly passwordPolicy: PasswordPolicy;
|
|
31
|
+
readonly otpPolicy: OtpPolicy;
|
|
32
|
+
}
|
|
33
|
+
interface SendOtpResult {
|
|
34
|
+
readonly expiresIn: number;
|
|
35
|
+
}
|
|
36
|
+
interface GetLoginPolicyInput {
|
|
37
|
+
readonly mobileNumber: string;
|
|
38
|
+
}
|
|
39
|
+
interface SendOtpInput {
|
|
40
|
+
readonly mobileNumber: string;
|
|
41
|
+
}
|
|
42
|
+
interface SignUpInput {
|
|
43
|
+
readonly mobileNumber: string;
|
|
44
|
+
readonly otp?: string;
|
|
45
|
+
readonly password?: string;
|
|
46
|
+
}
|
|
47
|
+
interface SignInInput {
|
|
48
|
+
readonly mobileNumber: string;
|
|
49
|
+
readonly otp?: string;
|
|
50
|
+
readonly password?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
type AuthAction = "SIGN_UP" | "SIGN_IN";
|
|
54
|
+
type AuthNextStep = "CREATE_PASSWORD" | "ENTER_PASSWORD" | "ENTER_OTP" | "ENTER_PASSWORD_AND_OTP" | "CHOOSE_PASSWORD_OR_OTP";
|
|
55
|
+
type CredentialName = "password" | "otp";
|
|
56
|
+
interface CredentialRequirements {
|
|
57
|
+
readonly password: PasswordPolicy;
|
|
58
|
+
readonly otp: OtpPolicy;
|
|
59
|
+
readonly atLeastOneOf: readonly CredentialName[];
|
|
60
|
+
}
|
|
61
|
+
interface AuthFlow {
|
|
62
|
+
readonly action: AuthAction;
|
|
63
|
+
readonly nextStep: AuthNextStep;
|
|
64
|
+
readonly credentials: CredentialRequirements;
|
|
65
|
+
readonly policy: AuthPolicy;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
type HttpMethod = "GET" | "POST";
|
|
69
|
+
interface HttpRequest {
|
|
70
|
+
readonly url: string;
|
|
71
|
+
readonly method: HttpMethod;
|
|
72
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
73
|
+
readonly body?: string;
|
|
74
|
+
readonly timeoutMs?: number;
|
|
75
|
+
}
|
|
76
|
+
interface HttpResponse {
|
|
77
|
+
readonly status: number;
|
|
78
|
+
readonly body: unknown;
|
|
79
|
+
}
|
|
80
|
+
interface HttpTransport {
|
|
81
|
+
/**
|
|
82
|
+
* Return HTTP failures as responses. Throw AuthError(TIMEOUT) for timeouts;
|
|
83
|
+
* other thrown values are normalized to NETWORK_ERROR without their cause.
|
|
84
|
+
* Implementations must reject redirects, disable auth-response caching and
|
|
85
|
+
* avoid ambient cookies. Credentials must never be logged or persisted.
|
|
86
|
+
*/
|
|
87
|
+
request(request: HttpRequest): Promise<HttpResponse>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
interface AuthClientMetadata {
|
|
91
|
+
readonly appId?: string;
|
|
92
|
+
readonly appVersion?: string;
|
|
93
|
+
}
|
|
94
|
+
interface AuthClientConfig {
|
|
95
|
+
readonly baseUrl: string;
|
|
96
|
+
readonly timeoutMs?: number;
|
|
97
|
+
readonly transport?: HttpTransport;
|
|
98
|
+
readonly metadata?: AuthClientMetadata;
|
|
99
|
+
readonly allowInsecureHttp?: boolean;
|
|
100
|
+
}
|
|
101
|
+
interface AuthClient {
|
|
102
|
+
begin(input: GetLoginPolicyInput): Promise<AuthFlow>;
|
|
103
|
+
getLoginPolicy(input: GetLoginPolicyInput): Promise<AuthPolicy>;
|
|
104
|
+
sendOtp(input: SendOtpInput): Promise<SendOtpResult>;
|
|
105
|
+
signUp(input: SignUpInput): Promise<AuthResult>;
|
|
106
|
+
signIn(input: SignInInput): Promise<SignInResult>;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
declare function createAuthClient(config: AuthClientConfig): AuthClient;
|
|
110
|
+
|
|
111
|
+
type AuthErrorCode = "AUTHENTICATION_FAILED" | "INVALID_BASE_URL" | "INVALID_CLIENT_CONFIG" | "INVALID_MOBILE" | "INVALID_OR_EXPIRED_OTP" | "INVALID_PASSWORD" | "INVALID_RESPONSE" | "INVALID_SIGN_IN_INPUT" | "INVALID_SIGN_UP_INPUT" | "MASTER_TOKEN_FAILED" | "MASTER_TOKEN_REJECTED" | "NETWORK_ERROR" | "SERVER_ERROR" | "TIMEOUT" | "UNSUPPORTED_POLICY";
|
|
112
|
+
interface AuthErrorOptions {
|
|
113
|
+
readonly cause?: unknown;
|
|
114
|
+
readonly httpStatus?: number;
|
|
115
|
+
readonly retryable?: boolean;
|
|
116
|
+
}
|
|
117
|
+
declare class AuthError extends Error {
|
|
118
|
+
readonly code: AuthErrorCode;
|
|
119
|
+
readonly httpStatus: number | undefined;
|
|
120
|
+
readonly retryable: boolean;
|
|
121
|
+
constructor(code: AuthErrorCode, message: string, options?: AuthErrorOptions);
|
|
122
|
+
}
|
|
123
|
+
declare function isAuthError(error: unknown): error is AuthError;
|
|
124
|
+
|
|
125
|
+
export { type AuthAction, type AuthClient, type AuthClientConfig, type AuthClientMetadata, type AuthEmployee, AuthError, type AuthErrorCode, type AuthErrorOptions, type AuthFlow, type AuthNextStep, type AuthPolicy, type AuthResult, type AuthToken, type CredentialName, type CredentialRequirements, type GetLoginPolicyInput, type HttpMethod, type HttpRequest, type HttpResponse, type HttpTransport, type OtpPolicy, type PasswordPolicy, type SendOtpInput, type SendOtpResult, type SignInInput, type SignInResult, type SignUpInput, createAuthClient, isAuthError };
|