@e280/authlocal
Version:
User-sovereign login system for everybody
58 lines (47 loc) • 1.6 kB
text/typescript
import {signClaim} from "../claim/sign.js"
import {verifyClaim} from "../claim/verify.js"
import {tokentime} from "../token/tokentime.js"
import {getAppOriginFromProofToken, verifyProof} from "./proof.js"
import {LoginSignClaimOptions, Proof, Session, VerifyLoginOptions} from "./types.js"
export class Login {
static async verify({session, appOrigins}: VerifyLoginOptions) {
const {proofToken} = session
const proof = await verifyProof({proofToken, appOrigins})
const proofAppOrigin = getAppOriginFromProofToken(proofToken)
return new this(session, proof, proofAppOrigin)
}
constructor(
public readonly session: Session,
public readonly proof: Proof,
public readonly proofAppOrigin: string,
) {}
get nametag() { return this.proof.nametag }
get sessionId() { return this.proof.sessionId }
get proofToken() { return this.session.proofToken }
get expiresAt() {
const expiresAt = tokentime.readExpiresAt(this.proofToken)
if (expiresAt === undefined)
throw new Error("misconfigured proof token will never expire")
return expiresAt
}
isExpired(time = Date.now()) {
return tokentime.isExpired(this.proofToken, time)
}
async signClaim<C>(options: LoginSignClaimOptions<C>) {
const claimToken = await signClaim({
...options,
session: this.session,
appOrigin: this.proofAppOrigin,
})
// self-verify, helping to catch errors earlier
await verifyClaim({
claimToken,
atTime: options.atTime,
appOrigins: [this.proofAppOrigin],
allowedAudiences: options.audience
? [options.audience]
: undefined,
})
return claimToken
}
}