@veraid/kliento-verifier
Version:
Self-contained client authentication tokens
53 lines • 1.91 kB
JavaScript
import { TokenBundle } from '@veraid/kliento';
import { Hono } from 'hono';
import { STATUS_CODES } from './utils/http.js';
export const CONTENT_TYPES = {
AUTH_HEADER: 'application/vnd.kliento.auth-header',
TOKEN_BUNDLE: 'application/vnd.kliento.token-bundle',
};
async function deserialiseTokenBundle(context) {
const contentType = context.req.header('content-type');
if (!contentType || contentType === CONTENT_TYPES.TOKEN_BUNDLE) {
const body = await context.req.arrayBuffer();
try {
return TokenBundle.deserialise(body);
}
catch (error) {
return context.json({ error: error.message, status: 'malformed' }, STATUS_CODES.OK);
}
}
if (contentType === CONTENT_TYPES.AUTH_HEADER) {
const body = await context.req.text();
try {
return TokenBundle.deserialiseFromAuthHeader(body);
}
catch (error) {
return context.json({ error: error.message, status: 'malformed' }, STATUS_CODES.OK);
}
}
return context.json({ error: 'Unrecognised content type' }, STATUS_CODES.UNSUPPORTED_MEDIA_TYPE);
}
const app = new Hono().post('/', async (context) => {
const audience = context.req.query('audience');
if (!audience) {
return context.json({ error: 'Audience is missing from the query string' }, STATUS_CODES.BAD_REQUEST);
}
const tokenBundle = await deserialiseTokenBundle(context);
if (tokenBundle instanceof Response) {
return tokenBundle;
}
let result;
try {
result = await tokenBundle.verify(audience);
}
catch (error) {
return context.json({ error: error.message, status: 'invalid' }, STATUS_CODES.OK);
}
return context.json({
claims: result.claims,
status: 'valid',
subject: result.subjectId,
});
});
export default app;
//# sourceMappingURL=app.js.map