コンテンツにスキップ

Hono、Koa & NestJSアダプター

概要

@authrim/serverHonoKoaNestJS 向けのアダプターを提供します。各アダプターはアクセストークン(BearerおよびDPoP)を検証し、フレームワーク固有の慣用的なパターンで認証済みユーザーコンテキストを公開します。

ExpressとFastifyについては、Express & Fastifyアダプターを参照してください。

Honoアダプター

@authrim/server/adapters/hono からインポートします。

Honoは認証データに(リクエストプロパティへの直接設定ではなく)コンテキスト変数を使用します。アクセスには getAuth()getAuthTokenType() ヘルパー関数を使用してください。

authrimMiddleware()

必須認証 — 未認証のリクエストに401を返します:

import { Hono } from 'hono';
import { createAuthrimServer } from '@authrim/server';
import {
authrimMiddleware,
getAuth,
getAuthTokenType,
} from '@authrim/server/adapters/hono';
const server = createAuthrimServer({
issuer: 'https://auth.example.com',
audience: 'https://api.example.com',
});
const app = new Hono();
// Protect all routes under /api
app.use('/api/*', authrimMiddleware(server));
app.get('/api/profile', (c) => {
const auth = getAuth(c); // ValidatedToken (guaranteed)
const type = getAuthTokenType(c); // 'Bearer' | 'DPoP'
return c.json({ sub: auth.sub, tokenType: type });
});

authrimOptionalMiddleware()

オプション認証 — 未認証のリクエストでも処理を続行します:

import {
authrimOptionalMiddleware,
getAuth,
} from '@authrim/server/adapters/hono';
app.get('/api/feed', authrimOptionalMiddleware(server), (c) => {
const auth = getAuth(c);
if (auth) {
return c.json({ feed: getPersonalizedFeed(auth.sub) });
}
return c.json({ feed: getPublicFeed() });
});

ヘルパー関数

関数戻り値の型説明
getAuth(c)ValidatedToken | undefinedHonoコンテキストから検証済みトークンを取得
getAuthTokenType(c)'Bearer' | 'DPoP' | undefinedHonoコンテキストからトークンタイプを取得

Cloudflare Workersサンプル

HonoはCloudflare Workersにデプロイされることが多いフレームワークです。以下に完全なサンプルを示します:

src/index.ts
import { Hono } from 'hono';
import { createAuthrimServer } from '@authrim/server';
import {
authrimMiddleware,
authrimOptionalMiddleware,
getAuth,
} from '@authrim/server/adapters/hono';
type Bindings = {
AUTHRIM_ISSUER: string;
AUTHRIM_AUDIENCE: string;
};
const app = new Hono<{ Bindings: Bindings }>();
app.use('/api/*', async (c, next) => {
const server = createAuthrimServer({
issuer: c.env.AUTHRIM_ISSUER,
audience: c.env.AUTHRIM_AUDIENCE,
});
return authrimMiddleware(server)(c, next);
});
app.get('/api/profile', (c) => {
const auth = getAuth(c);
return c.json({ sub: auth!.sub });
});
app.get('/health', (c) => c.json({ status: 'ok' }));
export default app;
wrangler.toml
name = "my-api"
main = "src/index.ts"
compatibility_date = "2024-12-01"
[vars]
AUTHRIM_ISSUER = "https://auth.example.com"
AUTHRIM_AUDIENCE = "https://api.example.com"

Honoでのスコープ検証

import { createMiddleware } from 'hono/factory';
function requireScope(...scopes: string[]) {
return createMiddleware(async (c, next) => {
const auth = getAuth(c);
if (!auth) {
return c.json({ error: 'unauthorized' }, 401);
}
const tokenScopes = auth.scope?.split(' ') ?? [];
const hasAll = scopes.every((s) => tokenScopes.includes(s));
if (!hasAll) {
return c.json({
error: 'insufficient_scope',
required: scopes,
}, 403);
}
await next();
});
}
app.get('/api/admin', authrimMiddleware(server), requireScope('admin:read'), (c) => {
return c.json({ admin: true });
});

