---
title: "Ory Hydraとは？仕組みとv26.2.0の構築手順、ログイン・同意・ログアウトの実装"
url: "https://www.issoh.co.jp/tech/details/10390/"
published: 2025-12-24
updated: 2026-10-23
categories: ["セキュリティ"]
publisher: "株式会社一創"
---

# Ory Hydraとは？仕組みとv26.2.0の構築手順、ログイン・同意・ログアウトの実装

Ory Hydraは、Go製・オープンソースのOAuth 2.0／OpenID Connectサーバーです。ユーザーのデータベースもログイン画面も持たず、「誰がログインしたか」は利用者側のアプリが決め、Hydraはトークンの発行と検証だけを受け持ちます。この記事では、2026年10月時点の最新版v26.2.0を手元で起動した実行結果をもとに、仕組み、ログイン・同意・ログアウト画面との連携、つまずきやすいCSRF Cookieのエラー、本番構成で外せない設定、Keycloakとの選び分けを整理します。

## まとめ：Ory Hydraの要点

- **役割**：OAuth 2.0の認可サーバーとOpenID Connectプロバイダーだけを担う。ユーザー管理・ログイン画面・同意画面は自前で用意するか、同じOryのKratosと組み合わせる
- **最新版**：v26.2.0（2026-03-20）。v2.3.0の次がv25.4.0（2025-11-07）で、ここから年と四半期を表すカレンダー方式（YY.Q.B）の版番号に変わった
- **構成**：公開用のPublic API（4444番）と管理用のAdmin API（4445番）。Admin APIには認証機能が無いので、外部に出さない
- **自分で作るもの**：ログイン画面・同意画面・ログアウト画面・エラー画面。ログイン・同意・ログアウト画面はchallengeを受け取り、サーバー側からAdmin APIのacceptまたはrejectを呼ぶ。エラー画面は受け取ったエラー情報を表示する
- **つまずきやすい点**：「No CSRF value available in the session cookie」は、Cookieが届いていないときに出る。ホスト名の混在と、本番モードでのhttp接続が典型的な原因
- **ライセンス**：Apache-2.0。マネージド版はOry Network（有料は年$770から）
- **向かない場面**：ユーザー管理画面やLDAP連携まで箱から出して使いたいなら、全部入りのKeycloakのほうが早い

## Ory Hydraの位置づけ：ユーザーDBを持たない認可サーバー

