@productcraft/auth 0.5.1 → 0.6.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 +26 -2
- package/dist/index.cjs +66 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -1
- package/dist/index.d.ts +41 -1
- package/dist/index.js +66 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -90,8 +90,11 @@ await consumer.auth.signup({
|
|
|
90
90
|
|
|
91
91
|
await consumer.auth.refresh({ refresh_token });
|
|
92
92
|
await consumer.auth.logout({ refresh_token });
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
|
|
94
|
+
// Forgot password. `sendPasswordResetEmail` mints the code AND emails it
|
|
95
|
+
// via Mail — this is what you want for a normal reset flow.
|
|
96
|
+
await consumer.auth.sendPasswordResetEmail({ email });
|
|
97
|
+
await consumer.auth.resetPassword({ code, new_password: "..." });
|
|
95
98
|
|
|
96
99
|
// Sign in with Apple (native iOS flow). See "Federated sign-in" below.
|
|
97
100
|
await consumer.auth.signinWithProvider({
|
|
@@ -116,6 +119,27 @@ await consumer.oauth.clientCredentials({ clientId, clientSecret, scope });
|
|
|
116
119
|
|
|
117
120
|
> **Wire-shape note.** Auth's JSON wire is snake_case, and the SDK returns response objects as-is (e.g. `access_token`, `refresh_token`, `token_type`, `expires_in`). Request DTOs follow the same convention; some convenience fields (`identifier`, `password`, `nonce`) are unaffected, but anywhere the spec uses an underscore the SDK does too.
|
|
118
121
|
|
|
122
|
+
### One-time codes: who sends the email?
|
|
123
|
+
|
|
124
|
+
Verification and password-reset each come in two flavours. **Picking the wrong one is silent** — you get a `2xx` and no email is ever sent — so choose deliberately:
|
|
125
|
+
|
|
126
|
+
| Method | Mints a code | Sends the email | Returns |
|
|
127
|
+
| --- | --- | --- | --- |
|
|
128
|
+
| `auth.requestVerification()` | ✅ | ❌ | `{ code, expires_at }` |
|
|
129
|
+
| `auth.sendVerificationEmail()` | ✅ | ✅ via Mail | `{ expires_at }` |
|
|
130
|
+
| `auth.requestReset()` | ✅ | ❌ | `{ code, expires_at }` |
|
|
131
|
+
| `auth.sendPasswordResetEmail()` | ✅ | ✅ via Mail | `{ expires_at }` |
|
|
132
|
+
|
|
133
|
+
**Use `send*` for a normal flow.** Mail delivers the code using your app's configured sender and template, and you never handle the plaintext code.
|
|
134
|
+
|
|
135
|
+
**Use `request*` only when you are delivering the code yourself** — your own SMTP, an SMS provider, or consuming it in-process (e.g. provisioning a test account). If you call `request*` and drop the returned `code` on the floor, your users get nothing and nothing is logged anywhere, because no send was ever attempted.
|
|
136
|
+
|
|
137
|
+
Each pair is gated by a *separate* PAK permission (`auth.user.verify.create` vs `auth.user.verify.send-email`, and likewise for `password-reset`), so a workspace can enable minting without enabling outbound mail.
|
|
138
|
+
|
|
139
|
+
The `send*` methods fail loudly with a typed `412` when Mail isn't ready — `ENVOI_NOT_ENABLED`, `ENVOI_SENDER_NOT_CONFIGURED`, `ENVOI_TEMPLATE_NOT_CONFIGURED`, `ENVOI_APP_NOT_BOUND_TO_WORKSPACE` — or `503 ENVOI_DISPATCH_FAILED`. If your endpoint returns a uniform response to prevent account enumeration, catch and **log** these rather than discarding them; a swallowed 412 is indistinguishable from the silent failure above.
|
|
140
|
+
|
|
141
|
+
Both `request*` and `send*` return `{}` when the contact doesn't match (or is already verified / unverified as appropriate). That's the anti-enumeration contract, not an error — there is nothing to branch on.
|
|
142
|
+
|
|
119
143
|
## Federated sign-in (Apple, Google)
|
|
120
144
|
|
|
121
145
|
`consumer.auth.signinWithProvider` lets a BFF exchange a provider-issued identity token for an Auth `{ access_token, refresh_token }` pair. The endpoint creates the EndUser on first sign-in and returns the same account on subsequent ones — the SDK is a thin wrapper over Auth's `POST /{appSlug}/v1/auth/oauth/{provider}` which does the heavy lifting (Apple JWKS verification, issuer pinning, audience validation against the app's configured native client ids, server-side nonce replay protection, account creation / linking).
|
package/dist/index.cjs
CHANGED
|
@@ -1361,6 +1361,36 @@ async function consumerAuthControllerRequestPasswordReset({
|
|
|
1361
1361
|
return res.data;
|
|
1362
1362
|
}
|
|
1363
1363
|
|
|
1364
|
+
// src/_generated/clients/consumerAuth/consumerAuthControllerSendPasswordResetEmail.ts
|
|
1365
|
+
function getConsumerAuthControllerSendPasswordResetEmailUrl({
|
|
1366
|
+
appSlug
|
|
1367
|
+
}) {
|
|
1368
|
+
const app_slug = appSlug;
|
|
1369
|
+
const res = {
|
|
1370
|
+
method: "POST",
|
|
1371
|
+
url: `/${app_slug}/v1/auth/send-password-reset-email`
|
|
1372
|
+
};
|
|
1373
|
+
return res;
|
|
1374
|
+
}
|
|
1375
|
+
async function consumerAuthControllerSendPasswordResetEmail({
|
|
1376
|
+
appSlug,
|
|
1377
|
+
data,
|
|
1378
|
+
headers
|
|
1379
|
+
}, config = {}) {
|
|
1380
|
+
const { client: request = client, ...requestConfig } = config;
|
|
1381
|
+
const requestData = data;
|
|
1382
|
+
const res = await request({
|
|
1383
|
+
method: "POST",
|
|
1384
|
+
url: getConsumerAuthControllerSendPasswordResetEmailUrl({
|
|
1385
|
+
appSlug
|
|
1386
|
+
}).url.toString(),
|
|
1387
|
+
data: requestData,
|
|
1388
|
+
...requestConfig,
|
|
1389
|
+
headers: { ...headers, ...requestConfig.headers }
|
|
1390
|
+
});
|
|
1391
|
+
return res.data;
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1364
1394
|
// src/_generated/clients/consumerAuth/consumerAuthControllerResetPassword.ts
|
|
1365
1395
|
function getConsumerAuthControllerResetPasswordUrl({
|
|
1366
1396
|
appSlug
|
|
@@ -1887,7 +1917,17 @@ var ConsumerScope = class {
|
|
|
1887
1917
|
{ client: this.client }
|
|
1888
1918
|
),
|
|
1889
1919
|
/**
|
|
1890
|
-
*
|
|
1920
|
+
* Mint a 6-digit password-reset code. **Sends no email.** Returns
|
|
1921
|
+
* `{ code, expires_at }` for delivery via your own channel — or
|
|
1922
|
+
* `{}` when the contact doesn't match a verified account (uniform
|
|
1923
|
+
* shape — no account enumeration).
|
|
1924
|
+
*
|
|
1925
|
+
* If you want Mail to deliver the code for you, call
|
|
1926
|
+
* {@link sendPasswordResetEmail} instead. Calling this one and
|
|
1927
|
+
* discarding the `code` means the user never hears anything.
|
|
1928
|
+
*
|
|
1929
|
+
* PAK-required with `auth.user.password-reset.create`: caller must
|
|
1930
|
+
* instantiate `Auth` with
|
|
1891
1931
|
* `auth: { type: "apiKey", key: "pcft_live_..." }`. The
|
|
1892
1932
|
* kubb-generated `headers.authorization` slot is a stub — the
|
|
1893
1933
|
* HTTP client's auth middleware overrides whatever's passed.
|
|
@@ -1896,6 +1936,31 @@ var ConsumerScope = class {
|
|
|
1896
1936
|
{ appSlug: this.appSlug, data, headers: { authorization: "" } },
|
|
1897
1937
|
{ client: this.client }
|
|
1898
1938
|
),
|
|
1939
|
+
/**
|
|
1940
|
+
* Mint + dispatch a password-reset email via Mail in one call.
|
|
1941
|
+
* Returns `{ expires_at }` on success; the plaintext code is NOT
|
|
1942
|
+
* returned. Returns `{}` when the contact is missing or unverified
|
|
1943
|
+
* (same enumeration defence as {@link requestReset}).
|
|
1944
|
+
*
|
|
1945
|
+
* This is the counterpart to {@link sendVerificationEmail} for the
|
|
1946
|
+
* reset slot, and the method you want for a plain "forgot
|
|
1947
|
+
* password" flow — {@link requestReset} only mints, it does not
|
|
1948
|
+
* email.
|
|
1949
|
+
*
|
|
1950
|
+
* PAK-required with `auth.user.password-reset.send-email` —
|
|
1951
|
+
* distinct permission from the bare mint so customers can enable
|
|
1952
|
+
* mint without enabling outbound Mail traffic. Surfaces typed 412
|
|
1953
|
+
* precondition errors (e.g. `ENVOI_NOT_ENABLED`,
|
|
1954
|
+
* `ENVOI_TEMPLATE_NOT_CONFIGURED`) rather than failing silently.
|
|
1955
|
+
*/
|
|
1956
|
+
sendPasswordResetEmail: (data) => consumerAuthControllerSendPasswordResetEmail(
|
|
1957
|
+
{
|
|
1958
|
+
appSlug: this.appSlug,
|
|
1959
|
+
data,
|
|
1960
|
+
headers: { authorization: "" }
|
|
1961
|
+
},
|
|
1962
|
+
{ client: this.client }
|
|
1963
|
+
),
|
|
1899
1964
|
resetPassword: (data) => consumerAuthControllerResetPassword(
|
|
1900
1965
|
{ appSlug: this.appSlug, data },
|
|
1901
1966
|
{ client: this.client }
|