1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Cloudflare Workers + HonoJSチュートリアル③:API Key 認証

Last updated at Posted at 2025-01-04

はじめに

前回は JWT (JSON Web Token) による認証を導入し、トークンを用いたセキュアな API アクセス方法を紹介しました。

今回は API Key を用いたシンプルな認証方法を実装します。
API Key 方式は、特定のクライアントだけに鍵を配布し、それをヘッダーなどに含めることでアクセスを制限する仕組みです。


1. API Key 認証の概要

  • API Key はランダムに生成された文字列を使い、クライアントがリクエスト時に付与します。
  • Hono (Cloudflare Workers) では、ミドルウェアを利用して API Key の検証を行い、正しくない場合は 401 (Unauthorized) を返却します。

mermaid 図:API Key 認証フロー


2. 環境変数 (.env) の導入

API Key をソースコード内に直書きすると、漏洩リスクが高まります。
.dev.vars ファイルにキーを記述し、公開リポジトリには含めない運用にしましょう。

touch .dev.vars

.env ファイルの例:

API_KEY=my-very-secret-api-key
PORT=3000

.gitignore.dev.vars を追加し、リポジトリに含めないようにします。


3. ディレクトリ構成

前回までのチュートリアルと同様に、認証用のロジックは middlewares/ に配置すると整理しやすいです。

my-hono-crud/
├─ .dev.vars
├─ package.json
├─ tsconfig.json
├─ src/
│   ├─ index.ts           // エントリーポイント
│   ├─ middlewares/
│   │   └─ apiKeyAuth.ts  // API Key検証ミドルウェア
│   └─ users/
│       └─ index.ts
└─ ...

4. コード例

4-1. src/middlewares/apiKeyAuth.ts

API Key を検証するミドルウェアを作成します。以下の例では、Authorization ヘッダーに Bearer <YOUR_API_KEY> の形式でキーが渡される想定です。

import { Context, Next } from 'hono'
import 'dotenv/config'

export const apiKeyAuthMiddleware = async (c: Context, next: Next) => {
  const authHeader = c.req.header('Authorization') // "Bearer xxx" が入る想定

  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return c.json({ error: 'No or invalid API Key header' }, 401)
  }

  const apiKey = authHeader.replace('Bearer ', '')

  // 環境変数のAPI_KEYと一致するか確認
  if (apiKey !== c.env.API_KEY) {
    return c.json({ error: 'Invalid API Key' }, 401)
  }

  // OK なら次へ
  await next()
}

4-2. src/users/index.ts

ユーザー CRUD のエンドポイントへアクセスする前に、上記の apiKeyAuthMiddleware を適用します。

import { Hono } from 'hono'
import { apiKeyAuthMiddleware } from '../middlewares/apiKeyAuth'

type User = { id: number; name: string }
let users: User[] = []

const userApp = new Hono()

// すべてのエンドポイントに対してAPI Key認証を要求
userApp.use('*', apiKeyAuthMiddleware)

// Create: ユーザー作成 (POST /users)
userApp.post('/', async (c) => {
  const { name } = await c.req.json()
  const newUser: User = {
    id: Date.now(),
    name
  }
  users.push(newUser)
  return c.json({ message: 'User created', user: newUser })
})

// Read: 全ユーザー取得 (GET /users)
userApp.get('/', (c) => {
  return c.json(users)
})

// Read: 特定ユーザー取得 (GET /users/:id)
userApp.get('/:id', (c) => {
  const userId = parseInt(c.req.param('id'))
  const user = users.find((u) => u.id === userId)
  if (!user) {
    return c.json({ error: 'User not found' }, 404)
  }
  return c.json(user)
})

// Update: ユーザー更新 (PATCH /users/:id)
userApp.patch('/:id', async (c) => {
  const userId = parseInt(c.req.param('id'))
  const { name } = await c.req.json()
  const userIndex = users.findIndex((u) => u.id === userId)

  if (userIndex === -1) {
    return c.json({ error: 'User not found' }, 404)
  }

  users[userIndex].name = name
  return c.json({ message: 'User updated', user: users[userIndex] })
})

// Delete: ユーザー削除 (DELETE /users/:id)
userApp.delete('/:id', (c) => {
  const userId = parseInt(c.req.param('id'))
  const userIndex = users.findIndex((u) => u.id === userId)

  if (userIndex === -1) {
    return c.json({ error: 'User not found' }, 404)
  }

  const deletedUser = users.splice(userIndex, 1)[0]
  return c.json({ message: 'User deleted', user: deletedUser })
})

export default userApp

4-3. src/index.ts

メインのエントリーポイントで userApp を呼び出します。

import { Hono } from 'hono'
import userApp from './users/index'

const app = new Hono()

// "/users" 以下へのルートを委譲
app.route('/users', userApp)

export default app

5. 動作確認

ローカルで npm start (あるいは wrangler dev) などを実行し、以下のコマンドでテストしてみましょう。

5-1. ユーザー作成 (POST /users)

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer my-very-secret-api-key" \
  -d '{"name":"Alice"}' \
  http://localhost:8787/users
  • -H "Authorization: Bearer <API_KEY>" の形で API Key を指定します。
  • .envAPI_KEY=my-very-secret-api-key と一致しない場合は、401 Unauthorized が返されます。

5-2. ユーザー取得 (GET /users, GET /users/:id)

curl -X GET \
  -H "Authorization: Bearer my-very-secret-api-key" \
  http://localhost:8787/users

その他、PATCH / DELETE なども同様に Authorization ヘッダーを付与することでアクセス可能です。


6. まとめと応用

  • API Key 方式 はシンプルで実装しやすいですが、鍵の漏洩リスクに注意が必要です。
  • 環境変数 (.env) によるキー管理を行い、ソースコードに直書きしないようにしましょう。
  • 鍵の定期的なローテーション や、使用期限を設ける運用なども検討するとより安全です。
  • 本番運用では、HTTPS (SSL/TLS) 化した環境で運用し、通信経路を暗号化しておきましょう。

これで API Key 認証 を導入した Hono アプリのチュートリアルは完了です。
今までに紹介した JWT 認証API Key 認証 は用途によって使い分けることが多いので、運用シーンに応じて最適な方法を選んでみてください。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?