OAuth 2.0の認可サーバーは、クライアントの登録、認可コードやトークンの発行、失効、署名鍵の管理を担います。Hydraはこの部分だけを実装し、パスワードの照合や会員情報の保存を持ちません。[GitHubリポジトリ](https://github.com/ory/hydra)の説明文では「integrates with your user management through headless APIs」と説明されています。既に会員DBとログイン画面がある事業者が、その上に「他社アプリにAPIアクセスを許可する仕組み」や社内のSSOを追加するときに向いた作りです。

OAuth 2.0そのものの流れは[OAuth 2.0の仕組みと認可フローの解説](/tech/details/8369/)、IDトークンの検証手順は[OIDC（OpenID Connect）の解説](/tech/details/6532/)にまとめています。

### Oryの製品群とHydraの担当範囲

「ory」で検索するとHydra以外の製品も出てきます。Oryは同じ版番号で複数のサーバーを出しており、2026-03-20（UTC）に次の5製品がそろってv26.2.0になりました。

| 製品             | 担当                    |
| -------------- | --------------------- |
| Ory Hydra      | OAuth 2.0／OIDCのトークン発行 |
| Ory Kratos     | ユーザー登録・ログイン・MFA       |
| Ory Keto       | 権限判定（Zanzibar型）       |
| Ory Oathkeeper | APIの手前で認証・認可するプロキシ    |
| Ory Polis      | SAML／OIDCのエンタープライズSSO |

Hydraにログイン機能を足したいならKratos、APIの手前でトークンを検証したいならOathkeeper、という分担です。すべてを入れる必要はなく、Hydra単体でも既存のログイン画面とつなげば動きます。

### 対応グラントタイプと実装済みの標準仕様

v26.2.0を起動して `/.well-known/openid-configuration` を取得すると、`grant_types_supported` は次の5つでした。

```
["authorization_code", "implicit", "client_credentials", "refresh_token",
 "urn:ietf:params:oauth:grant-type:device_code"]
```

クライアント認証方式（`token_endpoint_auth_methods_supported`）は `client_secret_post`・`client_secret_basic`・`private_key_jwt`・`none` の4つです。`none` はPKCEを使う公開クライアント（SPAやモバイル）向けです。デバイスフロー（RFC 8628）はv25.4.0で入り、同じ版でOAuth 2.0のメタデータ `/.well-known/oauth-authorization-server`（RFC 8414）も返すようになりました。

READMEはほかに、Dynamic Client Registration（RFC 7591）、JWT Profile（RFC 7523）、Token Introspection（RFC 7662）を実装済みとして挙げています。OpenID Foundationの認定はBasic OP・Implicit OP・Hybrid OP・Config OP・Dynamic OPの5プロファイルです（取得はv1.0.0時点）。

MCPの認可仕様（2025-11-25版）が認可サーバーに対応を推奨（SHOULD）しているCIMD（Client ID Metadata Documents）は、v26.2.0の時点で未対応です。2026-01-17に起票された対応要望の[issue #4061](https://github.com/ory/hydra/issues/4061)は、2026-10-23時点でも開いたままです。CIMDの仕組みは[CIMD（Client ID Metadata Documents）の解説](/tech/details/10011/)を参照してください。

## v2.3.0・v25.4.0・v26.2.0の変更点と版番号の変遷

国内の解説記事の多くはv2.x時代のものです。版番号が2から25へ飛んだのは、2025年11月のリリースでOryが年と四半期を表すカレンダー方式（YY.Q.B）の版番号へ切り替えたためで、中身が20世代進んだわけではありません。

| 版       | 公開日        | 主な変更                                 |
| ------- | ---------- | ------------------------------------ |
| v2.3.0  | 2025-01-17 | v2系の最終版。リフレッシュトークンの猶予付きローテーション       |
| v25.4.0 | 2025-11-07 | デバイスフロー、RFC 8414のメタデータ、同意単位のトークン一括失効 |
| v26.2.0 | 2026-03-20 | Postgresのトランザクション自動再試行、依存の脆弱性対応      |

2026-10-23時点で、[v26.2.0](https://github.com/ory/hydra/releases/tag/v26.2.0)より新しいリリースは出ておらず、Docker Hubの `oryd/hydra:latest` もv26.2.0です。v2系から上げるときは、DBマイグレーションに加えて、PostgreSQLで `uuid-ossp` 拡張を有効にしておきます（v25.4.0でUUID生成が `uuid_generate_v4()` に変わったため）。

## アーキテクチャ：Public API（4444）とAdmin API（4445）の分離

Hydraは既定で2つのポートを開きます。

- **Public API（4444）**：`/oauth2/auth`（認可）、`/oauth2/token`（トークン）、`/userinfo`、`/oauth2/sessions/logout`（ログアウト）、`/.well-known/jwks.json` など、クライアントとブラウザが叩くエンドポイント
- **Admin API（4445）**：クライアントの登録、ログイン・同意・ログアウトリクエストの受理と拒否、トークンのイントロスペクションなど、自社のバックエンドだけが叩くエンドポイント

Oryの[本番運用ドキュメント](https://www.ory.com/docs/hydra/self-hosted/production)は、Admin APIについて「None of the administrative endpoints have any built-in access control」と明記しています。4445番に届けば、誰でもクライアントを作成でき、どのユーザーのログインでも承認できます。Admin APIはインターネットに出さず、社内ネットワークに閉じるか、APIゲートウェイで認証をかけてください。環境変数 `SERVE_ADMIN_HOST` に `unix:/var/run/hydra/admin_socket` を設定すると、Admin APIをUNIXソケットにバインドできます。本番運用ドキュメントには旧名の `ADMIN_HOST` が載っていますが、v26.2.0で `ADMIN_HOST` を指定して起動すると、ソケットは作られず全インターフェースの4445番で待ち受けようとしました。

Public API側も、同ドキュメントはAPIゲートウェイかロードバランサーの背後に置き、そこでTLSを終端する構成を強く推奨しています。パスで振り分けるゲートウェイでは、公開ホスト名はそのまま、パスは振り分け用のプレフィックス（例 `/hydra/`）を除いてHydraへ渡す設定が必要です（challengeの値の計算にホストとパスが使われるため）。

## ログイン・同意フローの実装：challengeの取得とacceptによる受理

Hydraを組み込むとき、自社で作るのは次の4つの画面と、Admin APIを呼ぶサーバー側の処理です。

| 設定キー           | 画面      | 受け取る値               | 返す先                   |
| -------------- | ------- | ------------------- | --------------------- |
| `urls.login`   | ログイン    | `login_challenge`   | login accept／reject   |
| `urls.consent` | 同意      | `consent_challenge` | consent accept／reject |
| `urls.logout`  | ログアウト確認 | `logout_challenge`  | logout accept／reject  |
| `urls.error`   | エラー表示   | `error` など          | なし                    |

画面とは別に、どのスコープでどのAPIを守るかというscope体系の設計も自社の仕事です。Hydraはクライアントに許可したscopeの範囲でしかトークンを出しませんが、scopeの名前と意味は決めてくれません。

v26.2.0で認可コードフロー（PKCE付き）を最後まで通したときの流れは次のとおりでした。

1. クライアントがブラウザを `/oauth2/auth?client_id=…&code_challenge=…` へ送る
2. Hydraが `urls.login` の画面へ `?login_challenge=…` を付けてリダイレクトする
3. ログイン画面が `GET /admin/oauth2/auth/requests/login?login_challenge=…` でリクエスト内容を取得する（返るキーは `challenge`・`client`・`requested_scope`・`skip`・`subject` など）
4. ユーザーを自前の方法で認証し、`PUT /admin/oauth2/auth/requests/login/accept` に `subject` を送る。応答の `redirect_to` へブラウザを戻す
5. Hydraが `urls.consent` の画面へ `?consent_challenge=…` を付けてリダイレクトする
6. 同意画面が `requested_scope` を表示し、許可されたら `PUT /admin/oauth2/auth/requests/consent/accept` に `grant_scope` を送る。IDトークンに載せたいクレームは `session.id_token` に入れる
7. Hydraが `redirect_uri` へ `code=ory_ac_…` を返し、クライアントが `/oauth2/token` で交換する

手順4と6の呼び出しをcurlで示します。`LC` には手順2で受け取ったlogin\_challenge、`CC` には手順5で受け取ったconsent\_challengeをそれぞれ設定し、順番に実行してください。subject・grant\_scope・emailは説明用の値なので、認証済みユーザーと実際に許可された内容に置き換えます。ログイン・同意画面のサーバー側で、この2つのHTTPリクエストを送るのが実装の中心です。

```
curl -s -X PUT -H 'Content-Type: application/json' \
  -d '{"subject":"user-123","remember":true,"remember_for":3600}' \
  "http://127.0.0.1:4445/admin/oauth2/auth/requests/login/accept?login_challenge=$LC"

curl -s -X PUT -H 'Content-Type: application/json' \
  -d '{"grant_scope":["openid","offline_access"],"remember":true,
       "session":{"id_token":{"email":"user@example.com"}}}' \
  "http://127.0.0.1:4445/admin/oauth2/auth/requests/consent/accept?consent_challenge=$CC"
```

トークン交換の応答には `access_token`・`id_token`・`refresh_token` が入り、IDトークンの `sub` はログイン受理で送った `user-123`、`email` は同意受理で送った値でした。同じ認可コードをもう一度交換すると `invalid_grant`（The authorization code has already been used）で拒否されます。手順の意味は[認可コードフローの実装手順](/tech/details/16415/)、code\_verifierの作り方は[PKCEの解説](/tech/details/16405/)で詳しく扱っています。

### skipフラグとremember：2回目のログインを省く仕組み

ログイン受理で `"remember": true` を送ると、HydraはブラウザにCookieでセッションを残します。同じブラウザで2回目の認可リクエストを出すと、ログインリクエストの `skip` が `true`、`subject` が `user-123` で返りました。同意も `"remember": true` で受理し、記録が有効な間に同じユーザー・同じクライアントが許可済み範囲のscopeを要求した場合は、同意リクエストの `skip` も `true` になります。

`skip` が `true` のときは、画面を出さずにそのままacceptを返すのが正しい実装です。ここでパスワード入力画面を出すと、SSOのつもりが毎回ログインを求める作りになります。`skip` はHydraが発行したCookieで判定されるため、ブラウザがそのCookieを送らない状況（Cookieの削除、別ブラウザ）では毎回 `false` になります。複数のアプリで1回のログインを使い回す設計の全体像は[SSO（シングルサインオン）の実現方式の解説](/tech/details/15821/)で扱っています。

### prompt=login・max\_age・prompt=noneによるskip判定の違い

クライアントが認可リクエストに付けるOIDCのパラメータで、`skip` の値が変わります。ログイン済み・同意済みのブラウザで試した結果は次のとおりです。

| 認可リクエスト              | login skip   | consent skip |
| -------------------- | ------------ | ------------ |
| パラメータなし（2回目）         | true         | true         |
| `prompt=login`       | false        | true         |
| `max_age=1`（3秒後）     | false        | true         |
| `prompt=none`（未ログイン） | 画面に来ずにエラーで戻る |              |

`prompt=login` と、前回のログインから `max_age` 秒を過ぎたリクエストでは、Cookieが残っていてもHydraは `skip=false` を返し、`subject` も空にします。送金や設定変更の前にパスワードを入れ直させたいクライアントは、この2つで再認証を要求できます。同意の `skip` は別管理で、ログインをやり直させても `true` のままでした。

`prompt=none` は画面を一切出さずにログイン状態を確かめるためのパラメータで、セッションが無いとログイン画面を経由せず、`redirect_uri` へ `error=login_required`（Prompt ‘none’ was requested, but no existing login session was found.）が返ります。同意が無い場合は `consent_required` です（[v26.2.0のconsent/strategy\_default.go](https://github.com/ory/hydra/blob/v26.2.0/consent/strategy%5Fdefault.go)）。

### skip\_consentで同意画面を省くときの注意

自社のアプリのように同意画面を見せる必要が無いクライアントには、`skip_consent: true` を設定できます。ただし、v26.2.0でこのクライアントを試すと、同意リクエストの `skip` は `false` で返り、Hydraは同意画面へリダイレクトしてきました。v26.2.0のソースでは、この項目はクライアントの保存と検証にしか使われておらず、同意を自動で済ませる処理は同意画面の側にあります。

公式のサンプル画面（[hydra-login-consent-nodeのconsent.ts](https://github.com/ory/hydra-login-consent-node/blob/master/src/routes/consent.ts)）は、`consentRequest.skip` か `client.skip_consent` のどちらかが真なら画面を出さずにacceptしています。自作の同意画面でも、同意リクエストに含まれる `client.skip_consent` を見てacceptする分岐を入れてください。ログアウトの確認画面を省く `skip_logout_consent` も同じ扱いです。どちらもAdmin APIからしか設定できず、Dynamic Client Registrationで指定するとエラーになります。

### 既存のLDAP・Active Directoryとつなぐ方法

HydraにはLDAP連携の機能がありません。ログイン画面のサーバーがLDAPやActive Directoryへbindしてパスワードを照合し、成功したらその識別子を `subject` としてacceptに渡します。`subject` にはメールアドレスのように変わりうる値ではなく、社員番号や、ADのobjectGUID・OpenLDAPのentryUUIDのような不変の識別子を使ってください。IDトークンの `sub` はクライアント側でユーザーの主キーとして保存されるため、後から変えると別人扱いになります。

## ログアウトの実装：logout\_challengeとpost\_logout\_redirect\_uri

ログアウトもログインと同じく、Hydraがchallengeを付けて自社の画面へ渡す方式です。RP-Initiated Logout・Front-Channel Logout・Back-Channel Logoutの3つに対応しています（[OryのOpenID Connect logoutドキュメント](https://www.ory.com/docs/oauth2-oidc/oidc-logout)）。v26.2.0で、クライアント起点のログアウトを通した手順は次のとおりでした。

1. クライアントがブラウザを `/oauth2/sessions/logout?id_token_hint=…&post_logout_redirect_uri=…&state=…` へ送る
2. Hydraが `urls.logout` の画面へ `?logout_challenge=…` を付けてリダイレクトする
3. ログアウト画面が `GET /admin/oauth2/auth/requests/logout?logout_challenge=…` で内容を取得する（`subject`・`sid`・`client`・`rp_initiated` などが返る）
4. 確認後に `PUT /admin/oauth2/auth/requests/logout/accept` を呼ぶと、`logout_verifier` 付きのURLが返る。そこへブラウザを戻す
5. Hydraがセッションを消し、`post_logout_redirect_uri` へ `state` を付けて戻す

`post_logout_redirect_uri` は、クライアント登録時の `post_logout_redirect_uris` に入れた値でないと使えません。Oryのドキュメントは、どのセッションを終わらせるかをHydraが判断できるよう、`id_token_hint` を常に付けることを勧めています。

ログアウトの後、同じブラウザで認可リクエストを出すと、ログインの `skip` は `false` に戻りました。一方、同意の `skip` は `true` のままでした。ログアウトで消えるのはログインのセッションで、「このクライアントにこのscopeを許可した」という記録は残ります。同意をやり直させたい場合は、Admin APIの `DELETE /admin/oauth2/auth/sessions/consent` で同意を取り消します。

## エラーの返し方とCSRF Cookieのトラブル

### rejectによるクライアントへのエラー応答

ログインに失敗させたい、ユーザーが同意を拒んだ、という場合はacceptの代わりにrejectを呼びます。

```
curl -s -X PUT -H 'Content-Type: application/json' \
  -d '{"error":"access_denied","error_description":"The resource owner denied the request"}' \
  "http://127.0.0.1:4445/admin/oauth2/auth/requests/login/reject?login_challenge=$LC"
```

応答の `redirect_to` へブラウザを戻すと、クライアントの `redirect_uri` に `error=access_denied&error_description=The+resource+owner+denied+the+request&state=…` が付いて返りました。同意の拒否は `/consent/reject`、ログアウトの取りやめは `/logout/reject` で、ログアウトのrejectは204の空応答を返すため、その後の遷移先はログアウト画面の側で決めます。認可リクエストの `redirect_uri` が登録外のように、クライアントへ戻すこと自体が危ないエラーは、`urls.error` の画面へ送られます。

パスワードを間違えただけのときにrejectすると認可フローそのものが終わるので、その場合はログイン画面にエラーを出して再入力させ、rejectはユーザーがキャンセルしたときや、アカウントが停止されているときに使います。

### 「No CSRF value available in the session cookie」の原因

Hydraは、ログイン画面へ送る前と同意画面へ送る前にCSRF用のCookieをブラウザへ発行し、受理後に戻ってきたリクエストでそのCookieを照合します。これは自作画面のフォームに対するCSRF対策を代替しないため、ログイン・同意画面側でもCSRFトークンを検証します。v26.2.0で同じブラウザから取得したCookieは次の3つでした（`--dev` 付きで起動したため `_dev` が付いています）。

```
ory_hydra_login_csrf_dev_3567479735
ory_hydra_consent_csrf_dev_3567479735
ory_hydra_session_dev
```

末尾の数字はクライアントIDのmurmur3ハッシュで、同じブラウザで複数のクライアントのフローを並行させても混ざらないようにするためのものです。Cookieを持たない状態でログイン受理後の `redirect_to` を開くと、`redirect_uri` に `error=request_forbidden` と「The request is not allowed. No CSRF value available in the session cookie.」が返りました。Oryの[Common CSRF pitfalls](https://www.ory.com/docs/self-hosted/hydra/debug/csrf)が挙げる原因のうち、v26.2.0で確かめたものは次のとおりです。

- **ホスト名の混在**：`localhost:4444` で認可を始めると、Cookieは `localhost` に付きます。一方、acceptが返す `redirect_to` は `urls.self.issuer` のホスト（例 `127.0.0.1:4444`）なので、Cookieが送られず同じエラーになりました。クライアントの認可URLとissuerのホスト名をそろえます
- **本番モードでのhttp**：`--dev` を付けないと、HydraはCookieに必ずSecure属性を付けます（`driver/config/provider.go`）。TLSをゲートウェイで終端していても、ブラウザから見てhttpなら Cookie は送られません
- **SameSiteとiframe**：`serve.cookies.same_site_mode` を `None` にしないと、別サイトのiframeからはCookieが送られません。`None` はhttpsのissuerでしか効かず、httpのissuerでは `Lax` に置き換えられます

同じドキュメントは、リバースプロキシがCookieヘッダーを落としている場合や、パスの書き換えをしている場合も原因になると書いています。ブラウザの開発者ツールで、`redirect_to` へのリクエストに `ory_hydra_login_csrf_…` が載っているかを先に確かめると、原因を絞り込めます。

Cookieのドメインと名前は `serve.cookies.domain`・`serve.cookies.names` で変えられます（[Configuring cookies](https://www.ory.com/docs/hydra/guides/cookies)）。ログイン画面とHydraが別のサブドメインでも、通常はHydraのCookieを共有する必要はありません。ブラウザがHydraへ戻る際にCookieを送信できればよく、親ドメインへの拡張は共有が必要な設計に限ります。

## Hydraを手元で起動する手順（v26.2.0）

GitHubのリリースにはOS別のバイナリがあり、SQLiteを含むビルド（名前に `sqlite` が付くもの）を選べば、DBを用意せずに試せます。以下はmacOS用 `hydra_26.2.0-macOS_sqlite_64bit.tar.gz` で実行した手順です。

### 設定ファイルとsecrets.systemの16文字制約

次の内容を作業ディレクトリの `hydra.yml` に保存します。

```
serve:
  cookies:
    same_site_mode: Lax
urls:
  self:
    issuer: http://127.0.0.1:4444
  login: http://127.0.0.1:3000/login
  consent: http://127.0.0.1:3000/consent
  logout: http://127.0.0.1:3000/logout
  error: http://127.0.0.1:3000/error
  post_logout_redirect: http://127.0.0.1:3000/logged-out
secrets:
  system:
    - thisIsADevSecretOfAtLeast32Chars!!
```

`secrets.system` は機密データのAES-GCM暗号化とHMAC署名に使う鍵で、16文字未満だと起動に失敗します。5文字の値で起動したときのエラーは次のとおりでした。

```
Error: I[#/secrets/system/0] S[#/properties/secrets/properties/system/items/minLength] length must be >= 16, but got 5
```

本番では `openssl rand -base64 32` などで生成した値を使い、`secrets.cookie` と `secrets.pagination` も個別に設定するよう、Oryの本番運用ドキュメントが求めています。`secrets.system` は配列で、先頭が署名・暗号化に使われ、リスト全体が署名検証・復号に使われます。鍵を入れ替えるときは新しい値を先頭に追加し、古い値を後ろに残します。

### マイグレーションと起動（httpsが必須になる条件）

```
tar -xzf hydra_26.2.0-macOS_sqlite_64bit.tar.gz
mkdir -p /tmp/hydra
export DSN='sqlite:///tmp/hydra/db.sqlite?_fk=true&mode=rwc'
./hydra migrate -c hydra.yml sql up -e --yes
./hydra serve -c hydra.yml all --dev --sqa-opt-out
```

`serve all` はPublicとAdminの両方を起動します。`--dev` を外すと、`urls.self.issuer` がhttpのままでは「issuer URL scheme must be HTTPS unless development mode is enabled」で起動しません。ローカル検証だけ `--dev` を付け、本番はissuerをhttpsのURLにします。`--sqa-opt-out` は、起動時に「Software quality assurance features are enabled」と出る匿名の利用統計の送信を止めるオプションです。

### クライアント登録とトークン発行の確認

```
./hydra create client --endpoint http://127.0.0.1:4445 \
  --grant-type client_credentials --scope api.read \
  --token-endpoint-auth-method client_secret_post --format json > client.json
CID=$(jq -r .client_id client.json); SEC=$(jq -r .client_secret client.json)

curl -s -X POST http://127.0.0.1:4444/oauth2/token \
  -d grant_type=client_credentials -d client_id=$CID \
  -d client_secret=$SEC -d scope=api.read
```

応答は `{"access_token":"ory_at_…","expires_in":3599,"scope":"api.read","token_type":"bearer"}` でした。上の例ではフォームでクライアントシークレットを送るため `--token-endpoint-auth-method client_secret_post` を付けています（付けないと `client_secret_basic` で登録され、`invalid_client` で拒否されます）。発行したトークンは `hydra introspect token --endpoint http://127.0.0.1:4445 <token>` で中身を確認でき、`ACTIVE true` と有効期限が表示されます。

### Docker Composeのquickstartとサンプル画面の制約

Dockerで試す場合は、リポジトリ直下の `quickstart.yml` を使います。v26.2.0タグの定義は、`oryd/hydra:v26.2.0` と、Node.js製のサンプルログイン・同意画面 `oryd/hydra-login-consent-node:v26.2.0`（3000番）、SQLiteのボリュームの組み合わせです。ファイル冒頭に「FOR DEMONSTRATION PURPOSES ONLY」とある通り、サンプル画面は foo@bar.com／foobar の固定の組だけを受け付け、subject も固定値を返す作りなので、そのまま本番には使えません。実装の参考にする場合は、固定認証を実際のユーザー認証に置き換え、画面側のCSRF対策なども確認します。

```
git clone https://github.com/ory/hydra.git && cd hydra && git checkout v26.2.0
docker compose -f quickstart.yml up
# PostgreSQLで試すときは quickstart-postgres.yml を重ねる
docker compose -f quickstart.yml -f quickstart-postgres.yml up
```

## アクセストークンの形式：opaqueとJWTの選び方

既定のアクセストークンは `ory_at_` で始まる不透明な文字列（opaque）で、APIサーバーはAdmin APIのイントロスペクションで有効性を確かめます。設定で `strategies.access_token: jwt` にすると、RS256で署名された約1,100文字のJWTに変わり、ペイロードは `iss`・`sub`・`client_id`・`scp`（スコープの配列）・`exp` などでした。

| 観点               | opaque（既定）    | JWT          |
| ---------------- | ------------- | ------------ |
| APIでの検証          | 毎回イントロスペクション  | JWKSで署名検証    |
| 失効の即時反映          | される           | expまで残る      |
| トークン長（実測）        | 94文字          | 約1,100文字     |
| 検証レイテンシ（公式掲載の目安） | 約50ms・通信条件に依存 | 約1ms・実装条件に依存 |
| 中身の露出            | なし            | Base64で読める   |

v26.2.0のソースでは、この設定の説明に「jwt is a bad idea」と書かれています。リンク先の[公式ドキュメント](https://www.ory.com/docs/oauth2-oidc/jwt-access-token)は、失効させたJWTがexpまで有効に見えること、暗号化しない限り誰でも中身を読めること、pairwise subjectなど一部のOIDC機能が動かないことを挙げています。既定のopaqueのまま、イントロスペクションの結果をゲートウェイで短時間キャッシュする構成から始め（保持時間がそのまま失効の反映遅れになります）、イントロスペクションの負荷が問題になってからJWTを検討する順番を勧めます。JWTの検証手順は[JWTの構造と署名検証の解説](/tech/details/13453/)を参照してください。

## 対応データベースとjanitorによる本番運用

Hydra自身は状態を持たず、クライアント、ログイン・同意のセッション、トークン、署名鍵をすべてSQLデータベースに保存します。[OryのDatabaseドキュメント](https://www.ory.com/docs/self-hosted/deployment)はPostgreSQL・MySQL・CockroachDBを「fully supported」とし、SQLiteについては「must not be used in a production deployment」と明記しています。この記事の手順でSQLite版のバイナリを使っているのは手元の検証用だからで、本番はPostgreSQLかMySQLを選びます。v26.2.0の設定例（`internal/config/config.yaml`）ではPostgreSQLに「recommended」と付いています。DSNを `memory` にすると、再起動でデータがすべて消えます。

状態がDBにあるため、Hydraは複数台に並べて負荷分散できます。その代わり、期限切れのトークンやログイン・同意のリクエストがDBに溜まり続けます。`hydra janitor` がこれを一括削除するコマンドで、ヘルプに「This command is irreversible」とある通り元に戻せません。既定は `--limit 10000`・`--batch-size 100` です。本番DBでは件数上限を付けて定期実行し、実行前にバックアップを取ってください。

## Ory Network・OEL・セルフホストの選び方

Hydraの使い方は3通りあります。

| 形態                     | 中身                     | 費用                |
| ---------------------- | ---------------------- | ----------------- |
| セルフホスト（OSS）            | Apache-2.0のHydraを自社で運用 | ライセンス費なし          |
| Ory Network            | Oryが運用するマネージド版         | 無料プランあり・有料は年$770〜 |
| Ory Enterprise License | OSSに無い機能付きのセルフホスト版     | 個別見積もり            |

[Ory Networkの料金ページ](https://www.ory.com/pricing)（2026年10月23日取得）では、Developerが無料、Productionが年$770、Growthが年$9,350、Enterpriseが個別見積もりです。有料プランは従量部分があり、月間クレジット（Production $21／Growth $255）を超えた分として、client\_credentialsで発行するトークン（M2M Token）はProductionで1トークンあたり月$0.007、Growthで$0.006かかります。サービス間通信で大量にトークンを発行する設計なら、この単価で月額を見積もってからセルフホストと比べてください。

Ory Enterprise License（OEL）は、READMEによると、OSS版に無い追加機能、CVE修正を含む定期的なセキュリティリリースとSLA、プレミアムサポート、プライベートDockerレジストリが付くセルフホスト向けの契約です。OSSとして公開されるのは.0版だけで、途中のビルドはOEL契約者向けに配布されます。自社で運用しつつ、脆弱性修正の提供を契約で担保したい場合の選択肢です。

## Keycloakとの違いと、Hydraを選ぶべきでない場面

| 観点        | Ory Hydra     | Keycloak           |
| --------- | ------------- | ------------------ |
| ユーザー管理    | 持たない          | 内蔵                 |
| ログイン画面    | 自作（またはKratos） | 内蔵・テーマで変更          |
| LDAP／AD連携 | ログイン画面側で実装    | User Federationで設定 |
| 管理画面      | なし（CLI・API）   | 管理コンソールあり          |
| 実装言語      | Go            | Java               |

Hydraを選ぶ理由になるのは、既存の会員DBとログイン画面を動かさずにOAuth 2.0／OIDCを外付けしたい場合と、画面のUXを完全に自社で作りたい場合です。その代わり、この記事で見たログイン・同意・ログアウト・エラーの4画面と、skipやrejectの分岐は自社で実装し、保守し続けることになります。

次のどれかに当てはまるなら、Hydraは選ばないほうが早く終わります。

- 会員DBもログイン画面もまだ無く、パスワードリセットやMFAまで含めて一式が必要（Hydraだけでは何も揃わない。Kratosと組むか、Keycloakや[IDaaS](/tech/details/16401/)を使う）
- 運用担当が管理コンソールでクライアントやユーザーを操作したい（HydraはCLIとAPIのみ）
- LDAPやSAMLのIdPとの連携を設定だけで済ませたい

Keycloakの機能と導入判断は[Keycloakのメリット・デメリットと比較](/tech/details/7663/)で詳しく扱っています。既存の会員基盤にOAuth 2.0／OIDCを足す設計から相談したい場合は、[認証基盤・ID管理システム開発](/service/system/identity/)でお受けしています。

## よくある質問

### Ory Hydraは無料で使えますか？

はい。ソースコードはApache-2.0ライセンスで公開されており、セルフホストならライセンス費用はかかりません（サーバーとDBの運用費は別途かかります）。マネージド版のOry Networkは有料プランがあります。

### Ory Hydraだけでログイン画面まで作れますか？

作れません。Hydraはログイン・同意・ログアウトのリクエストをchallenge付きで外部の画面へ渡すだけです。画面は自作するか、Ory Kratosと組み合わせます。quickstartのサンプル画面は検証用です。

### Ory Hydraの最新バージョンはいくつですか？

2026年10月時点の最新はv26.2.0（2026-03-20公開）です。v2.3.0の次がv25.4.0で、ここから年と四半期を表すカレンダー方式（YY.Q.B）の版番号になりました。最新はGitHubのリリース一覧で確認してください。

### Ory HydraのAdmin APIに認証はかけられますか？

Hydra自体にはAdmin APIの認証機能がありません。4445番を社内ネットワークに閉じるか、APIゲートウェイで認証をかけるか、`SERVE_ADMIN_HOST` に `unix:` で始まるソケットの絶対パスを設定し、UNIXソケットのアクセス権で保護します。

### Ory HydraとKratosの違いは何ですか？

Hydraはトークンを発行するOAuth 2.0／OIDCサーバー、Kratosはユーザー登録・ログイン・MFAを担う認証サーバーです。Kratosでログインした結果をHydraのログイン受理に渡す、という組み合わせで使います。Kratosの設定 `oauth2_provider.url` にHydraを指定すると、Kratosのログイン画面が login\_challenge を直接処理します。

## 関連記事

- [OAuth 2.0とは？仕組み・認可フローと認証との違い、OAuth 2.1の変更点をわかりやすく解説](/tech/details/8369/)
- [OIDC（OpenID Connect）とは？IDトークンの検証手順とOAuth 2.0との違いを解説](/tech/details/6532/)
- [認可コードフローとは？認可リクエストからトークン交換までの実装手順と検証設計を解説](/tech/details/16415/)
- [シングルサインオン（SSO）とは？4つの実現方式とIDトークン検証・IdP選定を実装手順で解説](/tech/details/15821/)
- [Keycloakとは？Oktaとの違いと連携手順｜Auth0・Cognito比較で導入を判断【2026年10月】](/tech/details/7663/)

---

出典: [Ory Hydraとは？仕組みとv26.2.0の構築手順、ログイン・同意・ログアウトの実装](<https://www.issoh.co.jp/tech/details/10390/>)（株式会社一創）
