@atlasauth/emulator-core 0.1.0 → 0.2.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/dist/adopt.d.ts +50 -0
- package/dist/adopt.js +57 -0
- package/dist/adopt.js.map +1 -0
- package/dist/coverage.d.ts +15 -0
- package/dist/coverage.js +31 -0
- package/dist/coverage.js.map +1 -0
- package/dist/crypto-util.d.ts +10 -0
- package/dist/crypto-util.js +76 -0
- package/dist/crypto-util.js.map +1 -0
- package/dist/engine.d.ts +33 -2
- package/dist/engine.js +53 -8
- package/dist/engine.js.map +1 -1
- package/dist/error-catalog.js +8 -0
- package/dist/error-catalog.js.map +1 -1
- package/dist/event-gate.d.ts +3 -0
- package/dist/event-gate.js +372 -0
- package/dist/event-gate.js.map +1 -0
- package/dist/generic.js +9 -1
- package/dist/generic.js.map +1 -1
- package/dist/handlers/approvals.d.ts +2 -0
- package/dist/handlers/approvals.js +365 -0
- package/dist/handlers/approvals.js.map +1 -0
- package/dist/handlers/authz.d.ts +2 -0
- package/dist/handlers/authz.js +347 -0
- package/dist/handlers/authz.js.map +1 -0
- package/dist/handlers/billing.d.ts +2 -0
- package/dist/handlers/billing.js +398 -0
- package/dist/handlers/billing.js.map +1 -0
- package/dist/handlers/connections.d.ts +2 -0
- package/dist/handlers/connections.js +332 -0
- package/dist/handlers/connections.js.map +1 -0
- package/dist/handlers/device.d.ts +47 -0
- package/dist/handlers/device.js +648 -0
- package/dist/handlers/device.js.map +1 -0
- package/dist/handlers/federation.d.ts +2 -0
- package/dist/handlers/federation.js +481 -0
- package/dist/handlers/federation.js.map +1 -0
- package/dist/handlers/governance.d.ts +2 -0
- package/dist/handlers/governance.js +460 -0
- package/dist/handlers/governance.js.map +1 -0
- package/dist/handlers/hooks.js +4 -1
- package/dist/handlers/hooks.js.map +1 -1
- package/dist/handlers/index.d.ts +5 -1
- package/dist/handlers/index.js +32 -3
- package/dist/handlers/index.js.map +1 -1
- package/dist/handlers/keys.js +6 -1
- package/dist/handlers/keys.js.map +1 -1
- package/dist/handlers/machines.js +55 -8
- package/dist/handlers/machines.js.map +1 -1
- package/dist/handlers/messaging.d.ts +4 -0
- package/dist/handlers/messaging.js +486 -0
- package/dist/handlers/messaging.js.map +1 -0
- package/dist/handlers/oauth-flows.d.ts +28 -0
- package/dist/handlers/oauth-flows.js +419 -0
- package/dist/handlers/oauth-flows.js.map +1 -0
- package/dist/handlers/oauth.d.ts +75 -0
- package/dist/handlers/oauth.js +608 -0
- package/dist/handlers/oauth.js.map +1 -0
- package/dist/handlers/passkeys.d.ts +3 -0
- package/dist/handlers/passkeys.js +293 -0
- package/dist/handlers/passkeys.js.map +1 -0
- package/dist/handlers/platform.d.ts +15 -0
- package/dist/handlers/platform.js +454 -0
- package/dist/handlers/platform.js.map +1 -0
- package/dist/handlers/round2.d.ts +8 -0
- package/dist/handlers/round2.js +372 -0
- package/dist/handlers/round2.js.map +1 -0
- package/dist/handlers/scim.d.ts +2 -0
- package/dist/handlers/scim.js +408 -0
- package/dist/handlers/scim.js.map +1 -0
- package/dist/handlers/sessions.d.ts +7 -3
- package/dist/handlers/sessions.js +55 -25
- package/dist/handlers/sessions.js.map +1 -1
- package/dist/handlers/support.d.ts +20 -0
- package/dist/handlers/support.js +62 -0
- package/dist/handlers/support.js.map +1 -0
- package/dist/handlers/users.js +4 -0
- package/dist/handlers/users.js.map +1 -1
- package/dist/handlers/workflows.d.ts +2 -0
- package/dist/handlers/workflows.js +428 -0
- package/dist/handlers/workflows.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +23 -1
- package/dist/index.js.map +1 -1
- package/dist/jws.d.ts +41 -0
- package/dist/jws.js +133 -0
- package/dist/jws.js.map +1 -0
- package/dist/messages.d.ts +7 -0
- package/dist/messages.js +8 -4
- package/dist/messages.js.map +1 -1
- package/dist/parity-bin.js +3 -1
- package/dist/parity-bin.js.map +1 -1
- package/dist/parity-routes.d.ts +14 -0
- package/dist/parity-routes.js +421 -0
- package/dist/parity-routes.js.map +1 -0
- package/dist/parity.d.ts +10 -3
- package/dist/parity.js +14 -5
- package/dist/parity.js.map +1 -1
- package/dist/tokens.d.ts +17 -0
- package/dist/tokens.js +46 -0
- package/dist/tokens.js.map +1 -1
- package/dist/webauthn-virtual.d.ts +70 -0
- package/dist/webauthn-virtual.js +186 -0
- package/dist/webauthn-virtual.js.map +1 -0
- package/dist/webhook-ext.d.ts +16 -0
- package/dist/webhook-ext.js +218 -0
- package/dist/webhook-ext.js.map +1 -0
- package/dist/webhooks.d.ts +3 -0
- package/dist/webhooks.js +37 -3
- package/dist/webhooks.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.connectionsHandlers = connectionsHandlers;
|
|
4
|
+
const crypto_util_1 = require("../crypto-util");
|
|
5
|
+
const errors_1 = require("../errors");
|
|
6
|
+
const store_1 = require("../store");
|
|
7
|
+
const support_1 = require("./support");
|
|
8
|
+
const util_1 = require("./util");
|
|
9
|
+
/**
|
|
10
|
+
* Connection history and recovery on the engine's own state: the per-connection activity log (what happened, never what was
|
|
11
|
+
* sent: method, host, status and timing only), persisted provider events with read-back and replay, hosted reconnect
|
|
12
|
+
* (settings, a one-time link, the public pages) and the exchange of a non-expiring Shopify token for an expiring one.
|
|
13
|
+
* Connections themselves are the generic CRUD layer's rows. The relay goes through the engine's `fetch` option, so it never
|
|
14
|
+
* reaches a real provider unless a test says so.
|
|
15
|
+
*/
|
|
16
|
+
const RETENTION_MS = 30 * 86_400_000;
|
|
17
|
+
const ACTIVITY_KINDS = ['relay', 'token_read', 'refresh', 'health', 'provider_event', 'reconnect', 'token_exchange'];
|
|
18
|
+
const OUTCOMES = ['ok', 'error', 'blocked'];
|
|
19
|
+
const UNINSTALL = /(^|[/._-])(uninstall(ed)?|deauthori[sz]ed?|installation[._-]deleted|app[._/-]uninstalled)($|[/._-])/i;
|
|
20
|
+
const MAX_PAYLOAD = 256 * 1024;
|
|
21
|
+
const bad = (message, param) => new errors_1.EmulatorError('VALIDATION_FAILED', message, param);
|
|
22
|
+
const st = (0, support_1.engineState)((e) => ({ activity: new store_1.Table('connection_activity', e.clock.now, 'cact'), events: new store_1.Table('connection_provider_events', e.clock.now, 'cpev'), links: new Map(), settings: { enabled: false, link_ttl_hours: 168, return_url: null, providers: [] } }));
|
|
23
|
+
const connOf = (e, id) => {
|
|
24
|
+
const c = e.generic.get('connections')?.get(id);
|
|
25
|
+
if (!c)
|
|
26
|
+
throw (0, errors_1.notFound)('Connection');
|
|
27
|
+
return c;
|
|
28
|
+
};
|
|
29
|
+
const record = (e, connectionId, kind, outcome, extra = {}) => {
|
|
30
|
+
st(e).activity.insert({ connection_id: connectionId, kind, outcome, created_at: e.clock.now(), ...extra });
|
|
31
|
+
};
|
|
32
|
+
const activityView = (r) => ({ object: 'connection_activity', id: r.id, connection_id: r.connection_id, kind: r.kind, outcome: r.outcome, method: r.method ?? null, host: r.host ?? null, status: r.status ?? null, duration_ms: r.duration_ms ?? null, attempts: r.attempts ?? null, detail: r.detail ?? null, created_at: r.created_at });
|
|
33
|
+
const eventView = (r, payload) => ({ object: 'connection_provider_event', id: r.id, connection_id: r.connection_id, provider: r.provider, topic: r.topic, kind: r.kind, replayed: r.replay_count > 0, replay_count: r.replay_count, received_at: r.received_at, ...(payload ? { payload: r.payload } : {}) });
|
|
34
|
+
const sinceFilter = (e, v) => {
|
|
35
|
+
if (v === null)
|
|
36
|
+
return e.clock.now() - RETENTION_MS;
|
|
37
|
+
const n = /^\d+$/.test(v) ? Number(v) : Date.parse(v);
|
|
38
|
+
if (Number.isNaN(n))
|
|
39
|
+
throw bad('since must be epoch milliseconds or an ISO 8601 time.', 'since');
|
|
40
|
+
return Math.max(n, e.clock.now() - RETENTION_MS);
|
|
41
|
+
};
|
|
42
|
+
const hostAllowed = (host, allowed) => allowed.some((a) => (a.startsWith('*.') ? host.endsWith(a.slice(1)) && host.length > a.length - 1 : host === a));
|
|
43
|
+
const hashLink = async (t) => (0, crypto_util_1.bytesToB64url)(await (0, crypto_util_1.sha256)(t));
|
|
44
|
+
function announce(e, ev, replayed) {
|
|
45
|
+
e.webhooks.emit('connection.provider_event', { object: 'connection_provider_event', id: ev.id, connection_id: ev.connection_id, provider: ev.provider, topic: ev.topic, kind: ev.kind, ...(replayed ? { replayed: true, event_id: ev.id } : {}), received_at: ev.received_at });
|
|
46
|
+
}
|
|
47
|
+
function connectionsHandlers() {
|
|
48
|
+
const eventOf = (e, connectionId, id) => {
|
|
49
|
+
const ev = st(e).events.get(id);
|
|
50
|
+
if (!ev || ev.connection_id !== connectionId)
|
|
51
|
+
throw (0, errors_1.notFound)('Provider event');
|
|
52
|
+
return ev;
|
|
53
|
+
};
|
|
54
|
+
const eventList = (e, q, connectionId, c) => {
|
|
55
|
+
const since = sinceFilter(e, q.get('since'));
|
|
56
|
+
const rows = st(e).events.all().filter((r) => r.received_at >= since && (!connectionId || r.connection_id === connectionId) && (!q.get('connection_id') || r.connection_id === q.get('connection_id')) && (!q.get('provider') || r.provider === q.get('provider')) && (!q.get('topic') || r.topic === q.get('topic')));
|
|
57
|
+
const page = (0, store_1.paginate)(rows, (0, util_1.pageOf)(c));
|
|
58
|
+
return { object: 'list', data: page.data.map((r) => eventView(r, false)), has_more: page.has_more, next_cursor: page.next_cursor };
|
|
59
|
+
};
|
|
60
|
+
return [
|
|
61
|
+
// ── activity ──
|
|
62
|
+
{
|
|
63
|
+
method: 'GET',
|
|
64
|
+
pattern: '/v1/connections/:id/activity',
|
|
65
|
+
scope: 'organizations:read',
|
|
66
|
+
handler: (c) => {
|
|
67
|
+
const e = c.engine;
|
|
68
|
+
const conn = connOf(e, c.params.id);
|
|
69
|
+
const kind = c.query.get('kind');
|
|
70
|
+
const outcome = c.query.get('outcome');
|
|
71
|
+
if (kind && !ACTIVITY_KINDS.includes(kind))
|
|
72
|
+
throw bad(`kind must be one of: ${ACTIVITY_KINDS.join(', ')}.`, 'kind');
|
|
73
|
+
if (outcome && !OUTCOMES.includes(outcome))
|
|
74
|
+
throw bad(`outcome must be one of: ${OUTCOMES.join(', ')}.`, 'outcome');
|
|
75
|
+
const since = sinceFilter(e, c.query.get('since'));
|
|
76
|
+
const rows = st(e).activity.all().filter((r) => r.connection_id === conn.id && r.created_at >= since && (!kind || r.kind === kind) && (!outcome || r.outcome === outcome));
|
|
77
|
+
const page = (0, store_1.paginate)(rows, (0, util_1.pageOf)(c));
|
|
78
|
+
return { body: { object: 'list', data: page.data.map(activityView), has_more: page.has_more, next_cursor: page.next_cursor } };
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
// The relay: allowed method and host only; the log keeps method, host, status, duration and attempts, never the path, headers or body.
|
|
83
|
+
method: 'POST',
|
|
84
|
+
pattern: '/v1/connections/:id/relay',
|
|
85
|
+
scope: 'connections:relay',
|
|
86
|
+
handler: async (c) => {
|
|
87
|
+
const e = c.engine;
|
|
88
|
+
const conn = connOf(e, c.params.id);
|
|
89
|
+
const method = (0, support_1.oneOf)(c.body, 'method', ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE'], 'GET');
|
|
90
|
+
let url;
|
|
91
|
+
try {
|
|
92
|
+
url = new URL(String(c.body.url));
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
throw bad('url must be an absolute https URL.', 'url');
|
|
96
|
+
}
|
|
97
|
+
if (url.protocol !== 'https:' || url.username || url.password)
|
|
98
|
+
throw bad('url must be an https URL without credentials.', 'url');
|
|
99
|
+
const methods = conn.allowed_methods ?? ['GET'];
|
|
100
|
+
const refuse = (detail, param) => {
|
|
101
|
+
record(e, conn.id, 'relay', 'blocked', { method, host: url.host, detail });
|
|
102
|
+
throw new errors_1.EmulatorError('FORBIDDEN', detail, param);
|
|
103
|
+
};
|
|
104
|
+
if (conn.status === 'revoked')
|
|
105
|
+
refuse('This connection is revoked.', 'url');
|
|
106
|
+
if (!methods.includes(method))
|
|
107
|
+
refuse(`${method} is not in this connection's allowed_methods.`, 'method');
|
|
108
|
+
if (!hostAllowed(url.hostname, conn.allowed_hosts ?? []))
|
|
109
|
+
refuse('That host is not in this connection\'s allowed_hosts.', 'url');
|
|
110
|
+
if (!e.options.fetch) {
|
|
111
|
+
record(e, conn.id, 'relay', 'error', { method, host: url.host, status: null, duration_ms: 0, attempts: 1, detail: 'no fetch configured' });
|
|
112
|
+
throw new errors_1.EmulatorError('CONNECTION_UPSTREAM_ERROR', 'The emulator has no outbound fetch: pass the `fetch` option to answer relayed calls.');
|
|
113
|
+
}
|
|
114
|
+
const started = e.clock.now();
|
|
115
|
+
let res;
|
|
116
|
+
try {
|
|
117
|
+
res = await e.options.fetch(url.toString(), { method, headers: c.body.headers ?? {}, body: ['GET', 'HEAD'].includes(method) ? undefined : typeof c.body.body === 'string' ? c.body.body : c.body.body === undefined ? undefined : JSON.stringify(c.body.body) });
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
record(e, conn.id, 'relay', 'error', { method, host: url.host, status: null, duration_ms: e.clock.now() - started, attempts: 1, detail: 'network error' });
|
|
121
|
+
throw new errors_1.EmulatorError('CONNECTION_UPSTREAM_ERROR', `The provider could not be reached: ${err.message}`);
|
|
122
|
+
}
|
|
123
|
+
record(e, conn.id, 'relay', res.status < 400 ? 'ok' : 'error', { method, host: url.host, status: res.status, duration_ms: e.clock.now() - started, attempts: 1 });
|
|
124
|
+
return { body: { object: 'connection_relay_response', connection_id: conn.id, status: res.status, headers: Object.fromEntries(res.headers), body: await res.text() } };
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
// ── persisted provider events ──
|
|
128
|
+
{
|
|
129
|
+
// The provider's announcement lands here (in production, signature-verified per provider): stored, announced, and an uninstall revokes the connection.
|
|
130
|
+
method: 'POST',
|
|
131
|
+
pattern: '/v1/connection_provider_events/:instanceId/:provider',
|
|
132
|
+
public: true,
|
|
133
|
+
handler: (c) => {
|
|
134
|
+
const e = c.engine;
|
|
135
|
+
if (c.params.instanceId !== e.instanceId)
|
|
136
|
+
throw (0, errors_1.notFound)('Instance');
|
|
137
|
+
const conn = connOf(e, c.body.connection_id);
|
|
138
|
+
if (conn.provider !== c.params.provider)
|
|
139
|
+
throw (0, errors_1.notFound)('Connection for that provider');
|
|
140
|
+
if (typeof c.body.topic !== 'string' || !c.body.topic || c.body.topic.length > 200)
|
|
141
|
+
throw bad('topic is required (up to 200 characters).', 'topic');
|
|
142
|
+
const payload = c.body.payload ?? {};
|
|
143
|
+
if (JSON.stringify(payload).length > MAX_PAYLOAD)
|
|
144
|
+
throw bad('payload can be at most 256 KB.', 'payload');
|
|
145
|
+
const kind = UNINSTALL.test(c.body.topic) ? 'uninstall' : 'event';
|
|
146
|
+
const ev = st(e).events.insert({ connection_id: conn.id, provider: conn.provider, topic: c.body.topic, kind, payload, replay_count: 0, received_at: e.clock.now() });
|
|
147
|
+
record(e, conn.id, 'provider_event', 'ok', { detail: c.body.topic });
|
|
148
|
+
announce(e, ev, false);
|
|
149
|
+
if (kind === 'uninstall' && conn.status !== 'revoked') {
|
|
150
|
+
conn.status = 'revoked';
|
|
151
|
+
record(e, conn.id, 'health', 'ok', { detail: 'revoked by the provider' });
|
|
152
|
+
e.webhooks.emit('connection.revoked', { object: 'connection', id: conn.id, provider: conn.provider, reason: 'provider_uninstall' });
|
|
153
|
+
}
|
|
154
|
+
return { status: 201, body: eventView(ev, false) };
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
{ method: 'GET', pattern: '/v1/connections/:id/provider_events', scope: 'organizations:read', handler: (c) => ({ body: eventList(c.engine, c.query, connOf(c.engine, c.params.id).id, c) }) },
|
|
158
|
+
{ method: 'GET', pattern: '/v1/connection_provider_event_log', scope: 'organizations:read', handler: (c) => ({ body: eventList(c.engine, c.query, null, c) }) },
|
|
159
|
+
{
|
|
160
|
+
method: 'GET',
|
|
161
|
+
pattern: '/v1/connections/:id/provider_events/:eventId',
|
|
162
|
+
scope: 'organizations:read',
|
|
163
|
+
handler: (c) => ({ body: eventView(eventOf(c.engine, connOf(c.engine, c.params.id).id, c.params.eventId), true) }),
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
// Re-announces only: a replayed uninstall never revokes a connection again.
|
|
167
|
+
method: 'POST',
|
|
168
|
+
pattern: '/v1/connections/:id/provider_events/:eventId/replay',
|
|
169
|
+
scope: 'organizations:write',
|
|
170
|
+
handler: (c) => {
|
|
171
|
+
const e = c.engine;
|
|
172
|
+
const ev = eventOf(e, connOf(e, c.params.id).id, c.params.eventId);
|
|
173
|
+
ev.replay_count++;
|
|
174
|
+
announce(e, ev, true);
|
|
175
|
+
return { body: eventView(ev, false) };
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
// ── hosted reconnect ──
|
|
179
|
+
{ method: 'GET', pattern: '/v1/connection_reconnect_settings', scope: 'organizations:read', handler: (c) => ({ body: { object: 'connection_reconnect_settings', ...st(c.engine).settings } }) },
|
|
180
|
+
{
|
|
181
|
+
method: 'PUT',
|
|
182
|
+
pattern: '/v1/connection_reconnect_settings',
|
|
183
|
+
scope: 'organizations:write',
|
|
184
|
+
handler: (c) => {
|
|
185
|
+
const s = st(c.engine).settings;
|
|
186
|
+
const b = c.body;
|
|
187
|
+
const unknown = Object.keys(b).find((k) => !['enabled', 'link_ttl_hours', 'return_url', 'providers'].includes(k));
|
|
188
|
+
if (unknown)
|
|
189
|
+
throw bad(`Unknown field: ${unknown}.`, unknown);
|
|
190
|
+
const next = { ...s };
|
|
191
|
+
if (b.enabled !== undefined) {
|
|
192
|
+
if (typeof b.enabled !== 'boolean')
|
|
193
|
+
throw bad('enabled must be true or false.', 'enabled');
|
|
194
|
+
next.enabled = b.enabled;
|
|
195
|
+
}
|
|
196
|
+
if (b.link_ttl_hours !== undefined)
|
|
197
|
+
next.link_ttl_hours = (0, support_1.intIn)(b.link_ttl_hours, 'link_ttl_hours', 1, 720);
|
|
198
|
+
if (b.return_url !== undefined) {
|
|
199
|
+
if (b.return_url !== null) {
|
|
200
|
+
let u = null;
|
|
201
|
+
try {
|
|
202
|
+
u = new URL(b.return_url);
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
/* reported below */
|
|
206
|
+
}
|
|
207
|
+
if (!u || u.protocol !== 'https:' || u.username || u.password)
|
|
208
|
+
throw bad('return_url must be an https URL.', 'return_url');
|
|
209
|
+
}
|
|
210
|
+
next.return_url = b.return_url;
|
|
211
|
+
}
|
|
212
|
+
if (b.providers !== undefined) {
|
|
213
|
+
if (!Array.isArray(b.providers) || b.providers.length > 50 || b.providers.some((p) => typeof p !== 'string' || !p))
|
|
214
|
+
throw bad('providers is a list of up to 50 provider keys.', 'providers');
|
|
215
|
+
next.providers = [...new Set(b.providers)];
|
|
216
|
+
}
|
|
217
|
+
Object.assign(s, next);
|
|
218
|
+
return { body: { object: 'connection_reconnect_settings', ...s } };
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
// A one-time link for the owner to authorize again. Only a hash is stored; the URL is shown once. `send_email` mails the owner (your own mail provider).
|
|
223
|
+
method: 'POST',
|
|
224
|
+
pattern: '/v1/connections/:id/reconnect_link',
|
|
225
|
+
scope: 'organizations:write',
|
|
226
|
+
handler: async (c) => {
|
|
227
|
+
const e = c.engine;
|
|
228
|
+
const conn = connOf(e, c.params.id);
|
|
229
|
+
const s = st(e).settings;
|
|
230
|
+
if (c.body.send_email !== undefined && typeof c.body.send_email !== 'boolean')
|
|
231
|
+
throw bad('send_email must be a boolean.', 'send_email');
|
|
232
|
+
const ttl = c.body.ttl_hours === undefined ? s.link_ttl_hours : (0, support_1.intIn)(c.body.ttl_hours, 'ttl_hours', 1, 720);
|
|
233
|
+
if (!s.enabled)
|
|
234
|
+
throw new errors_1.EmulatorError('CONFLICT', 'Hosted reconnect is off. Turn it on with PUT /v1/connection_reconnect_settings.');
|
|
235
|
+
if (conn.kind !== 'oauth')
|
|
236
|
+
throw bad('Only an oauth connection is authorized again with the provider.', 'kind');
|
|
237
|
+
if (conn.status === 'revoked')
|
|
238
|
+
throw new errors_1.EmulatorError('CONFLICT', 'This connection was revoked; connect it again with POST /v1/connections/{id}/connect.');
|
|
239
|
+
if (s.providers.length && !s.providers.includes(conn.provider))
|
|
240
|
+
throw bad(`Hosted reconnect is not enabled for ${conn.provider}.`, 'provider');
|
|
241
|
+
let recipients = [];
|
|
242
|
+
if (c.body.send_email === true) {
|
|
243
|
+
const user = conn.owner?.type === 'user' ? e.db.users.get(conn.owner.id) : undefined;
|
|
244
|
+
const primary = user?.emails?.find((m) => m.id === user?.primary_email_address_id && m.verified);
|
|
245
|
+
if (!primary)
|
|
246
|
+
throw bad('This connection has no email recipient (a user owner needs a verified address).', 'send_email');
|
|
247
|
+
recipients = [primary.email_address];
|
|
248
|
+
}
|
|
249
|
+
const token = (0, store_1.randomToken)(32);
|
|
250
|
+
const expiresAt = e.clock.now() + ttl * 3_600_000;
|
|
251
|
+
st(e).links.set(await hashLink(token), { connectionId: conn.id, expiresAt, started: false });
|
|
252
|
+
const url = `${e.issuer}/v1/connection_reconnect/${token}`;
|
|
253
|
+
for (const to of recipients)
|
|
254
|
+
e.messages.send({ channel: 'email', to, subject: `Reconnect your ${conn.provider} connection`, link: url, meta: { template: 'connection_reconnect' } });
|
|
255
|
+
record(e, conn.id, 'reconnect', 'ok', { detail: 'link issued' });
|
|
256
|
+
return { status: 201, body: { object: 'connection_reconnect_link', connection_id: conn.id, url, expires_at: expiresAt, emailed: recipients.length } };
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
// Public. Looking at the page spends nothing (a mail scanner may open it). Every bad link answers the same.
|
|
261
|
+
method: 'GET',
|
|
262
|
+
pattern: '/v1/connection_reconnect/:token',
|
|
263
|
+
public: true,
|
|
264
|
+
handler: async (c) => {
|
|
265
|
+
const e = c.engine;
|
|
266
|
+
const link = st(e).links.get(await hashLink(c.params.token ?? ''));
|
|
267
|
+
if (!link || link.expiresAt <= e.clock.now() || link.started)
|
|
268
|
+
throw bad('This link is not valid.', 'token');
|
|
269
|
+
const conn = connOf(e, link.connectionId);
|
|
270
|
+
return { headers: { 'cache-control': 'no-store' }, body: { object: 'connection_reconnect_page', connection: { id: conn.id, provider: conn.provider, name: conn.name ?? null }, expires_at: link.expiresAt } };
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
method: 'GET',
|
|
275
|
+
pattern: '/v1/connection_reconnect/:token/start',
|
|
276
|
+
public: true,
|
|
277
|
+
handler: async (c) => {
|
|
278
|
+
const e = c.engine;
|
|
279
|
+
const link = st(e).links.get(await hashLink(c.params.token ?? ''));
|
|
280
|
+
if (!link || link.expiresAt <= e.clock.now() || link.started)
|
|
281
|
+
throw bad('This link is not valid.', 'token');
|
|
282
|
+
link.started = true;
|
|
283
|
+
const conn = connOf(e, link.connectionId);
|
|
284
|
+
record(e, conn.id, 'reconnect', 'ok', { detail: 'started' });
|
|
285
|
+
const back = st(e).settings.return_url ?? `${e.issuer}/v1/connection_reconnect_done`;
|
|
286
|
+
return { status: 302, headers: { location: `${e.issuer}/__emulator/provider/${encodeURIComponent(conn.provider)}/authorize?connection_id=${conn.id}&return=${encodeURIComponent(back)}`, 'cache-control': 'no-store' } };
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
{ method: 'GET', pattern: '/v1/connection_reconnect_done', public: true, handler: () => ({ headers: { 'cache-control': 'no-store' }, body: { object: 'connection_reconnect_done', ok: true } }) },
|
|
290
|
+
// ── Shopify: non-expiring offline token to an expiring one ──
|
|
291
|
+
{
|
|
292
|
+
method: 'POST',
|
|
293
|
+
pattern: '/v1/connections/:id/token/exchange',
|
|
294
|
+
scope: 'connections:token',
|
|
295
|
+
handler: async (c) => {
|
|
296
|
+
const e = c.engine;
|
|
297
|
+
const conn = connOf(e, c.params.id);
|
|
298
|
+
if (conn.provider !== 'shopify')
|
|
299
|
+
throw bad('Only a Shopify connection has a token to exchange.', 'provider');
|
|
300
|
+
if (conn.status === 'revoked')
|
|
301
|
+
throw new errors_1.EmulatorError('CONFLICT', 'This connection is revoked.');
|
|
302
|
+
if (conn.expiring === true)
|
|
303
|
+
throw new errors_1.EmulatorError('CONFLICT', 'This connection already holds an expiring token.');
|
|
304
|
+
const shop = String(conn.host_params?.shop ?? conn.config?.shop ?? (conn.allowed_hosts ?? [])[0] ?? '');
|
|
305
|
+
const host = shop.includes('.') ? shop : `${shop}.myshopify.com`;
|
|
306
|
+
// The app secret goes only to the shop's own host.
|
|
307
|
+
if (!/^[a-z0-9][a-z0-9-]*\.myshopify\.com$/i.test(host))
|
|
308
|
+
throw bad('The exchange only runs against a *.myshopify.com shop.', 'host');
|
|
309
|
+
if (!e.options.fetch)
|
|
310
|
+
throw new errors_1.EmulatorError('OAUTH_EXCHANGE_FAILED', 'The emulator has no outbound fetch: pass the `fetch` option to play the Shopify token endpoint.');
|
|
311
|
+
let res;
|
|
312
|
+
try {
|
|
313
|
+
res = await e.options.fetch(`https://${host}/admin/oauth/access_token`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange', expiring: 1 }) });
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
throw new errors_1.EmulatorError('OAUTH_EXCHANGE_FAILED', 'The shop could not be reached; the token is unchanged.');
|
|
317
|
+
}
|
|
318
|
+
const json = res.ok ? await res.json().catch(() => null) : null;
|
|
319
|
+
if (!json || typeof json.access_token !== 'string') {
|
|
320
|
+
record(e, conn.id, 'token_exchange', 'error', { host, status: res.status });
|
|
321
|
+
throw new errors_1.EmulatorError('OAUTH_EXCHANGE_FAILED', 'Shopify refused the exchange; the token is unchanged.', undefined, { meta: { provider_status: res.status } });
|
|
322
|
+
}
|
|
323
|
+
conn.expiring = true;
|
|
324
|
+
conn.has_refresh_token = typeof json.refresh_token === 'string';
|
|
325
|
+
conn.updated_at = e.clock.now();
|
|
326
|
+
record(e, conn.id, 'token_exchange', 'ok', { host, status: res.status });
|
|
327
|
+
return { body: { object: 'connection_token_exchange', connection_id: conn.id, exchanged: true, expiring: true, has_refresh_token: conn.has_refresh_token, expires_in: Number(json.expires_in) || null } };
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
];
|
|
331
|
+
}
|
|
332
|
+
//# sourceMappingURL=connections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connections.js","sourceRoot":"","sources":["../../src/handlers/connections.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Engine, RouteContext, RouteDef } from '../engine';
|
|
2
|
+
import type { Obj } from '../openapi';
|
|
3
|
+
export declare const resetDevice: (e: Engine) => void;
|
|
4
|
+
/** The unified `grants` claim entry (machine and agent grants share one shape). */
|
|
5
|
+
export declare const tokenGrant: (g: {
|
|
6
|
+
type: "machine" | "agent";
|
|
7
|
+
id: string;
|
|
8
|
+
resource: string;
|
|
9
|
+
scopes: string[];
|
|
10
|
+
kind?: string | null;
|
|
11
|
+
constraints?: Obj | null;
|
|
12
|
+
expiresAt?: number | null;
|
|
13
|
+
}) => Obj;
|
|
14
|
+
/** A resource server by identifier or id (the generic CRUD layer stores them), or a bare identifier when none is stored. */
|
|
15
|
+
export declare function resourceServerOf(e: Engine, ref: string): {
|
|
16
|
+
id: string | null;
|
|
17
|
+
identifier: string;
|
|
18
|
+
row: Obj | null;
|
|
19
|
+
};
|
|
20
|
+
export declare const presentAgent: (m: Obj) => Obj;
|
|
21
|
+
export declare const presentAccessRequest: (r: Obj) => Obj;
|
|
22
|
+
/** An agent grant is an approved, unexpired access request. The usage routes (`/v1/grants/agent/:id/...`) resolve through this. */
|
|
23
|
+
export declare function agentGrant(e: Engine, id: string | undefined): Obj | undefined;
|
|
24
|
+
export declare function deviceHandlers(): RouteDef[];
|
|
25
|
+
/** What a request proved about the key or certificate it holds, for sender-constrained tokens (`cnf`). */
|
|
26
|
+
export interface ProvedBinding {
|
|
27
|
+
jkt?: string;
|
|
28
|
+
x5t?: string;
|
|
29
|
+
}
|
|
30
|
+
/** Throws the validation error a machine's `token_binding` demands when `proved` does not satisfy it. */
|
|
31
|
+
export declare function enforceTokenBinding(m: Obj, proved: ProvedBinding): void;
|
|
32
|
+
export declare const cnfOf: (p: ProvedBinding) => Obj | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Mint a machine token for `m` from the request fields (`audience`, `scopes`, `organization_id`). Every route that
|
|
35
|
+
* issues one (signed challenge, federation) goes through here, so claims never differ by way in. `beforeIssue` runs after
|
|
36
|
+
* every refusal and before the token is signed (the challenge route spends its nonce there).
|
|
37
|
+
*/
|
|
38
|
+
export declare function issueMachineToken(c: RouteContext, m: Obj, req: Obj, opts?: {
|
|
39
|
+
proved?: ProvedBinding;
|
|
40
|
+
maxTtlSeconds?: number;
|
|
41
|
+
extraClaims?: Obj;
|
|
42
|
+
beforeIssue?: () => void;
|
|
43
|
+
}): Promise<{
|
|
44
|
+
body: Obj;
|
|
45
|
+
}>;
|
|
46
|
+
/** The binding a request proves on a machine route: a DPoP proof (htm POST, htu this URL, single-use jti) and/or a forwarded client certificate. */
|
|
47
|
+
export declare function provedBindingOf(c: RouteContext): Promise<ProvedBinding>;
|