@aiquants/auth-core
v0.6.1
Published
Transport-agnostic auth core: shared session/profile types, email/domain allowlist policy, and localizable auth error messages. No framework or provider SDK dependency.
Downloads
873
Readme
@aiquants/auth-core
Transport- and provider-agnostic authentication core: shared session/profile types, an email/domain allowlist policy, and localizable auth error messages. No framework or Google SDK dependency — pair it with a framework adapter (@aiquants/auth-react-router).
Install
Inside this monorepo it is already wired as a pnpm workspace package:
"dependencies": { "@aiquants/auth-core": "workspace:*" }API
AuthenticationPayload,GoogleProfileBase,SessionProfile,MyGoogleProfile— the session/profile types re-homed from the app's@coji/remix-auth-googlemodule augmentation so non-auth code can import them without pulling in remix-auth.emailDomainAllowlist(allowedEmails, allowedDomains)→(email) => boolean— trim+lowercase normalized, logical OR of exact-email and domain match, fail-closed (throws when both lists empty).parseAllowlistCsv(raw)parses a comma-separated env value. Domain patterns accept bothexample.comand@example.com(a leading@is stripped), because env values are usually written bare while admin UIs tend to teach the@-prefixed form. Matching is exact on the host —example.comnever grantsevil-example.comorsub.example.com.normalizeAuthEmail(email)— the single comparison form (trim+toLowerCase) shared by the allowlist predicate, the external directory ledger, and membership matching. Two normalizers would let an address be present in one surface and absent in another with nothing raising an error.AuthUser/AuthGroup/AuthGroupMember/AuthAllowlistEntry— entity types for a user/group administration surface (see@aiquants/auth-react-router/admin).AuthGroup.externalLink(AuthGroupExternalLink) records that an upstream directory owns the group's name and membership;AuthGroup.readOnlyis the flag the UI acts on. Role assignment stays local, so an upstream change never grants privileges by itself.AuthAllowlistEntryis a discriminated union ontype:email/domainrows carry a literalpattern,grouprows carry agroupId. A group's address can be renamed upstream, so it is never the canonical value.AuthAllowlistEntry.ownersays who may edit the row (deployment= immutable env-var source,tenant= that tenant's administrators). It is deliberately not a login-time filter: authentication happens before a tenant is resolved.readOnlyis required on both types. Making it optional would introduce an implicit "unset means editable" default.
AuthDirectoryStatus— health of the external directory synchronization.isStaleistruewhen a sync has never succeeded, because "unknown" is not evidence of health.defaultAuthMessages/AuthMessages/resolveAuthMessages(over?)— the Japanese login-page error strings, overridable per app.
Session profile shape (byte-compatible contract)
SessionProfile is the exact value persisted in the "__session" cookie under key "user":
{ id, displayName, name: { familyName, givenName }, emails: [{ value }],
accessToken, refreshToken?, expirationDateMs?, provider, role? }photo / _json / photos are intentionally excluded. Changing this shape invalidates live 30-day session cookies.
MIT
