@agenticprimitives/connect-client
v1.0.0-alpha.9
Published
Generic relying-party connect client: hand off to the central-auth Home (FedCM-first → OIDC redirect/popup), exchange the code for an SA-signed scoped delegation. The relying half of spec 230/259; no credential ever originates in the relying app.
Maintainers
Readme
@agenticprimitives/connect-client
The relying-party half of Connect. A relying app makes no credential or OAuth request itself: it hands
off to the user's central-auth Home (the IdP) — which runs the credential ceremony (wallet / Google /
YouVersion / passkey) and custody — and gets back an SA-signed scoped delegation. Standard OIDC
(authorize → code → /token) with a seamless FedCM-first front.
See spec 295, spec 230 / 259, ADR-0019, ADR-0021, ADR-0032.
Why
YouVersion/Google OAuth clients are origin-pinned to the registered Home origin. If a relying app originates the OAuth itself (from its own origin), strict providers reject it. The fix — and the doctrine — is that the Home is the single credential/OAuth origin; relying apps only ever exchange a returned code. This package is that relying-side protocol, extracted once instead of copied per app.
Usage
import { createConnectClient, connectViaFedcm, connectViaPopup, connectViaRedirect } from '@agenticprimitives/connect-client';
// The app injects its domain.ts — NO hostnames live in this package (ADR-0021).
const connect = createConnectClient({
clientId: 'demo-web',
delegate: '0x…', // the relying-site backend account the Home scopes its grant to
redirectUri: () => window.location.origin + '/',
resolveAuthOrigin: (name) => resolveHomeOrigin(name), // app: name → <home> | apex
isAllowedIssuerOrigin: (o) => isAllowedHome(o), // app: issuer allowlist
});
// FedCM-first, then popup, then redirect (the seamless launcher):
try {
const r = await connectViaFedcm(await resolveHomeOrigin(''), 'demo-web', onProgress);
// r.idToken + r.delegation — done, no /token round-trip
} catch {
const p = await connectViaPopup(connect, name, 'demo-web-connect-relay', onProgress, signal);
if (p.status === 'blocked') {
const { url, stash } = await connectViaRedirect(connect, name);
sessionStorage.setItem('connect', JSON.stringify(stash));
window.location.href = url; // returns ?code&state
} else if (p.status === 'success') {
const tok = await connect.exchangeCode(p.authOrigin, p.code, p.codeVerifier);
await connect.verifyIdToken(p.authOrigin, tok.idToken, p.stash.nonce);
}
}On ?code&state return (the redirect path), read the stash, exchangeCode, then verifyIdToken.
Boundary
Relying side only. The broker/Home side is @agenticprimitives/connect; credential ceremonies live at the
Home (connect-auth). This package imports only @agenticprimitives/types + @agenticprimitives/fedcm-rp,
is WebCrypto-only, and contains no hostnames.
