@openape/auth
v0.10.1
Published
OpenApe authentication: IdP + SP OIDC protocol logic
Downloads
1,945
Readme
@openape/auth
DDISA protocol implementation for both Identity Providers (IdP) and Service Providers (SP). Framework-agnostic — provides the authorization flow logic, token exchange, WebAuthn integration, and store interfaces without binding to any HTTP framework.
Note: The DDISA protocol uses an authorize/token/callback pattern but is its own protocol — not a standard OAuth or federation profile. Tokens are called assertions, not ID tokens.
Installation
npm install @openape/authPeer dependency: @openape/core
IdP API
Functions for building an Identity Provider.
Authorization
validateAuthorizeRequest(params)— Validate incoming authorization request parametersevaluatePolicy(params)— Evaluate IdP policy for a given SP and user
Token Exchange
handleTokenExchange(params, stores)— Exchange authorization code for a signed assertionissueAssertion(params)— Issue a signed DDISA assertion JWT
JWKS
generateJWKS(keyStore)— Generate a JWKS response from stored keysserveJWKS(handler, keyStore)— Serve the/.well-known/jwks.jsonendpoint
WebAuthn
Registration and authentication using passkeys.
createRegistrationOptions(rpConfig, credential, challenge)— Generate WebAuthn registration optionscreateAuthenticationOptions(challenge)— Generate WebAuthn authentication optionsverifyRegistration(response, challenge, credential)— Verify registration response, returnsWebAuthnCredentialverifyAuthentication(response, challenge, credential)— Verify authentication responseuint8ArrayToBase64URL(array)/base64URLToUint8Array(str)— Encoding helpers
WebAuthn Config
interface RPConfig {
name: string // Relying party display name
id: string // Relying party ID (domain)
origin: string // Expected origin
}SP API
Functions for building a Service Provider.
discoverIdP(domain)— Discover IdP configuration via DNScreateAuthorizationURL(options)— Build authorization URL with PKCEhandleCallback(params, options)— Handle callback, exchange code for assertioncreateSPManifest(config)— Create an SP manifest objectserveSPManifest(handler, manifest)— Serve the/.well-known/sp-manifest.jsonendpoint
Store Interfaces
The IdP requires several stores for state management. In-memory implementations are included for development.
CodeStore
interface CodeStore {
save(entry: CodeEntry): Promise<void>
find(code: string): Promise<CodeEntry | null>
delete(code: string): Promise<void>
}KeyStore
interface KeyStore {
getSigningKey(): Promise<KeyEntry>
getAllPublicKeys(): Promise<KeyEntry[]>
}ConsentStore
interface ConsentStore {
hasConsent(userId: string, clientId: string): Promise<boolean>
save(entry: ConsentEntry): Promise<void>
}ChallengeStore
interface ChallengeStore {
save(challenge: WebAuthnChallenge): Promise<void>
find(challengeId: string): Promise<WebAuthnChallenge | null>
delete(challengeId: string): Promise<void>
}CredentialStore
interface CredentialStore {
save(credential: WebAuthnCredential): Promise<void>
find(id: string): Promise<WebAuthnCredential | null>
list(userId: string): Promise<WebAuthnCredential[]>
delete(id: string): Promise<void>
}RegistrationUrlStore
interface RegistrationUrlStore {
save(entry: RegistrationUrl): Promise<void>
find(token: string): Promise<RegistrationUrl | null>
delete(token: string): Promise<void>
list(userId: string): Promise<RegistrationUrl[]>
}In-memory implementations: InMemoryCodeStore, InMemoryConsentStore, InMemoryKeyStore.
Example: SP Login Flow
import { discoverIdP, createAuthorizationURL, handleCallback } from '@openape/auth'
import { resolveIdP } from '@openape/core'
// 1. Discover the user's IdP via DNS
const idpUrl = await resolveIdP('[email protected]'.split('@')[1])
// 2. Build the authorization URL with PKCE
const { authorizationUrl, codeVerifier, state, nonce } = await createAuthorizationURL({
idpUrl,
clientId: 'sp.example.com',
redirectUri: 'https://sp.example.com/callback',
})
// → Redirect user to authorizationUrl
// 3. Handle the callback after user authenticates
const { user } = await handleCallback(
{ code, state },
{ codeVerifier, nonce, idpUrl, clientId: 'sp.example.com', redirectUri: 'https://sp.example.com/callback' }
)
// user.sub = '[email protected]', user.act = 'human'