Koaアダプター

@authrim/server/adapters/koa からインポートします。

Koaは認証データを ctx.state に格納します。

authrimMiddleware()

必須認証

import Koa from 'koa';
import Router from '@koa/router';
import { createAuthrimServer } from '@authrim/server';
import { authrimMiddleware } from '@authrim/server/adapters/koa';
const server = createAuthrimServer({
issuer: 'https://auth.example.com',
audience: 'https://api.example.com',
});
const app = new Koa();
const router = new Router();
// Protect all API routes
app.use(authrimMiddleware(server));
router.get('/api/profile', (ctx) => {
ctx.body = {
sub: ctx.state.auth.sub,
tokenType: ctx.state.authTokenType,
};
});
app.use(router.routes());
app.listen(3000);

authrimOptionalMiddleware()

オプション認証

import { authrimOptionalMiddleware } from '@authrim/server/adapters/koa';
router.get('/api/feed', authrimOptionalMiddleware(server), (ctx) => {
if (ctx.state.auth) {
ctx.body = { feed: getPersonalizedFeed(ctx.state.auth.sub) };
} else {
ctx.body = { feed: getPublicFeed() };
}
});

ステートプロパティ

プロパティ説明
ctx.state.authValidatedToken | undefined検証済みトークンのクレーム
ctx.state.authTokenType'Bearer' | 'DPoP' | undefined使用されたトークンタイプ

Koa完全サンプル

import Koa from 'koa';
import Router from '@koa/router';
import { createAuthrimServer } from '@authrim/server';
import {
authrimMiddleware,
authrimOptionalMiddleware,
} from '@authrim/server/adapters/koa';
const server = createAuthrimServer({
issuer: 'https://auth.example.com',
audience: 'https://api.example.com',
});
const app = new Koa();
const router = new Router();
// Health check — no auth
router.get('/health', (ctx) => {
ctx.body = { status: 'ok' };
});
// Optional auth
router.get('/api/posts', authrimOptionalMiddleware(server), (ctx) => {
const user = ctx.state.auth?.sub ?? 'anonymous';
ctx.body = { user, posts: getPosts(user) };
});
// Protected routes
const protectedRouter = new Router({ prefix: '/api/me' });
protectedRouter.use(authrimMiddleware(server));
protectedRouter.get('/profile', (ctx) => {
ctx.body = { sub: ctx.state.auth.sub, email: ctx.state.auth.email };
});
protectedRouter.get('/settings', (ctx) => {
ctx.body = { settings: getUserSettings(ctx.state.auth.sub) };
});
app.use(router.routes());
app.use(protectedRouter.routes());
app.listen(3000);

KoaのTypeScript型拡張

import type { ValidatedToken } from '@authrim/server';
declare module 'koa' {
interface DefaultState {
auth: ValidatedToken;
authTokenType: 'Bearer' | 'DPoP';
}
}

NestJSアダプター

@authrim/server/adapters/nestjs からインポートします。

NestJSはルート保護に Guard を使用します。アダプターはNestJSの依存性注入システムと互換性のあるGuardクラスを生成するファクトリ関数を提供します。

createAuthrimGuard()

必須認証 — 無効なトークンに対して HttpException(401) をスローします:

import { Module, Controller, Get, UseGuards } from '@nestjs/common';
import { HttpException } from '@nestjs/common';
import { createAuthrimServer } from '@authrim/server';
import {
createAuthrimGuard,
getAuthFromRequest,
getAuthTokenTypeFromRequest,
} from '@authrim/server/adapters/nestjs';
const server = createAuthrimServer({
issuer: 'https://auth.example.com',
audience: 'https://api.example.com',
});
const AuthGuard = createAuthrimGuard(server, HttpException);
@Controller('api')
@UseGuards(AuthGuard)
export class ApiController {
@Get('profile')
getProfile(@Req() req: Request) {
const auth = getAuthFromRequest(req);
const tokenType = getAuthTokenTypeFromRequest(req);
return { sub: auth?.sub, tokenType };
}
}

