@micacms/auth-oidc 0.2.2 → 0.4.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 +1 -1
- package/dist/admission.d.ts +5 -4
- package/dist/admission.d.ts.map +1 -1
- package/dist/admission.js +22 -15
- package/dist/admission.js.map +1 -1
- package/dist/config.d.ts +8 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +41 -4
- package/dist/config.js.map +1 -1
- package/dist/gate.d.ts +4 -5
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js +14 -13
- package/dist/gate.js.map +1 -1
- package/dist/index.d.ts +4 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -11
- package/dist/index.js.map +1 -1
- package/dist/oidc.d.ts +9 -2
- package/dist/oidc.d.ts.map +1 -1
- package/dist/oidc.js +22 -9
- package/dist/oidc.js.map +1 -1
- package/dist/return-to.d.ts +8 -0
- package/dist/return-to.d.ts.map +1 -0
- package/dist/return-to.js +24 -0
- package/dist/return-to.js.map +1 -0
- package/dist/routes.d.ts +2 -2
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +33 -23
- package/dist/routes.js.map +1 -1
- package/dist/session.d.ts +58 -26
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +137 -72
- package/dist/session.js.map +1 -1
- package/package.json +4 -4
- package/dist/sessions-repository.d.ts +0 -56
- package/dist/sessions-repository.d.ts.map +0 -1
- package/dist/sessions-repository.js +0 -96
- package/dist/sessions-repository.js.map +0 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> **Experimental.** Pre-1.0: the API can still change without notice.
|
|
4
4
|
|
|
5
5
|
The server-only OIDC gate for Mica: the authorization code flow with PKCE,
|
|
6
|
-
sessions in
|
|
6
|
+
sessions in an encrypted cookie, admission rules over provider claims, and the middleware
|
|
7
7
|
gate the runtime mounts in front of the admin API.
|
|
8
8
|
|
|
9
9
|
It is a dependency of `@micacms/self-hosted` and of nothing else. In
|
package/dist/admission.d.ts
CHANGED
|
@@ -11,13 +11,14 @@
|
|
|
11
11
|
*
|
|
12
12
|
* MICA_ADMIT_GROUP=mica-editors a claim the provider sends
|
|
13
13
|
* MICA_ADMIT_DOMAIN=example.com every verified address there
|
|
14
|
+
* MICA_ADMIT_EMAILS=alice@gmail.com these verified addresses
|
|
14
15
|
* MICA_ADMIT_SUBJECTS=https://id.example.com|a1b2c3
|
|
15
16
|
*
|
|
16
17
|
* The group rule is the one to grow into. Adding an editor is then a group
|
|
17
18
|
* change in the identity provider — where the operator already manages
|
|
18
19
|
* joiners and leavers — and Mica is not touched, not restarted, and holds no
|
|
19
|
-
* copy of the list to go stale. The
|
|
20
|
-
* groups,
|
|
20
|
+
* copy of the list to go stale. The email list exists for a provider with no
|
|
21
|
+
* groups, such as Google; the subject list for one that verifies no addresses.
|
|
21
22
|
*
|
|
22
23
|
* What this costs, and it is a real cost: removing somebody from a group at
|
|
23
24
|
* the provider does not take effect until their next sign-in, because the
|
|
@@ -27,7 +28,7 @@
|
|
|
27
28
|
* decision in docs/decisions.md.
|
|
28
29
|
*/
|
|
29
30
|
import type { AuthConfig } from "./config.js";
|
|
30
|
-
import type { SessionIdentity } from "./
|
|
31
|
+
import type { SessionIdentity } from "./session.js";
|
|
31
32
|
export type AdmissionResult = {
|
|
32
33
|
admitted: true;
|
|
33
34
|
} | {
|
|
@@ -39,5 +40,5 @@ export interface AdmissionPolicy {
|
|
|
39
40
|
readonly summary: string;
|
|
40
41
|
admits(identity: SessionIdentity): AdmissionResult;
|
|
41
42
|
}
|
|
42
|
-
export declare function createAdmissionPolicy(config: Pick<AuthConfig, "admitGroups" | "admitDomains" | "admitSubjects">): AdmissionPolicy;
|
|
43
|
+
export declare function createAdmissionPolicy(config: Pick<AuthConfig, "admitGroups" | "admitDomains" | "admitEmails" | "admitSubjects">): AdmissionPolicy;
|
|
43
44
|
//# sourceMappingURL=admission.d.ts.map
|
package/dist/admission.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../src/admission.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../src/admission.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,MAAM,eAAe,GAAG;IAAE,QAAQ,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvF,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,QAAQ,EAAE,eAAe,GAAG,eAAe,CAAC;CACpD;AAsCD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,aAAa,GAAG,cAAc,GAAG,aAAa,GAAG,eAAe,CAAC,GACzF,eAAe,CAsDjB"}
|
package/dist/admission.js
CHANGED
|
@@ -11,13 +11,14 @@
|
|
|
11
11
|
*
|
|
12
12
|
* MICA_ADMIT_GROUP=mica-editors a claim the provider sends
|
|
13
13
|
* MICA_ADMIT_DOMAIN=example.com every verified address there
|
|
14
|
+
* MICA_ADMIT_EMAILS=alice@gmail.com these verified addresses
|
|
14
15
|
* MICA_ADMIT_SUBJECTS=https://id.example.com|a1b2c3
|
|
15
16
|
*
|
|
16
17
|
* The group rule is the one to grow into. Adding an editor is then a group
|
|
17
18
|
* change in the identity provider — where the operator already manages
|
|
18
19
|
* joiners and leavers — and Mica is not touched, not restarted, and holds no
|
|
19
|
-
* copy of the list to go stale. The
|
|
20
|
-
* groups,
|
|
20
|
+
* copy of the list to go stale. The email list exists for a provider with no
|
|
21
|
+
* groups, such as Google; the subject list for one that verifies no addresses.
|
|
21
22
|
*
|
|
22
23
|
* What this costs, and it is a real cost: removing somebody from a group at
|
|
23
24
|
* the provider does not take effect until their next sign-in, because the
|
|
@@ -27,17 +28,16 @@
|
|
|
27
28
|
* decision in docs/decisions.md.
|
|
28
29
|
*/
|
|
29
30
|
/**
|
|
30
|
-
* The
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* hold one in turn. Keying admission on an address is therefore a standing
|
|
34
|
-
* offer to whoever holds it next, which is a well-trodden route to account
|
|
35
|
-
* takeover. The issuer is part of the key because a subject is only unique
|
|
36
|
-
* within the provider that issued it.
|
|
31
|
+
* The strictest rule: the subject never changes and is never reassigned. The
|
|
32
|
+
* issuer is part of the key because a subject is only unique within the
|
|
33
|
+
* provider that issued it.
|
|
37
34
|
*/
|
|
38
35
|
function matchesSubject(identity, entries) {
|
|
39
36
|
return entries.some((entry) => entry.issuer === identity.issuer && entry.subject === identity.subject);
|
|
40
37
|
}
|
|
38
|
+
function matchesEmail(identity, emails) {
|
|
39
|
+
return emails.includes(identity.email.toLowerCase());
|
|
40
|
+
}
|
|
41
41
|
function matchesDomain(identity, domains) {
|
|
42
42
|
const at = identity.email.lastIndexOf("@");
|
|
43
43
|
if (at < 0)
|
|
@@ -56,10 +56,11 @@ function matchesGroup(identity, groups) {
|
|
|
56
56
|
return groups.some((group) => held.has(group.replace(/^\//, "")));
|
|
57
57
|
}
|
|
58
58
|
export function createAdmissionPolicy(config) {
|
|
59
|
-
const { admitGroups, admitDomains, admitSubjects } = config;
|
|
59
|
+
const { admitGroups, admitDomains, admitEmails, admitSubjects } = config;
|
|
60
60
|
const summary = [
|
|
61
61
|
admitGroups.length > 0 ? `group=${admitGroups.join("|")}` : null,
|
|
62
62
|
admitDomains.length > 0 ? `domain=${admitDomains.join("|")}` : null,
|
|
63
|
+
admitEmails.length > 0 ? `emails=${admitEmails.length}` : null,
|
|
63
64
|
admitSubjects.length > 0 ? `subjects=${admitSubjects.length}` : null,
|
|
64
65
|
]
|
|
65
66
|
.filter(Boolean)
|
|
@@ -73,22 +74,28 @@ export function createAdmissionPolicy(config) {
|
|
|
73
74
|
return { admitted: true };
|
|
74
75
|
if (matchesGroup(identity, admitGroups))
|
|
75
76
|
return { admitted: true };
|
|
76
|
-
|
|
77
|
+
const byEmail = matchesEmail(identity, admitEmails);
|
|
78
|
+
if (byEmail || matchesDomain(identity, admitDomains)) {
|
|
77
79
|
/**
|
|
78
|
-
*
|
|
80
|
+
* An email or domain rule trusts the provider to have checked the address.
|
|
79
81
|
*
|
|
80
82
|
* Where a provider allows self-registration, an unverified address is
|
|
81
83
|
* a claim the person typed. Admitting on that would let anybody enter
|
|
82
|
-
*
|
|
84
|
+
* an address they do not hold, so the rule refuses and says why — the
|
|
83
85
|
* operator can turn verification on, or use a group or subject rule
|
|
84
86
|
* instead.
|
|
87
|
+
*
|
|
88
|
+
* What remains is reassignment: an organisation that gives a former
|
|
89
|
+
* editor's address to somebody new gives them this site too. Public
|
|
90
|
+
* providers such as Gmail never reuse an address; the trade is
|
|
91
|
+
* recorded in docs/decisions.md.
|
|
85
92
|
*/
|
|
86
93
|
if (identity.emailVerified)
|
|
87
94
|
return { admitted: true };
|
|
88
95
|
return {
|
|
89
96
|
admitted: false,
|
|
90
|
-
reason: `${identity.email} is
|
|
91
|
-
"does not report the address as verified.",
|
|
97
|
+
reason: `${identity.email} is ${byEmail ? "an admitted address" : "in an admitted domain"}, ` +
|
|
98
|
+
"but the identity provider does not report the address as verified.",
|
|
92
99
|
};
|
|
93
100
|
}
|
|
94
101
|
return {
|
package/dist/admission.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admission.js","sourceRoot":"","sources":["../src/admission.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"admission.js","sourceRoot":"","sources":["../src/admission.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -28,11 +28,13 @@ export declare const authEnv: {
|
|
|
28
28
|
/**
|
|
29
29
|
* Who may edit this site. Authentication says who somebody is; these say
|
|
30
30
|
* whether that person gets in. At least one is required — the composition
|
|
31
|
-
* refuses to start without one. Comma-separated, all
|
|
31
|
+
* refuses to start without one. Comma-separated, all four.
|
|
32
32
|
*/
|
|
33
33
|
MICA_ADMIT_GROUP: z.ZodOptional<z.ZodString>;
|
|
34
34
|
MICA_ADMIT_DOMAIN: z.ZodOptional<z.ZodString>;
|
|
35
|
-
/**
|
|
35
|
+
/** Verified addresses — the list for a provider with no groups, such as Google. */
|
|
36
|
+
MICA_ADMIT_EMAILS: z.ZodOptional<z.ZodString>;
|
|
37
|
+
/** `issuer|subject` pairs — see admission.ts. */
|
|
36
38
|
MICA_ADMIT_SUBJECTS: z.ZodOptional<z.ZodString>;
|
|
37
39
|
/** Signs session cookies. Rotating it invalidates every session. */
|
|
38
40
|
SESSION_SECRET: z.ZodOptional<z.ZodString>;
|
|
@@ -55,6 +57,7 @@ declare const authSchema: z.ZodObject<{
|
|
|
55
57
|
MICA_OIDC_GROUPS_CLAIM: z.ZodDefault<z.ZodString>;
|
|
56
58
|
MICA_ADMIT_GROUP: z.ZodOptional<z.ZodString>;
|
|
57
59
|
MICA_ADMIT_DOMAIN: z.ZodOptional<z.ZodString>;
|
|
60
|
+
MICA_ADMIT_EMAILS: z.ZodOptional<z.ZodString>;
|
|
58
61
|
MICA_ADMIT_SUBJECTS: z.ZodOptional<z.ZodString>;
|
|
59
62
|
SESSION_SECRET: z.ZodOptional<z.ZodString>;
|
|
60
63
|
SESSION_TTL_HOURS: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
@@ -75,6 +78,7 @@ export declare function deriveAuth<T extends AuthEnv & {
|
|
|
75
78
|
oidcAllowInsecure: boolean;
|
|
76
79
|
admitGroups: string[];
|
|
77
80
|
admitDomains: string[];
|
|
81
|
+
admitEmails: string[];
|
|
78
82
|
admitSubjects: {
|
|
79
83
|
issuer: string;
|
|
80
84
|
subject: string;
|
|
@@ -93,6 +97,7 @@ export interface AuthConfig {
|
|
|
93
97
|
oidcAllowInsecure: boolean;
|
|
94
98
|
admitGroups: string[];
|
|
95
99
|
admitDomains: string[];
|
|
100
|
+
admitEmails: string[];
|
|
96
101
|
admitSubjects: Array<{
|
|
97
102
|
issuer: string;
|
|
98
103
|
subject: string;
|
|
@@ -117,6 +122,7 @@ export declare function requireAuthConfig(config: {
|
|
|
117
122
|
MICA_OIDC_CLIENT_ID?: string | undefined;
|
|
118
123
|
admitGroups: string[];
|
|
119
124
|
admitDomains: string[];
|
|
125
|
+
admitEmails: string[];
|
|
120
126
|
admitSubjects: Array<{
|
|
121
127
|
issuer: string;
|
|
122
128
|
subject: string;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,OAAO;IAClB;;;;OAIG;;;IAGH,iDAAiD;;;IAGjD;;;;;OAKG;;IAGH;;;;OAIG;;;IAGH,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,OAAO;IAClB;;;;OAIG;;;IAGH,iDAAiD;;;IAGjD;;;;;OAKG;;IAGH;;;;OAIG;;;IAGH,mFAAmF;;IAEnF,iDAAiD;;IAGjD,oEAAoE;;IAEpE;;;;;OAKG;;;;;CAUJ,CAAC;AAEF,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;iBAAoB,CAAC;AACrC,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEjD,2EAA2E;AAC3E,wBAAgB,UAAU,CAAC,CAAC,SAAS,OAAO,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,EAC1F,GAAG,EAAE,CAAC;IAIJ;;;OAGG;;;;;;;;;;EAsBN;AAED,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,uBAAuB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7C,eAAe,EAAE,MAAM,CAAC;IACxB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1D,8EAA8E;IAC9E,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;CACzB;AA0BD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3D,GAAG,IAAI,CA4DP"}
|
package/dist/config.js
CHANGED
|
@@ -29,11 +29,13 @@ export const authEnv = {
|
|
|
29
29
|
/**
|
|
30
30
|
* Who may edit this site. Authentication says who somebody is; these say
|
|
31
31
|
* whether that person gets in. At least one is required — the composition
|
|
32
|
-
* refuses to start without one. Comma-separated, all
|
|
32
|
+
* refuses to start without one. Comma-separated, all four.
|
|
33
33
|
*/
|
|
34
34
|
MICA_ADMIT_GROUP: z.string().optional(),
|
|
35
35
|
MICA_ADMIT_DOMAIN: z.string().optional(),
|
|
36
|
-
/**
|
|
36
|
+
/** Verified addresses — the list for a provider with no groups, such as Google. */
|
|
37
|
+
MICA_ADMIT_EMAILS: z.string().optional(),
|
|
38
|
+
/** `issuer|subject` pairs — see admission.ts. */
|
|
37
39
|
MICA_ADMIT_SUBJECTS: z.string().optional(),
|
|
38
40
|
/** Signs session cookies. Rotating it invalidates every session. */
|
|
39
41
|
SESSION_SECRET: z.string().min(32).optional(),
|
|
@@ -67,6 +69,7 @@ export function deriveAuth(env) {
|
|
|
67
69
|
// Lowercased: a domain is case-insensitive, and an operator who writes
|
|
68
70
|
// `Example.com` means the same thing the provider spells `example.com`.
|
|
69
71
|
admitDomains: list(env.MICA_ADMIT_DOMAIN).map((domain) => domain.toLowerCase().replace(/^@/, "")),
|
|
72
|
+
admitEmails: list(env.MICA_ADMIT_EMAILS).map((email) => email.toLowerCase()),
|
|
70
73
|
admitSubjects: list(env.MICA_ADMIT_SUBJECTS).map((entry) => {
|
|
71
74
|
const separator = entry.indexOf("|");
|
|
72
75
|
return {
|
|
@@ -79,6 +82,29 @@ export function deriveAuth(env) {
|
|
|
79
82
|
cookieSecure: env.MICA_PUBLIC_URL.startsWith("https://"),
|
|
80
83
|
};
|
|
81
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Domains where anybody can register an address. A domain rule naming one
|
|
87
|
+
* admits the public, so it is refused; name the addresses instead.
|
|
88
|
+
*/
|
|
89
|
+
const PUBLIC_EMAIL_DOMAINS = new Set([
|
|
90
|
+
"gmail.com",
|
|
91
|
+
"googlemail.com",
|
|
92
|
+
"outlook.com",
|
|
93
|
+
"hotmail.com",
|
|
94
|
+
"live.com",
|
|
95
|
+
"msn.com",
|
|
96
|
+
"yahoo.com",
|
|
97
|
+
"icloud.com",
|
|
98
|
+
"me.com",
|
|
99
|
+
"aol.com",
|
|
100
|
+
"proton.me",
|
|
101
|
+
"protonmail.com",
|
|
102
|
+
"gmx.com",
|
|
103
|
+
"gmx.net",
|
|
104
|
+
"gmx.de",
|
|
105
|
+
"gmx.ch",
|
|
106
|
+
"web.de",
|
|
107
|
+
]);
|
|
82
108
|
/**
|
|
83
109
|
* The refusals that make a deployment honest before it serves a request.
|
|
84
110
|
*
|
|
@@ -96,23 +122,34 @@ export function requireAuthConfig(config) {
|
|
|
96
122
|
}
|
|
97
123
|
if (config.admitGroups.length === 0 &&
|
|
98
124
|
config.admitDomains.length === 0 &&
|
|
125
|
+
config.admitEmails.length === 0 &&
|
|
99
126
|
config.admitSubjects.length === 0) {
|
|
100
127
|
throw new ConfigError("Nothing says who may edit this site.\n" +
|
|
101
128
|
" Authentication is not admission: your provider will happily vouch for\n" +
|
|
102
129
|
" everybody it knows. Set at least one of these:\n\n" +
|
|
103
130
|
" MICA_ADMIT_GROUP=mica-editors a claim your provider sends\n" +
|
|
104
131
|
" MICA_ADMIT_DOMAIN=example.com every verified address there\n" +
|
|
132
|
+
" MICA_ADMIT_EMAILS=alice@gmail.com these verified addresses\n" +
|
|
105
133
|
" MICA_ADMIT_SUBJECTS=https://id.example.com|a1b2c3\n\n" +
|
|
106
134
|
" The group rule is the one to grow into: adding an editor is then a\n" +
|
|
107
135
|
" change in the identity provider, and Mica is not touched.");
|
|
108
136
|
}
|
|
137
|
+
const open = config.admitDomains.filter((domain) => PUBLIC_EMAIL_DOMAINS.has(domain));
|
|
138
|
+
if (open.length > 0) {
|
|
139
|
+
throw new ConfigError(`MICA_ADMIT_DOMAIN names ${open.join(", ")}, where anybody can register an address.\n` +
|
|
140
|
+
" That rule would let the public edit this site. Name the people instead:\n" +
|
|
141
|
+
" MICA_ADMIT_EMAILS=alice@gmail.com,bob@gmail.com");
|
|
142
|
+
}
|
|
143
|
+
const malformed = config.admitEmails.filter((email) => !/^[^@\s]+@[^@\s]+$/.test(email));
|
|
144
|
+
if (malformed.length > 0) {
|
|
145
|
+
throw new ConfigError(`MICA_ADMIT_EMAILS entries are email addresses, and these are not: ${malformed.join(", ")}`);
|
|
146
|
+
}
|
|
109
147
|
const wrong = config.admitSubjects.filter((entry) => !entry.issuer || !entry.subject);
|
|
110
148
|
if (wrong.length > 0) {
|
|
111
149
|
throw new ConfigError("MICA_ADMIT_SUBJECTS entries are `issuer|subject` pairs, and one is not:\n" +
|
|
112
150
|
` ${wrong.map((entry) => entry.subject || "(empty)").join(", ")}\n\n` +
|
|
113
151
|
" The issuer is part of the key because a subject is only unique within\n" +
|
|
114
|
-
" the provider that issued it.
|
|
115
|
-
" let people change those, and two people can hold one in turn.\n" +
|
|
152
|
+
" the provider that issued it. To admit an address, use MICA_ADMIT_EMAILS.\n" +
|
|
116
153
|
` MICA_ADMIT_SUBJECTS=${config.MICA_OIDC_ISSUER ?? "https://id.example.com"}|a1b2c3`);
|
|
117
154
|
}
|
|
118
155
|
}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAErD,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB;;;;OAIG;IACH,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC7C,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,iDAAiD;IACjD,uBAAuB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,sBAAsB,CAAC;IAC3D;;;;;OAKG;IACH,sBAAsB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;IAEpD;;;;OAIG;IACH,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACvC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACxC,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/gate.d.ts
CHANGED
|
@@ -3,19 +3,18 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Two layers, in order. `requireAccess` turns a session cookie into an
|
|
5
5
|
* `AccessContext` — or a 401 — re-checking admission on every request so a
|
|
6
|
-
* configuration change is immediate
|
|
6
|
+
* configuration change is immediate, and re-issuing the cookie while the
|
|
7
|
+
* session is in use. `csrfProtection` is the double-submit
|
|
7
8
|
* token over the Origin check the runtime already applies: cross-origin
|
|
8
9
|
* JavaScript can neither read the cookie nor set the header.
|
|
9
10
|
*/
|
|
10
11
|
import type { Context, MiddlewareHandler } from "hono";
|
|
11
12
|
import { type Env } from "@micacms/runtime";
|
|
12
13
|
import type { AdmissionPolicy } from "./admission.js";
|
|
13
|
-
import { type SessionService } from "./session.js";
|
|
14
|
-
import type { SessionRecord, SessionRepository } from "./sessions-repository.js";
|
|
14
|
+
import { type SessionRecord, type SessionService } from "./session.js";
|
|
15
15
|
export declare function sessionOf(c: Context<Env>): SessionRecord;
|
|
16
16
|
export interface GateDeps {
|
|
17
17
|
sessions: SessionService;
|
|
18
|
-
sessionsRepo: SessionRepository;
|
|
19
18
|
admission: AdmissionPolicy;
|
|
20
19
|
}
|
|
21
20
|
/**
|
|
@@ -36,5 +35,5 @@ export declare function requireAccess(deps: GateDeps): MiddlewareHandler<Env>;
|
|
|
36
35
|
* Runs after `requireAccess`, and complements the session cookie's
|
|
37
36
|
* `SameSite=Lax`, which already blocks the classic cross-site form post.
|
|
38
37
|
*/
|
|
39
|
-
export declare function csrfProtection(): MiddlewareHandler<Env>;
|
|
38
|
+
export declare function csrfProtection(deps: GateDeps): MiddlewareHandler<Env>;
|
|
40
39
|
//# sourceMappingURL=gate.d.ts.map
|
package/dist/gate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAEvD,OAAO,EAAY,KAAK,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,cAAc,CAAC;AAQtB,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,aAAa,CAGxD;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,eAAe,CAAC;CAC5B;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAiCpE;AAID;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAiBrE"}
|
package/dist/gate.js
CHANGED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Two layers, in order. `requireAccess` turns a session cookie into an
|
|
5
5
|
* `AccessContext` — or a 401 — re-checking admission on every request so a
|
|
6
|
-
* configuration change is immediate
|
|
6
|
+
* configuration change is immediate, and re-issuing the cookie while the
|
|
7
|
+
* session is in use. `csrfProtection` is the double-submit
|
|
7
8
|
* token over the Origin check the runtime already applies: cross-origin
|
|
8
9
|
* JavaScript can neither read the cookie nor set the header.
|
|
9
10
|
*/
|
|
10
|
-
import { getCookie } from "hono/cookie";
|
|
11
|
+
import { getCookie, setCookie } from "hono/cookie";
|
|
11
12
|
import { ApiError } from "@micacms/runtime";
|
|
12
|
-
import {
|
|
13
|
+
import { CSRF_HEADER, safeEqual, } from "./session.js";
|
|
13
14
|
/**
|
|
14
15
|
* The session behind the current request. Auth's own context variable —
|
|
15
16
|
* the runtime knows only the `access` it derives from it.
|
|
@@ -31,18 +32,11 @@ export function sessionOf(c) {
|
|
|
31
32
|
*/
|
|
32
33
|
export function requireAccess(deps) {
|
|
33
34
|
return async (c, next) => {
|
|
34
|
-
|
|
35
|
+
let session = deps.sessions.resolve(getCookie(c, deps.sessions.names.session));
|
|
35
36
|
if (!session) {
|
|
36
37
|
throw new ApiError("unauthenticated", "Your session has expired. Please sign in again.");
|
|
37
38
|
}
|
|
38
39
|
const { identity } = session;
|
|
39
|
-
if (!identity) {
|
|
40
|
-
// A row from a pre-split local-mode run of the same database. It
|
|
41
|
-
// authenticates nobody, so it is not a session for an authenticated
|
|
42
|
-
// deployment.
|
|
43
|
-
deps.sessionsRepo.delete(session.id);
|
|
44
|
-
throw new ApiError("unauthenticated", "Please sign in again.");
|
|
45
|
-
}
|
|
46
40
|
const verdict = deps.admission.admits(identity);
|
|
47
41
|
if (!verdict.admitted) {
|
|
48
42
|
c.get("logger").warn("Session no longer admitted", {
|
|
@@ -51,11 +45,18 @@ export function requireAccess(deps) {
|
|
|
51
45
|
});
|
|
52
46
|
throw new ApiError("forbidden", "You no longer have access to this site.");
|
|
53
47
|
}
|
|
48
|
+
const refreshed = deps.sessions.refresh(session);
|
|
49
|
+
if (refreshed)
|
|
50
|
+
session = refreshed.record;
|
|
54
51
|
c.set(SESSION_VARIABLE, session);
|
|
55
52
|
c.set("access", {
|
|
56
53
|
identity: { subject: identity.subject, email: identity.email, name: identity.name },
|
|
57
54
|
});
|
|
58
55
|
await next();
|
|
56
|
+
// After the handler, so the cookie lands on whatever response it built.
|
|
57
|
+
if (refreshed) {
|
|
58
|
+
setCookie(c, deps.sessions.names.session, refreshed.cookie, deps.sessions.sessionCookieOptions());
|
|
59
|
+
}
|
|
59
60
|
};
|
|
60
61
|
}
|
|
61
62
|
const SAFE_METHODS = new Set(["GET", "HEAD", "OPTIONS"]);
|
|
@@ -66,7 +67,7 @@ const SAFE_METHODS = new Set(["GET", "HEAD", "OPTIONS"]);
|
|
|
66
67
|
* Runs after `requireAccess`, and complements the session cookie's
|
|
67
68
|
* `SameSite=Lax`, which already blocks the classic cross-site form post.
|
|
68
69
|
*/
|
|
69
|
-
export function csrfProtection() {
|
|
70
|
+
export function csrfProtection(deps) {
|
|
70
71
|
return async (c, next) => {
|
|
71
72
|
if (SAFE_METHODS.has(c.req.method)) {
|
|
72
73
|
await next();
|
|
@@ -74,7 +75,7 @@ export function csrfProtection() {
|
|
|
74
75
|
}
|
|
75
76
|
const session = sessionOf(c);
|
|
76
77
|
const header = c.req.header(CSRF_HEADER);
|
|
77
|
-
const cookie = getCookie(c,
|
|
78
|
+
const cookie = getCookie(c, deps.sessions.names.csrf);
|
|
78
79
|
if (!header || !cookie || !safeEqual(header, cookie) || !safeEqual(header, session.csrfToken)) {
|
|
79
80
|
throw new ApiError("forbidden", "Invalid or missing CSRF token. Reload the page and retry.");
|
|
80
81
|
}
|
package/dist/gate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @micacms/auth-oidc — the server-only OIDC gate around @micacms/runtime.
|
|
3
3
|
*
|
|
4
|
-
* One factory: hand it the finished configuration
|
|
5
|
-
*
|
|
4
|
+
* One factory: hand it the finished configuration and a logger, and it
|
|
5
|
+
* returns the `AuthSurface` the runtime mounts — sign-in
|
|
6
6
|
* routes at `/api/auth`, and the session-plus-CSRF gate in front of the admin
|
|
7
7
|
* API — together with the services the composing app reports on.
|
|
8
8
|
*
|
|
@@ -10,24 +10,20 @@
|
|
|
10
10
|
* The local editor must never gain a path to it: that absence is the product
|
|
11
11
|
* boundary that keeps `npx @micacms/editor` free of authentication code.
|
|
12
12
|
*/
|
|
13
|
-
import type { AuthSurface, Logger
|
|
13
|
+
import type { AuthSurface, Logger } from "@micacms/runtime";
|
|
14
14
|
import { type RateLimiter } from "@micacms/runtime";
|
|
15
15
|
import { type AdmissionPolicy } from "./admission.js";
|
|
16
16
|
import type { AuthConfig } from "./config.js";
|
|
17
17
|
import { type OidcService } from "./oidc.js";
|
|
18
18
|
import { type SessionService } from "./session.js";
|
|
19
|
-
import { type SessionRepository } from "./sessions-repository.js";
|
|
20
19
|
export interface OidcAuthDeps {
|
|
21
20
|
config: AuthConfig;
|
|
22
|
-
/** The database sessions live in. Owned and opened by the composing app. */
|
|
23
|
-
db: SqlDatabase;
|
|
24
21
|
logger: Logger;
|
|
25
22
|
}
|
|
26
23
|
export interface OidcAuth {
|
|
27
24
|
/** What `createApp` mounts: routes at /api/auth, the gate before /api/admin. */
|
|
28
25
|
surface: AuthSurface;
|
|
29
26
|
sessions: SessionService;
|
|
30
|
-
sessionsRepo: SessionRepository;
|
|
31
27
|
admission: AdmissionPolicy;
|
|
32
28
|
oidc: OidcService;
|
|
33
29
|
loginLimiter: RateLimiter;
|
|
@@ -37,6 +33,5 @@ export { createAdmissionPolicy, type AdmissionPolicy, type AdmissionResult } fro
|
|
|
37
33
|
export { authEnv, deriveAuth, requireAuthConfig, type AuthConfig, type AuthEnv, } from "./config.js";
|
|
38
34
|
export { csrfProtection, requireAccess, sessionOf } from "./gate.js";
|
|
39
35
|
export { createOidcService, type OidcService } from "./oidc.js";
|
|
40
|
-
export { createSessionService, CSRF_COOKIE, CSRF_HEADER, SESSION_COOKIE, type SessionService, } from "./session.js";
|
|
41
|
-
export { createSessionRepository, type SessionIdentity, type SessionRecord, type SessionRepository, } from "./sessions-repository.js";
|
|
36
|
+
export { cookieNames, createSessionService, CSRF_COOKIE, CSRF_HEADER, SESSION_COOKIE, type SessionIdentity, type SessionRecord, type SessionService, } from "./session.js";
|
|
42
37
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEvE,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAEhE,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAEzE,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,gFAAgF;IAChF,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,eAAe,CAAC;IAC3B,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,EAAE,WAAW,CAAC;CAC3B;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,QAAQ,CAuB3D;AAED,OAAO,EAAE,qBAAqB,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACnG,OAAO,EACL,OAAO,EACP,UAAU,EACV,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,OAAO,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @micacms/auth-oidc — the server-only OIDC gate around @micacms/runtime.
|
|
3
3
|
*
|
|
4
|
-
* One factory: hand it the finished configuration
|
|
5
|
-
*
|
|
4
|
+
* One factory: hand it the finished configuration and a logger, and it
|
|
5
|
+
* returns the `AuthSurface` the runtime mounts — sign-in
|
|
6
6
|
* routes at `/api/auth`, and the session-plus-CSRF gate in front of the admin
|
|
7
7
|
* API — together with the services the composing app reports on.
|
|
8
8
|
*
|
|
@@ -16,25 +16,22 @@ import { csrfProtection, requireAccess } from "./gate.js";
|
|
|
16
16
|
import { createOidcService } from "./oidc.js";
|
|
17
17
|
import { authRoutes } from "./routes.js";
|
|
18
18
|
import { createSessionService } from "./session.js";
|
|
19
|
-
import { createSessionRepository } from "./sessions-repository.js";
|
|
20
19
|
export function createOidcAuth(deps) {
|
|
21
20
|
const { config, logger } = deps;
|
|
22
|
-
const
|
|
23
|
-
const sessions = createSessionService(sessionsRepo, config);
|
|
21
|
+
const sessions = createSessionService(config);
|
|
24
22
|
const admission = createAdmissionPolicy(config);
|
|
25
23
|
const oidc = createOidcService({ config, logger });
|
|
26
24
|
const loginLimiter = createRateLimiter({
|
|
27
25
|
limit: config.LOGIN_MAX_ATTEMPTS,
|
|
28
26
|
windowMs: config.LOGIN_WINDOW_MS,
|
|
29
27
|
});
|
|
30
|
-
const gate = { sessions,
|
|
28
|
+
const gate = { sessions, admission };
|
|
31
29
|
return {
|
|
32
30
|
surface: {
|
|
33
|
-
routes: authRoutes({ config, sessions,
|
|
34
|
-
gate: [requireAccess(gate), csrfProtection()],
|
|
31
|
+
routes: authRoutes({ config, sessions, oidc, admission, loginLimiter }),
|
|
32
|
+
gate: [requireAccess(gate), csrfProtection(gate)],
|
|
35
33
|
},
|
|
36
34
|
sessions,
|
|
37
|
-
sessionsRepo,
|
|
38
35
|
admission,
|
|
39
36
|
oidc,
|
|
40
37
|
loginLimiter,
|
|
@@ -44,6 +41,5 @@ export { createAdmissionPolicy } from "./admission.js";
|
|
|
44
41
|
export { authEnv, deriveAuth, requireAuthConfig, } from "./config.js";
|
|
45
42
|
export { csrfProtection, requireAccess, sessionOf } from "./gate.js";
|
|
46
43
|
export { createOidcService } from "./oidc.js";
|
|
47
|
-
export { createSessionService, CSRF_COOKIE, CSRF_HEADER, SESSION_COOKIE, } from "./session.js";
|
|
48
|
-
export { createSessionRepository, } from "./sessions-repository.js";
|
|
44
|
+
export { cookieNames, createSessionService, CSRF_COOKIE, CSRF_HEADER, SESSION_COOKIE, } from "./session.js";
|
|
49
45
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,iBAAiB,EAAoB,MAAM,kBAAkB,CAAC;AAEvE,OAAO,EAAE,qBAAqB,EAAwB,MAAM,gBAAgB,CAAC;AAE7E,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAoB,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAuB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,iBAAiB,EAAoB,MAAM,kBAAkB,CAAC;AAEvE,OAAO,EAAE,qBAAqB,EAAwB,MAAM,gBAAgB,CAAC;AAE7E,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAoB,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAuB,MAAM,cAAc,CAAC;AAgBzE,MAAM,UAAU,cAAc,CAAC,IAAkB;IAC/C,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAEhC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,iBAAiB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,iBAAiB,CAAC;QACrC,KAAK,EAAE,MAAM,CAAC,kBAAkB;QAChC,QAAQ,EAAE,MAAM,CAAC,eAAe;KACjC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAErC,OAAO;QACL,OAAO,EAAE;YACP,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;YACvE,IAAI,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC;SAClD;QACD,QAAQ;QACR,SAAS;QACT,IAAI;QACJ,YAAY;KACb,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,qBAAqB,EAA8C,MAAM,gBAAgB,CAAC;AACnG,OAAO,EACL,OAAO,EACP,UAAU,EACV,iBAAiB,GAGlB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAoB,MAAM,WAAW,CAAC;AAChE,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,WAAW,EACX,WAAW,EACX,cAAc,GAIf,MAAM,cAAc,CAAC"}
|
package/dist/oidc.d.ts
CHANGED
|
@@ -26,8 +26,6 @@
|
|
|
26
26
|
*/
|
|
27
27
|
import { type Logger } from "@micacms/runtime";
|
|
28
28
|
import type { AuthConfig } from "./config.js";
|
|
29
|
-
/** Carries state, PKCE verifier and nonce across the redirect to the provider. */
|
|
30
|
-
export declare const TRANSACTION_COOKIE = "mica_oidc";
|
|
31
29
|
export interface OidcTransaction {
|
|
32
30
|
state: string;
|
|
33
31
|
nonce: string;
|
|
@@ -49,6 +47,15 @@ export interface OidcClaims {
|
|
|
49
47
|
}
|
|
50
48
|
export declare function sealTransaction(transaction: OidcTransaction, secret: string): string;
|
|
51
49
|
export declare function openTransaction(cookie: string, secret: string): OidcTransaction | null;
|
|
50
|
+
/**
|
|
51
|
+
* The address and its `email_verified` flag, always from the same answer, so
|
|
52
|
+
* that a flag cannot vouch for an address it was not sent with (#91). Userinfo
|
|
53
|
+
* fills in an address the ID token lacks, or confirms the token's own address.
|
|
54
|
+
*/
|
|
55
|
+
export declare function emailFrom(claims: Record<string, unknown>, info?: Record<string, unknown>): {
|
|
56
|
+
email: string;
|
|
57
|
+
emailVerified: boolean;
|
|
58
|
+
};
|
|
52
59
|
export interface OidcServiceDeps {
|
|
53
60
|
config: AuthConfig;
|
|
54
61
|
logger: Logger;
|
package/dist/oidc.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oidc.d.ts","sourceRoot":"","sources":["../src/oidc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAMH,OAAO,EAAY,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"oidc.d.ts","sourceRoot":"","sources":["../src/oidc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAMH,OAAO,EAAY,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAU9C,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,6DAA6D;AAC7D,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,aAAa,EAAE,OAAO,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAoBD,wBAAgB,eAAe,CAAC,WAAW,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGpF;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAkBtF;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,OAAO,CAAA;CAAE,CAU3C;AAMD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe;IA2CnD,4EAA4E;oBACtD,MAAM,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,eAAe,CAAA;KAAE,CAAC;IAwBrF;;;;;;;OAOG;yBACwB,GAAG,eAAe,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC;IA6DlF;;;;;;OAMG;qBACoB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;EAahD;AAED,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAiB/D,2EAA2E;AAC3E,eAAO,MAAM,WAAW,QAAO,MAA+C,CAAC"}
|