@ministryofmany/client 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +10 -0
- package/README.md +282 -0
- package/dist/auth-js.d.ts +18 -0
- package/dist/auth-js.js +27 -0
- package/dist/auth-js.js.map +1 -0
- package/dist/badges/index.d.ts +116 -0
- package/dist/badges/index.js +44 -0
- package/dist/badges/index.js.map +1 -0
- package/dist/chunk-CSD6YO64.js +206 -0
- package/dist/chunk-CSD6YO64.js.map +1 -0
- package/dist/chunk-R4XGCZVA.js +1 -0
- package/dist/chunk-R4XGCZVA.js.map +1 -0
- package/dist/chunk-U2JFQKFV.js +105 -0
- package/dist/chunk-U2JFQKFV.js.map +1 -0
- package/dist/index.d.ts +75 -0
- package/dist/index.js +231 -0
- package/dist/index.js.map +1 -0
- package/dist/types-BHY-mOJf.d.ts +56 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
This project is dual-licensed under either of:
|
|
2
|
+
|
|
3
|
+
- Apache License, Version 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
|
|
4
|
+
- MIT license (https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
at your option.
|
|
7
|
+
|
|
8
|
+
Unless you explicitly state otherwise, any contribution intentionally
|
|
9
|
+
submitted for inclusion in this project by you shall be dual licensed as
|
|
10
|
+
above, without any additional terms or conditions.
|
package/README.md
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# @ministryofmany/client
|
|
2
|
+
|
|
3
|
+
OIDC relying-party SDK for **Minister** — an OpenID Connect identity provider
|
|
4
|
+
that lets users authenticate _and_ disclose W3C verifiable-credential "badges"
|
|
5
|
+
(email-domain, age-over-N, residency, connected accounts, and more).
|
|
6
|
+
|
|
7
|
+
Use this in your app to:
|
|
8
|
+
|
|
9
|
+
- Run the authorization-code flow with PKCE (S256) against Minister.
|
|
10
|
+
- Verify the returned `id_token` (signature, issuer, audience, nonce).
|
|
11
|
+
- Extract and **signature-verify** the disclosed badges against Minister's
|
|
12
|
+
public keys, with holder-binding enforced.
|
|
13
|
+
|
|
14
|
+
Three ways to integrate: run the full flow yourself (`createMinisterClient`), verify tokens/badges on a backend (`createMinisterVerifier`), or plug into Auth.js (`@ministryofmany/client/auth-js`).
|
|
15
|
+
|
|
16
|
+
ESM-only. Runs on Node 20+, Deno, and edge runtimes (Vercel Edge, Cloudflare
|
|
17
|
+
Workers) — it uses the Web Crypto API and `fetch`, not `node:crypto`.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
pnpm add @ministryofmany/client
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`jose` and `zod` are runtime dependencies and are installed automatically.
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
28
|
+
|
|
29
|
+
Create one client and reuse it. `issuer` is Minister's origin.
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { createMinisterClient } from "@ministryofmany/client";
|
|
33
|
+
|
|
34
|
+
export const minister = createMinisterClient({
|
|
35
|
+
issuer: "https://ministry.id",
|
|
36
|
+
clientId: process.env.MINISTER_CLIENT_ID!,
|
|
37
|
+
clientSecret: process.env.MINISTER_CLIENT_SECRET, // omit for public/PKCE-only clients
|
|
38
|
+
redirectUri: "https://yourapp.example/auth/minister/callback",
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 1. Start — build the authorization URL and persist flow state
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import type { OidcFlowState } from "@ministryofmany/client";
|
|
46
|
+
|
|
47
|
+
export async function startLogin() {
|
|
48
|
+
const { verifier, challenge } = await minister.generatePkce();
|
|
49
|
+
const state = minister.randomToken();
|
|
50
|
+
const nonce = minister.randomToken();
|
|
51
|
+
|
|
52
|
+
// Ask for the badges your app needs. `openid` is required; the SDK does
|
|
53
|
+
// not add it for you. `badgeScope("age-over-21")` === "badge:age-over-21".
|
|
54
|
+
const url = await minister.getAuthorizationUrl({
|
|
55
|
+
scopes: [
|
|
56
|
+
"openid",
|
|
57
|
+
"profile",
|
|
58
|
+
minister.badgeScope("age-over-21"),
|
|
59
|
+
minister.badgeScope("email-domain"),
|
|
60
|
+
],
|
|
61
|
+
state,
|
|
62
|
+
nonce,
|
|
63
|
+
codeChallenge: challenge,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// YOU own persistence. Store this keyed by `state`; the SDK stores nothing.
|
|
67
|
+
const flow: OidcFlowState = {
|
|
68
|
+
state,
|
|
69
|
+
nonce,
|
|
70
|
+
codeVerifier: verifier,
|
|
71
|
+
expiresAt: Date.now() + 10 * 60_000, // 10 minutes
|
|
72
|
+
};
|
|
73
|
+
await saveFlow(state, flow); // your storage: signed cookie, KV, DB row, ...
|
|
74
|
+
|
|
75
|
+
return url; // redirect the user here (302)
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
> **You own the flow state, and you must consume it atomically by `state`.**
|
|
80
|
+
> On callback, look the record up by the returned `state`, **delete it in the
|
|
81
|
+
> same operation** (delete-on-read), and reject if it is missing or expired.
|
|
82
|
+
> This makes each `state`/`nonce` usable at most once, which is what defends
|
|
83
|
+
> the flow against CSRF and replay. The SDK deliberately stores nothing.
|
|
84
|
+
|
|
85
|
+
### 2. Callback — exchange the code for verified claims + badges
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
export async function handleCallback(req: Request) {
|
|
89
|
+
const url = new URL(req.url);
|
|
90
|
+
const code = url.searchParams.get("code");
|
|
91
|
+
const state = url.searchParams.get("state");
|
|
92
|
+
if (!code || !state) throw new Error("missing code/state");
|
|
93
|
+
|
|
94
|
+
// Atomic consume: fetch AND delete by state in one step.
|
|
95
|
+
const flow = await takeFlow(state);
|
|
96
|
+
if (!flow || flow.expiresAt < Date.now()) {
|
|
97
|
+
throw new Error("unknown or expired login flow");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const { claims, badges, rejected } = await minister.exchangeCode({
|
|
101
|
+
code,
|
|
102
|
+
codeVerifier: flow.codeVerifier,
|
|
103
|
+
expectedNonce: flow.nonce,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// `claims.sub` is a pairwise pseudonymous id — stable for this user at
|
|
107
|
+
// YOUR client, and different from what other RPs see.
|
|
108
|
+
// `badges` are already signature-verified and holder-bound.
|
|
109
|
+
const isAdult = badges.some((b) => b.type === "age-over-21");
|
|
110
|
+
|
|
111
|
+
// `rejected` holds any disclosed badges that failed verification (bad
|
|
112
|
+
// signature, expired, wrong issuer, ...). Login still succeeds; log/alert
|
|
113
|
+
// on these if a partner may be misconfigured.
|
|
114
|
+
|
|
115
|
+
await upsertUser({
|
|
116
|
+
ministerSub: claims.sub,
|
|
117
|
+
name: claims.name,
|
|
118
|
+
avatar: claims.picture,
|
|
119
|
+
isAdult,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// ... set your own session ...
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
`exchangeCode` throws `MinisterTokenError` if the token exchange fails or the
|
|
127
|
+
`id_token` signature / issuer / audience / nonce / expiry checks fail — map
|
|
128
|
+
that to a `401`. A disclosed badge that fails verification is **not** fatal:
|
|
129
|
+
it is dropped from `badges` and surfaced in `rejected`, and login proceeds.
|
|
130
|
+
|
|
131
|
+
### Verifying a badge received out of band
|
|
132
|
+
|
|
133
|
+
Badges can also reach you outside the OIDC flow (e.g. a Minister share link).
|
|
134
|
+
Verify any Minister VC JWT against Minister's public keys:
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
import { VcVerificationError } from "@ministryofmany/client";
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
const badge = await minister.verifyMinisterBadge(vcJwt);
|
|
141
|
+
// badge.type -> the badge slug, e.g. "email-domain"
|
|
142
|
+
// badge.claims -> schema-validated claims, e.g. { domain: "example.com" }
|
|
143
|
+
// badge.subject -> the holder's stable Minister DID (== credentialSubject.id);
|
|
144
|
+
// NOT the id_token `sub` (that is a per-RP pairwise value)
|
|
145
|
+
// badge.raw -> the original JWT, for storage/forwarding
|
|
146
|
+
} catch (err) {
|
|
147
|
+
if (err instanceof VcVerificationError) {
|
|
148
|
+
// invalid signature, wrong issuer, bad envelope, or holder-binding mismatch
|
|
149
|
+
}
|
|
150
|
+
throw err;
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Optionally validate the claim shape against the known badge vocabulary:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
import { getBadgeClaimSchema } from "@ministryofmany/client";
|
|
158
|
+
|
|
159
|
+
const schema = getBadgeClaimSchema("email-domain");
|
|
160
|
+
const parsed = schema?.safeParse(badge.claims);
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Verify on your backend (without running the flow)
|
|
164
|
+
|
|
165
|
+
If your app uses an OIDC library (or another service runs the flow) and you
|
|
166
|
+
just need to verify a Minister `id_token` and its badges, use the verifier —
|
|
167
|
+
no flow state, no redirect handling:
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
import { createMinisterVerifier } from "@ministryofmany/client";
|
|
171
|
+
|
|
172
|
+
const minister = createMinisterVerifier({
|
|
173
|
+
issuer: "https://ministry.id",
|
|
174
|
+
clientId: "your-client-id", // enables the id_token `aud` check (recommended)
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const claims = await minister.verifyIdToken(idToken); // throws MinisterTokenError on a bad token
|
|
178
|
+
// claims: { sub, name?, picture?, raw }
|
|
179
|
+
|
|
180
|
+
const { badges, rejected } = await minister.verifyBadges(idToken);
|
|
181
|
+
// badges: [{ type: "age-over-21", claims: { threshold: 21 }, subject, raw }, ...]
|
|
182
|
+
// rejected: [{ raw, error }] (badges that failed verification; never throws per-badge)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`verifyBadges` accepts either a raw `id_token` string (it verifies the wrapper
|
|
186
|
+
first) or an already-verified payload object (it trusts the wrapper and only
|
|
187
|
+
verifies the badge VCs). The verifier caches Minister's JWKS after the first
|
|
188
|
+
fetch. Pass `jwks` to inject a key in tests.
|
|
189
|
+
|
|
190
|
+
## With Auth.js (next-auth)
|
|
191
|
+
|
|
192
|
+
`@ministryofmany/client/auth-js` gives you a provider config and a badge helper you
|
|
193
|
+
hand to Auth.js through its documented extension points. We do **not** modify,
|
|
194
|
+
fork, or pin Auth.js — `@auth/core` is a types-only optional peer.
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
import NextAuth from "next-auth";
|
|
198
|
+
import { ministerProvider, ministerBadgesFromProfile } from "@ministryofmany/client/auth-js";
|
|
199
|
+
import { badgeScopes } from "@ministryofmany/client/badges";
|
|
200
|
+
|
|
201
|
+
export const { handlers, auth } = NextAuth({
|
|
202
|
+
providers: [
|
|
203
|
+
ministerProvider({
|
|
204
|
+
clientId: process.env.MINISTER_CLIENT_ID!,
|
|
205
|
+
clientSecret: process.env.MINISTER_CLIENT_SECRET, // omit for public clients
|
|
206
|
+
issuer: process.env.MINISTER_ISSUER!,
|
|
207
|
+
scopes: ["openid", "profile", ...badgeScopes(["age-over-18"])],
|
|
208
|
+
}),
|
|
209
|
+
],
|
|
210
|
+
callbacks: {
|
|
211
|
+
async jwt({ token, profile }) {
|
|
212
|
+
if (profile) {
|
|
213
|
+
const { badges } = await ministerBadgesFromProfile(profile, {
|
|
214
|
+
issuer: process.env.MINISTER_ISSUER!,
|
|
215
|
+
});
|
|
216
|
+
token.ministerBadges = badges;
|
|
217
|
+
}
|
|
218
|
+
return token;
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
`ministerProvider` returns a standard OIDC provider config; Auth.js verifies the
|
|
225
|
+
`id_token`, and `ministerBadgesFromProfile` verifies the nested badge VCs inside
|
|
226
|
+
your own callback.
|
|
227
|
+
|
|
228
|
+
### Subpath imports
|
|
229
|
+
|
|
230
|
+
- `@ministryofmany/client` — the main entry: flow client, verifier, errors, types, and the badge vocabulary.
|
|
231
|
+
- `@ministryofmany/client/badges` — the badge vocabulary alone (slugs, scopes, Zod claim schemas, `badgeScope`/`badgeScopes`/`badgeTypeOf`). Dependency-light; no jose pulled in. Useful for building scope lists or parsing claims in a UI.
|
|
232
|
+
- `@ministryofmany/client/auth-js` — the Auth.js helpers only (`ministerProvider`, `ministerBadgesFromProfile`).
|
|
233
|
+
|
|
234
|
+
## What "verified" means here
|
|
235
|
+
|
|
236
|
+
- **id_token:** EdDSA signature against Minister's JWKS, plus `iss` ==
|
|
237
|
+
configured issuer, `aud` == your `clientId`, and `nonce` == the value you
|
|
238
|
+
persisted at start, with `exp`/`iat` present and `exp` not in the past.
|
|
239
|
+
- **Each badge:** EdDSA signature against Minister's public keys, `iss` ==
|
|
240
|
+
`did:web:<minister-host>`, JWT `typ` == `vc+jwt`, a present and unexpired
|
|
241
|
+
`exp`, a well-formed `vc` envelope, and `credentialSubject.id` == the VC's
|
|
242
|
+
own `sub` (holder binding). A badge whose signature, issuer, type, expiry,
|
|
243
|
+
structure, or subject binding is wrong is rejected (dropped into `rejected`,
|
|
244
|
+
never thrown from `verifyBadges`).
|
|
245
|
+
|
|
246
|
+
> **Issuer-domain coupling (all badges rejected?).** The expected badge issuer
|
|
247
|
+
> is derived as `did:web:<host-of-your-configured-issuer>`. Minister signs badge
|
|
248
|
+
> VCs with `did:web:<MINISTER_ISSUER_DOMAIN>`. If the Minister deployment's
|
|
249
|
+
> `MINISTER_ISSUER_DOMAIN` host does not equal the OIDC issuer host, **every
|
|
250
|
+
> badge fails verification** and lands in `rejected` with an issuer mismatch
|
|
251
|
+
> (login and `id_token` verification are unaffected). If you see all badges
|
|
252
|
+
> rejected, check that Minister's `MINISTER_ISSUER_DOMAIN` host matches its
|
|
253
|
+
> OIDC issuer host.
|
|
254
|
+
|
|
255
|
+
## API
|
|
256
|
+
|
|
257
|
+
| Export | Purpose |
|
|
258
|
+
| --- | --- |
|
|
259
|
+
| `createMinisterClient(config)` | Build a flow client bound to one Minister + RP. |
|
|
260
|
+
| `client.getAuthorizationUrl(args)` | Discover the authorize endpoint and build the redirect URL. |
|
|
261
|
+
| `client.exchangeCode(args)` | Token exchange + verify id_token + verify badges. Returns `{ claims, badges, rejected }`. |
|
|
262
|
+
| `client.verifyMinisterBadge(vcJwt, opts?)` | Verify a single VC badge; `type` is a slug string (e.g. `"email-domain"`). |
|
|
263
|
+
| `client.generatePkce()` | PKCE S256 `{ verifier, challenge }`. |
|
|
264
|
+
| `client.randomToken(bytes?)` | URL-safe random `state` / `nonce`. |
|
|
265
|
+
| `client.badgeScope(slug)` | `"badge:<slug>"` helper. |
|
|
266
|
+
| `createMinisterVerifier(config)` | Configure-once verifier: `verifyIdToken`, `verifyBadges`, `verifyBadge`. |
|
|
267
|
+
| `verifyMinisterIdToken`, `verifyMinisterBadges`, `verifyMinisterBadge` | The standalone verification functions. |
|
|
268
|
+
| `badgeScope`, `badgeScopes`, `badgeTypeOf`, `knownBadgeTypes`, `getBadgeClaimSchema` | Badge vocabulary helpers. |
|
|
269
|
+
| `MinisterTokenError` | Thrown when an `id_token` itself fails verification. |
|
|
270
|
+
| `OidcFlowState`, `MinisterClaims`, `VerifiedBadge`, `BadgesResult`, `RejectedBadge`, ... | Public types. |
|
|
271
|
+
| `VcVerificationError`, `OidcError`, `MinisterTokenError` | Error classes. |
|
|
272
|
+
|
|
273
|
+
### Testing without the network
|
|
274
|
+
|
|
275
|
+
`exchangeCode` and `verifyMinisterBadge` accept injectable key sources so your
|
|
276
|
+
tests never hit Minister: pass `idTokenKey` / `badgeKey` (to `exchangeCode`) or
|
|
277
|
+
`{ key }` (to `verifyMinisterBadge`) — a `KeyLike`, a `Uint8Array`, or a `jose`
|
|
278
|
+
key-resolver function. The default is a remote JWKS fetched from Minister.
|
|
279
|
+
|
|
280
|
+
## License
|
|
281
|
+
|
|
282
|
+
MIT OR Apache-2.0
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { OIDCConfig } from '@auth/core/providers';
|
|
2
|
+
import { JWTPayload } from 'jose';
|
|
3
|
+
import { K as KeyInput, B as BadgesResult } from './types-BHY-mOJf.js';
|
|
4
|
+
|
|
5
|
+
interface MinisterProviderOptions {
|
|
6
|
+
clientId: string;
|
|
7
|
+
clientSecret?: string;
|
|
8
|
+
issuer: string;
|
|
9
|
+
scopes?: string[];
|
|
10
|
+
}
|
|
11
|
+
declare function ministerProvider(options: MinisterProviderOptions): OIDCConfig<Record<string, unknown>>;
|
|
12
|
+
interface MinisterBadgesFromProfileOptions {
|
|
13
|
+
issuer: string;
|
|
14
|
+
key?: KeyInput;
|
|
15
|
+
}
|
|
16
|
+
declare function ministerBadgesFromProfile(profile: JWTPayload | Record<string, unknown>, options: MinisterBadgesFromProfileOptions): Promise<BadgesResult>;
|
|
17
|
+
|
|
18
|
+
export { type MinisterBadgesFromProfileOptions, type MinisterProviderOptions, ministerBadgesFromProfile, ministerProvider };
|
package/dist/auth-js.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
verifyMinisterBadges
|
|
3
|
+
} from "./chunk-CSD6YO64.js";
|
|
4
|
+
import "./chunk-U2JFQKFV.js";
|
|
5
|
+
|
|
6
|
+
// src/auth-js.ts
|
|
7
|
+
function ministerProvider(options) {
|
|
8
|
+
const scopes = options.scopes ?? ["openid", "profile"];
|
|
9
|
+
return {
|
|
10
|
+
id: "minister",
|
|
11
|
+
name: "Minister",
|
|
12
|
+
type: "oidc",
|
|
13
|
+
issuer: options.issuer,
|
|
14
|
+
clientId: options.clientId,
|
|
15
|
+
clientSecret: options.clientSecret,
|
|
16
|
+
authorization: { params: { scope: scopes.join(" ") } },
|
|
17
|
+
checks: ["pkce", "state", "nonce"]
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function ministerBadgesFromProfile(profile, options) {
|
|
21
|
+
return verifyMinisterBadges(profile, { issuer: options.issuer, key: options.key });
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
ministerBadgesFromProfile,
|
|
25
|
+
ministerProvider
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=auth-js.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/auth-js.ts"],"sourcesContent":["// @minister/client/auth-js — non-invasive helpers for Auth.js (next-auth).\n// We do NOT modify Auth.js; these are values/functions you hand to it via\n// its documented extension points. `@auth/core` is a types-only optional\n// peer used solely for the OIDCConfig return type.\nimport type { OIDCConfig } from \"@auth/core/providers\";\nimport type { JWTPayload } from \"jose\";\nimport { verifyMinisterBadges } from \"./verify-badges\";\nimport type { KeyInput, BadgesResult } from \"./types\";\n\nexport interface MinisterProviderOptions {\n clientId: string;\n clientSecret?: string;\n issuer: string;\n // Defaults to [\"openid\", \"profile\"]. Add badge:<type> scopes to request badges.\n scopes?: string[];\n}\n\n// Build the Auth.js OIDC provider config object. Drop it into\n// NextAuth({ providers: [ministerProvider({...})] }). Auth.js owns the\n// flow, session, and cookies; this is only its provider configuration.\nexport function ministerProvider(options: MinisterProviderOptions): OIDCConfig<Record<string, unknown>> {\n const scopes = options.scopes ?? [\"openid\", \"profile\"];\n return {\n id: \"minister\",\n name: \"Minister\",\n type: \"oidc\",\n issuer: options.issuer,\n clientId: options.clientId,\n clientSecret: options.clientSecret,\n authorization: { params: { scope: scopes.join(\" \") } },\n checks: [\"pkce\", \"state\", \"nonce\"],\n };\n}\n\nexport interface MinisterBadgesFromProfileOptions {\n issuer: string;\n key?: KeyInput;\n}\n\n// Verify the minister_badges in an Auth.js `profile` (already-verified\n// id_token payload). Call inside your own jwt/profile callback.\nexport function ministerBadgesFromProfile(\n profile: JWTPayload | Record<string, unknown>,\n options: MinisterBadgesFromProfileOptions,\n): Promise<BadgesResult> {\n return verifyMinisterBadges(profile as JWTPayload, { issuer: options.issuer, key: options.key });\n}\n"],"mappings":";;;;;;AAoBO,SAAS,iBAAiB,SAAuE;AACtG,QAAM,SAAS,QAAQ,UAAU,CAAC,UAAU,SAAS;AACrD,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ,QAAQ;AAAA,IAChB,UAAU,QAAQ;AAAA,IAClB,cAAc,QAAQ;AAAA,IACtB,eAAe,EAAE,QAAQ,EAAE,OAAO,OAAO,KAAK,GAAG,EAAE,EAAE;AAAA,IACrD,QAAQ,CAAC,QAAQ,SAAS,OAAO;AAAA,EACnC;AACF;AASO,SAAS,0BACd,SACA,SACuB;AACvB,SAAO,qBAAqB,SAAuB,EAAE,QAAQ,QAAQ,QAAQ,KAAK,QAAQ,IAAI,CAAC;AACjG;","names":[]}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
declare const EmailDomainClaims: z.ZodObject<{
|
|
4
|
+
domain: z.ZodString;
|
|
5
|
+
}, "strip", z.ZodTypeAny, {
|
|
6
|
+
domain: string;
|
|
7
|
+
}, {
|
|
8
|
+
domain: string;
|
|
9
|
+
}>;
|
|
10
|
+
type EmailDomainClaims = z.infer<typeof EmailDomainClaims>;
|
|
11
|
+
declare const EmailExactClaims: z.ZodObject<{
|
|
12
|
+
email: z.ZodString;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
email: string;
|
|
15
|
+
}, {
|
|
16
|
+
email: string;
|
|
17
|
+
}>;
|
|
18
|
+
type EmailExactClaims = z.infer<typeof EmailExactClaims>;
|
|
19
|
+
declare const OAUTH_PROVIDERS: readonly ["github", "google", "discord"];
|
|
20
|
+
declare const OAuthAccountClaims: z.ZodObject<{
|
|
21
|
+
provider: z.ZodEnum<["github", "google", "discord"]>;
|
|
22
|
+
accountId: z.ZodString;
|
|
23
|
+
handle: z.ZodOptional<z.ZodString>;
|
|
24
|
+
}, "strip", z.ZodTypeAny, {
|
|
25
|
+
provider: "github" | "google" | "discord";
|
|
26
|
+
accountId: string;
|
|
27
|
+
handle?: string | undefined;
|
|
28
|
+
}, {
|
|
29
|
+
provider: "github" | "google" | "discord";
|
|
30
|
+
accountId: string;
|
|
31
|
+
handle?: string | undefined;
|
|
32
|
+
}>;
|
|
33
|
+
type OAuthAccountClaims = z.infer<typeof OAuthAccountClaims>;
|
|
34
|
+
declare const AGE_THRESHOLDS: readonly [16, 18, 21, 25, 30, 35, 40, 45, 55, 65];
|
|
35
|
+
type AgeThreshold = (typeof AGE_THRESHOLDS)[number];
|
|
36
|
+
declare const AgeOverClaimsFor: (threshold: AgeThreshold) => z.ZodObject<{
|
|
37
|
+
threshold: z.ZodLiteral<16 | 18 | 21 | 25 | 30 | 35 | 40 | 45 | 55 | 65>;
|
|
38
|
+
}, "strip", z.ZodTypeAny, {
|
|
39
|
+
threshold: 16 | 18 | 21 | 25 | 30 | 35 | 40 | 45 | 55 | 65;
|
|
40
|
+
}, {
|
|
41
|
+
threshold: 16 | 18 | 21 | 25 | 30 | 35 | 40 | 45 | 55 | 65;
|
|
42
|
+
}>;
|
|
43
|
+
declare const ResidencyCountryClaims: z.ZodObject<{
|
|
44
|
+
country: z.ZodString;
|
|
45
|
+
}, "strip", z.ZodTypeAny, {
|
|
46
|
+
country: string;
|
|
47
|
+
}, {
|
|
48
|
+
country: string;
|
|
49
|
+
}>;
|
|
50
|
+
type ResidencyCountryClaims = z.infer<typeof ResidencyCountryClaims>;
|
|
51
|
+
declare const ResidencyStateClaims: z.ZodObject<{
|
|
52
|
+
country: z.ZodString;
|
|
53
|
+
state: z.ZodString;
|
|
54
|
+
}, "strip", z.ZodTypeAny, {
|
|
55
|
+
state: string;
|
|
56
|
+
country: string;
|
|
57
|
+
}, {
|
|
58
|
+
state: string;
|
|
59
|
+
country: string;
|
|
60
|
+
}>;
|
|
61
|
+
type ResidencyStateClaims = z.infer<typeof ResidencyStateClaims>;
|
|
62
|
+
declare const ResidencyCityClaims: z.ZodObject<{
|
|
63
|
+
country: z.ZodString;
|
|
64
|
+
state: z.ZodString;
|
|
65
|
+
city: z.ZodString;
|
|
66
|
+
}, "strip", z.ZodTypeAny, {
|
|
67
|
+
state: string;
|
|
68
|
+
country: string;
|
|
69
|
+
city: string;
|
|
70
|
+
}, {
|
|
71
|
+
state: string;
|
|
72
|
+
country: string;
|
|
73
|
+
city: string;
|
|
74
|
+
}>;
|
|
75
|
+
type ResidencyCityClaims = z.infer<typeof ResidencyCityClaims>;
|
|
76
|
+
declare const InviteCodeClaims: z.ZodObject<{
|
|
77
|
+
label: z.ZodString;
|
|
78
|
+
}, "strip", z.ZodTypeAny, {
|
|
79
|
+
label: string;
|
|
80
|
+
}, {
|
|
81
|
+
label: string;
|
|
82
|
+
}>;
|
|
83
|
+
type InviteCodeClaims = z.infer<typeof InviteCodeClaims>;
|
|
84
|
+
declare const TlsnAttestationClaims: z.ZodObject<{
|
|
85
|
+
domain: z.ZodString;
|
|
86
|
+
claim: z.ZodString;
|
|
87
|
+
}, "strict", z.ZodTypeAny, {
|
|
88
|
+
domain: string;
|
|
89
|
+
claim: string;
|
|
90
|
+
}, {
|
|
91
|
+
domain: string;
|
|
92
|
+
claim: string;
|
|
93
|
+
}>;
|
|
94
|
+
type TlsnAttestationClaims = z.infer<typeof TlsnAttestationClaims>;
|
|
95
|
+
|
|
96
|
+
interface BadgeTypeDef {
|
|
97
|
+
slug: string;
|
|
98
|
+
credentialType: string;
|
|
99
|
+
scope: string;
|
|
100
|
+
claims: z.ZodType<unknown>;
|
|
101
|
+
}
|
|
102
|
+
declare function defineBadgeType(input: {
|
|
103
|
+
slug: string;
|
|
104
|
+
credentialType: string;
|
|
105
|
+
claims: z.ZodType<unknown>;
|
|
106
|
+
}): BadgeTypeDef;
|
|
107
|
+
declare const BADGE_TYPES: Record<string, BadgeTypeDef>;
|
|
108
|
+
declare function slugForCredentialType(credentialType: string): string | undefined;
|
|
109
|
+
|
|
110
|
+
declare function badgeScope(slug: string): string;
|
|
111
|
+
declare function badgeScopes(slugs: string[]): string[];
|
|
112
|
+
declare function badgeTypeOf(vcType: string[]): string | undefined;
|
|
113
|
+
declare function getBadgeClaimSchema(slug: string): z.ZodType<unknown> | undefined;
|
|
114
|
+
declare function knownBadgeTypes(): string[];
|
|
115
|
+
|
|
116
|
+
export { AGE_THRESHOLDS, AgeOverClaimsFor, type AgeThreshold, BADGE_TYPES, type BadgeTypeDef, EmailDomainClaims, EmailExactClaims, InviteCodeClaims, OAUTH_PROVIDERS, OAuthAccountClaims, ResidencyCityClaims, ResidencyCountryClaims, ResidencyStateClaims, TlsnAttestationClaims, badgeScope, badgeScopes, badgeTypeOf, defineBadgeType, getBadgeClaimSchema, knownBadgeTypes, slugForCredentialType };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import "../chunk-R4XGCZVA.js";
|
|
2
|
+
import {
|
|
3
|
+
AGE_THRESHOLDS,
|
|
4
|
+
AgeOverClaimsFor,
|
|
5
|
+
BADGE_TYPES,
|
|
6
|
+
EmailDomainClaims,
|
|
7
|
+
EmailExactClaims,
|
|
8
|
+
InviteCodeClaims,
|
|
9
|
+
OAUTH_PROVIDERS,
|
|
10
|
+
OAuthAccountClaims,
|
|
11
|
+
ResidencyCityClaims,
|
|
12
|
+
ResidencyCountryClaims,
|
|
13
|
+
ResidencyStateClaims,
|
|
14
|
+
TlsnAttestationClaims,
|
|
15
|
+
badgeScope,
|
|
16
|
+
badgeScopes,
|
|
17
|
+
badgeTypeOf,
|
|
18
|
+
defineBadgeType,
|
|
19
|
+
getBadgeClaimSchema,
|
|
20
|
+
knownBadgeTypes,
|
|
21
|
+
slugForCredentialType
|
|
22
|
+
} from "../chunk-U2JFQKFV.js";
|
|
23
|
+
export {
|
|
24
|
+
AGE_THRESHOLDS,
|
|
25
|
+
AgeOverClaimsFor,
|
|
26
|
+
BADGE_TYPES,
|
|
27
|
+
EmailDomainClaims,
|
|
28
|
+
EmailExactClaims,
|
|
29
|
+
InviteCodeClaims,
|
|
30
|
+
OAUTH_PROVIDERS,
|
|
31
|
+
OAuthAccountClaims,
|
|
32
|
+
ResidencyCityClaims,
|
|
33
|
+
ResidencyCountryClaims,
|
|
34
|
+
ResidencyStateClaims,
|
|
35
|
+
TlsnAttestationClaims,
|
|
36
|
+
badgeScope,
|
|
37
|
+
badgeScopes,
|
|
38
|
+
badgeTypeOf,
|
|
39
|
+
defineBadgeType,
|
|
40
|
+
getBadgeClaimSchema,
|
|
41
|
+
knownBadgeTypes,
|
|
42
|
+
slugForCredentialType
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|