createAuthrimOptionalGuard()

オプション認証 — 未認証のリクエストを拒否しません:

import { createAuthrimOptionalGuard } from '@authrim/server/adapters/nestjs';
const OptionalAuthGuard = createAuthrimOptionalGuard(server);
@Controller('public')
@UseGuards(OptionalAuthGuard)
export class PublicController {
@Get('feed')
getFeed(@Req() req: Request) {
const auth = getAuthFromRequest(req);
if (auth) {
return { feed: getPersonalizedFeed(auth.sub) };
}
return { feed: getPublicFeed() };
}
}

ヘルパー関数

関数戻り値の型説明
getAuthFromRequest(context)ValidatedToken | undefinedExecutionContext または Request から認証情報を取得
getAuthTokenTypeFromRequest(context)'Bearer' | 'DPoP' | undefinedトークンタイプを取得

カスタム @Auth() パラメータデコレーター

よりクリーンなコントローラーコードのための便利なパラメータデコレーターを作成します:

import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { getAuthFromRequest } from '@authrim/server/adapters/nestjs';
import type { ValidatedToken } from '@authrim/server';
export const Auth = createParamDecorator(
(data: unknown, ctx: ExecutionContext): ValidatedToken | undefined => {
const request = ctx.switchToHttp().getRequest();
return getAuthFromRequest(request);
},
);

コントローラーでの使用方法:

@Controller('api')
@UseGuards(AuthGuard)
export class ApiController {
@Get('profile')
getProfile(@Auth() auth: ValidatedToken) {
return { sub: auth.sub, email: auth.email };
}
}

NestJS完全サンプル

auth.module.ts
import { Module, Global } from '@nestjs/common';
import { HttpException } from '@nestjs/common';
import { createAuthrimServer } from '@authrim/server';
import { createAuthrimGuard, createAuthrimOptionalGuard } from '@authrim/server/adapters/nestjs';
const server = createAuthrimServer({
issuer: process.env.AUTHRIM_ISSUER!,
audience: process.env.AUTHRIM_AUDIENCE!,
});
export const AuthGuard = createAuthrimGuard(server, HttpException, {
realm: 'my-api',
onError: (err) => console.warn('Auth error:', err.code),
});
export const OptionalAuthGuard = createAuthrimOptionalGuard(server);
@Global()
@Module({})
export class AuthModule {}
users.controller.ts
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AuthGuard, OptionalAuthGuard } from './auth.module';
import { Auth } from './auth.decorator';
import type { ValidatedToken } from '@authrim/server';
@Controller('users')
export class UsersController {
@Get('me')
@UseGuards(AuthGuard)
getMe(@Auth() auth: ValidatedToken) {
return { sub: auth.sub, email: auth.email };
}
@Get()
@UseGuards(OptionalAuthGuard)
listUsers(@Auth() auth: ValidatedToken | undefined) {
if (auth) {
return { users: getAllUsers(), requestedBy: auth.sub };
}
return { users: getPublicUsers() };
}
}

フレームワーク比較

項目ExpressFastifyHonoKoaNestJS
認証情報の場所req.authrequest.authgetAuth(c)ctx.state.authgetAuthFromRequest(req)
必須ミドルウェアauthrimMiddleware()authrimPreHandler()authrimMiddleware()authrimMiddleware()createAuthrimGuard()
オプションミドルウェアauthrimOptionalMiddleware()authrimOptionalPreHandler()authrimOptionalMiddleware()authrimOptionalMiddleware()createAuthrimOptionalGuard()
アプリ全体の適用app.use(...)authrimPlugin()app.use(path, ...)app.use(...)コントローラーに @UseGuards()
型安全性declare globaldeclare moduleコンテキスト変数declare moduleパラメータデコレーター

次のステップ