目次


Hydra のブートストラップ方法を学ぶ

クラウド・ネイティブの OAuth 2.0 および OpenID Connect サーバーを使用して、ユーザーに代わって許可されたリクエストを行う

Comments

OAuth 2.0 と OpenID

OAuth 2.0 と OpenID の基本概念は、ユーザーがアプリケーション (「アプリケーション X」) を使用して何らかの操作を実行する際に、アプリケーションにアクセスするための要件として、企業またはビジネス (「サービス Z」) のアカウントにアクセスして、ユーザーに代わってそのアカウントで許可を要求するというものです。有効かつセキュアな方法で許可を付与できるようにするには (つまり、ユーザーからの信頼を損なうことなく、ユーザーの資格情報を直接要求すること)、Hydra のようなツールをサービス Z に統合できます。これにより、アプリケーション X がユーザーに代わり、許可されたリクエストを実行できるようになります。

Hydra の紹介

OAuth 2.0 サーバーを実行する場合の使用ケースを理解していなければ、そもそも Hydra のようなツールがなぜ必要となるのかを簡単に理解することはできません。端的に言えば、Hydra は非常に軽量かつ簡素な OAuth 2.0 許可サーバーです。このタイプの認証サービスを使用する好例 (あるいは、使用しなければならない最も明らかな理由) は、API を作成し、その API に (例えばユーザーに代わって) サード・パーティーがアクセスするための手段を用意するケースです。

基本概念を理解するには、以下の図が大いに参考になります。この図には、許可コードのフローの概要が示されています。

図 1: Hydora のプロセス・フロー
Hydora のプロセス・フローを示す図
Hydora のプロセス・フローを示す図

Hydra をインストールする

Hydra を実行およびインストールする基本的な方法は 3 つあります。個人的には、Docker イメージまたはコンテナーに含まれる Hydra を使用し、そこから Hydra を実行することをお勧めします (この記事では、この方法を使用してサーバーを実行します)。後世のために説明しておくと、Hydra を実行するには、公式リリースに含まれるバイナリーをダウンロードするという方法、またはソースから Hydra をビルドするという方法もあります。この記事ではホスト・マシン上で Hyrda を実行してサーバーに接続するので、ローカル側にも Hydra をインストールしてください。ただし、Hydra サーバーに接続された Docker コンテナーからすべてのコマンドを実行するほうが快適に作業できると思う場合は、ローカル側に Hyda をインストールする必要はありません。バイナリーからインストールするのは比較的簡単で、プロジェクトのリリース・ページから該当するリリースをダウンロードして、PATH の通った任意の場所にインストールするだけで作業は完了します。あるいは、バイナリーを実行可能ファイルにすれば、直接そのファイルを呼び出すこともできます。

macOS 上では、次のコマンドを実行するだけで、PATH を実行可能にすることができます。

chmod +x hydra-darwin-amd64
./hydra-darwin-amd64 -h

ソースからビルドする場合は、golang 1.8 以降がセットアップされて適切に構成されている必要があります (PATH を構成して、go get が機能するようになったことを確認してください)。以下のリンク先の Hydra gitbooks のページに、わかりやすい説明が記載されています。https://ory.gitbooks.io/hydra/content/install.html#build-from-source

Docker を使用して Hydra をセットアップする

Hydra サーバーのセットアップ手順は特定のアプリケーションに依存しないため、ほとんどの手順は公式ガイドに記載されているとおりです。この記事では、Docker を使用して Hydra をセットアップします。それは、Hydra には既存の Docker イメージがあるためだけでなく、Docker を使用すればサーバーを簡単に実行できることから、詳細に気を取られずにプロセスの仕組みを理解できるためです。

Hydra サーバーを起動する前に、データベースを稼働中の状態にしておきます。データベースとして最適な選択肢は、Postgres または MySQL のいずれかです。データベースを起動するには、組み込み migrate コマンドを使用してスキーマを移行し、作成する必要があります。この作業が完了したら、サーバーを実行できます。Hyrda の使用方法をデモンストレーションするためにインメモリー・データベースをそのまま使用するので、今のところ、データベースについて懸念する必要はありません。このデモンストレーションは説明のみを目的としていて、本番環境での使用ケースを対象としたものではないことに注意してください。また、この記事全体を通してさまざまなフラグ (--dangerous-force-http など) を使用しますが、これらのフラグもテストおよび説明を目的としたものです。

Hydra を稼働させるには、以下のコマンドを実行する必要があります。

docker run -d \
 --name hydra-server \
 -p 9000:4444 \
 -e SYSTEM_SECRET=$SYSTEM_SECRET \
 -e DATABASE_URL=$DATABASE_URL \
 -e ISSUER=https://localhost:9000/ \
 -e CONSENT_URL=http://localhost:3000/consent \
 -e FORCE_ROOT_CLIENT_CREDENTIALS=admin:admin-password \
 oryd/hydra:latest --dangerous-force-http --dangerous-auto-logon --disable-telemetry

SSL の使用に関する注意事項

この記事のセットアップでは何のセキュリティー対策も講じていません (これがセキュリティー・アプリケーションであることを考えると、皮肉な話です)。けれども、この記事の目的は最も基本的な承認フロー・プロセスの仕組みを理解することであるため、セキュリティー対策は使用しません。また、この記事で使用するフラグとオプションの多くは、テストや学習以外の目的で使用されることはありません。例えば、(他の多数の機能に加え) Hydra サーバーに SSL を使用しないことは推奨されません。このアプリケーションを本番環境で実行できるようにするためのあらゆる措置については、公式のドキュメントを参照してください。SSL を使用するには (推奨)、Hydra サーバーを起動する際にキーと証明書が必要です。それには最も簡単な方法として、ホスト・マシン上で Openssl を使用できます。その手順の一例は、このリンク先の heroku のドキュメントで説明されています。

以降の手順では、サンプル・クライアントをセットアップできるよう、Hydra サーバーにアクセスする必要があります。この作業はすでに実行中の Docker コンテナーから行うのではないため、サンプル・クライアントをセットアップするには、いくつもの方法があります。その 1 つは、Hydra サーバーを実行してそのサーバーに接続するのではなく、Hydra が含まれる別の Docker コンテナーを起動してコンテナー・シェルに接続するという方法です。この方法は非常に優れていますが、他にどのような方法で実現できるのかを説明するために、以降の手順ではホスト・マシン上で稼働している Hydra を Docker コンテナーに接続します。

Hydra をローカル側で使用する

リリース・ページから Hydra のバイナリーをダウンロードして、そのバイナリーを $PATH に追加します。その後は以下のコマンドを使用することで、ホスト・マシン上で稼働中の Docker 化された Hydra コンテナーに接続できます。

hydra connect --url https://localhost:9000 --id admin --secret admin-password

Hydra が機能していることを確認するには、トークンを作成して検証します。

hydra token validate --skip-tls-verify $(hydra token client --skip-tls-verify)

次に、Hydra クライアントとポリシーをセットアップします。

hydra clients create --skip-tls-verify \
  --id consent-app \
  --secret consent-secret \
  --name "Consent App Client" \
  --grant-types client_credentials \
  --response-types token \
  --allowed-scopes hydra.consent

hydra policies create --skip-tls-verify \
  --actions get,accept,reject \
  --description "Allow consent-app to manage OAuth2 consent requests." \
  --allow \
  --id consent-app-policy \
  --resources "rn:hydra:oauth2:consent:requests:<.*>" \
  --subjects consent-app

注: 現時点では、これらのリクエストはすべて、理論上は任意の場所 (cURL など) で実行できます。また、Python や任意の OAuth2 ライブラリーを使用して、プロセスを自動化および簡素化することもできます。

Hydra をアプリケーションに統合する

Hyrda を使用する要点は、アプリケーションで Hyrda を使用することにあります。幸い、公式リポジトリーから 2 つの有効なサンプルを入手できるようになっているため、そのうちの 1 つ (Node.js のサンプル) を使用します。Go アプリケーションは簡単に理解できる内容になっていますが (このリンク先のリポジトリーを参照)、ここでは Node.js のサンプルを使用します。この Express アプリケーションの基本的な仕組みは、Hydra サーバー上で simple-oauth2 ライブラリーを使用して、/oauth2/auth ルートからのアクセス・トークンをリクエストするというものです。アクセス・トークンを取得した後は、Hydra SDK を使用してクライアントのインスタンスを作成し、そのインスタンスを使用してユーザーに代わって承認をリクエストできます。公開済みの Docker イメージを使用できるため、このプロセスを開始してテストするのは至って簡単です。すべてが正常に機能していることを確認するとともに、エンド・ユーザーの承認を必要とする API を作成して、その API へのアクセスを許可する必要がある場合にサード・パーティーの観点から Hydra を統合する方法を理解するには、以下のようにしてイメージを実行できます。

docker run -d --name hydra-consent --link hydra-server:hydra -p 9020:3000 \
 -e HYDRA_CLIENT_ID=consent-app \
 -e HYDRA_CLIENT_SECRET=consent-secret \
 -e HYDRA_URL=https://hydra:4444 \
 -e NODE_TLS_REJECT_UNAUTHORIZED=0 \
 oryd/hydra-consent-app-express:latest

アクセス・トークンを取得する

承認アプリケーション (Node.js アプリケーション・コンテナー) が稼働中になったら、OAuth コンシューマー・アプリケーション・クライアントを作成する必要があります。理論上、これらのアプリケーションは両方とも、HTTP API (または、OAuth2 承認フロー全体を実行する任意のライブラリー) に対して使用するものですが、今のところは、Hydra サーバーに接続された Hydra バイナリーから以下のコマンドを実行できます。クライアントを作成してから OAuth 2.0 コード・フローを開始するには、以下を実行します。

hydra clients create --skip-tls-verify \
 --id some-consumer \
 --secret consumer-secret \
 -g authorization_code,refresh_token,client_credentials \
 -r token,code,id_token \
 --allowed-scopes openid,offline,hydra.clients \
 --callbacks http://localhost:9010/callback

hydra token user --skip-tls-verify \
 --auth-url https://localhost:9000/oauth2/auth \
 --token-url https://hydra:4444/oauth2/token \
 --id some-consumer \
 --secret consumer-secret \
 --scopes openid,offline,hydra.clients \
 --redirect http://localhost:9010/callback

このコマンドにより、ブラウザーから https://localhost:9000/oauth2/auth?client_id=some-consumer&redirect_uri=http+various_other_data のような URL が返されて、ログインできるようになります。入力する資格情報は Web ページ上に表示されて、すべてのボックスにチェック・マークを付けられるようになっています。ただし厳密には、これらのボックスにはユーザーがこのプロセスを進める際にチェック・マークを入れます。ユーザーが目にすることになるのは、おそらく、プロセスのこの部分だけです。プロセスの残りの部分は、認証サーバーまたはクライアント・アプリケーションのバックエンド上で開始されるためです。返されるアクセス・トークン (およびスコープ内でオフラインを指定したことから、リフレッシュ・トークン) を、有効期限が切れると同時に非表示にすることもできます。アクセス・トークンとリフレッシュ・トークンは、取り消したり検査したりすることもできます (このリンク先の Hydra ドキュメントを参照)。このプロセスを統合するアプリケーションでは、前のトークンを検査して、必要に応じて更新することが賢明でしょう。幸い、Hydra を使用して簡単にトークンを検査、更新することができます。

アクセス・トークンを使用する

認証トークンを実際に使用しましょう。トークン自体に API へのアクセス権があるとしても、トークンはデフォルトで有効にされないため、ユーザーに対するポリシーも作成する必要があります。前に Hydra バイナリーを使用して生成したアクセス・トークンを使用して、以下のコマンドを実行してください。

hydra policies create --skip-tls-verify \
 --actions get \
 --allow \
 --id consent-app-policy \
 --resources "rn:hydra:clients" \
 --subjects user:12345:dandean

ここからは、cURL または Python を使用して、例えば作成されたすべてのクライアントを表示するなどの操作を実行できます。

curl --insecure -H "Authorization: bearer `ACCESS_TOKEN_FROM_ABOVE`"
                https://localhost:9000/clients/

以上が、OAuth 2.0 サーバーのセットアップ方法、承認フローが別の Web アプリケーションの一部として機能する仕組み、そしてユーザーが承認フローとやり取りする方法の背後にあるプロセスの要約です。

その他: Python での使用

Hydra のようなものを Python で使用することも可能です。どちらの公式 SDK も swagger-codege を使用して作成されているため、以下のコマンドを実行するだけで、Python で Hydra を使用できるようになります。

brew install swagger-codegen
swagger-codegen generate -i ./docs/api.swagger.json -l python -o ./sdk/python/swagger

あるいは、python-hydra-sdk のような別の SDK を使用することもできます。この記事のために、このリンク先のページにこの Python SDK をプッシュしておきました。

一貫して Python で処理するとしたら、初期アクセス・トークン (以下を参照) を取得する手段が必要です。

上述のように、OAuth 2.0 クライアントを直接 SDK に統合することはできますが (また、python-flask codegen によって作成される構成ファイル内の URL を変更すれば、python-flask codegen はそのままの形で機能するようです)、requests_oauthlib ライブラリーを使用して初期認証トークンを取得する方法を説明しておきます。

これをセットアップするには、pip install requests_oauthlib を使用してインストールします。

最初のステップは、Hydra サービスを使用するユーザーを対象としたポリシーとクライアントを作成するために使用できるアクセス・トークンを作成することです。

from oauthlib.oauth2 import BackendApplicationClient
from requests.auth import HTTPBasicAuth

auth = HTTPBasicAuth('admin', 'admin-password') # from FORCE_ROOT_CLIENT_CREDENTIALS above
client = BackendApplicationClient(client_id=client_id)
oauth = OAuth2Session(client=client)

token = oauth.fetch_token(token_url='https://localhost:9000/oauth2/token', auth=auth, verify=False)
print(token)

以下のようなレスポンスが返されます。

{'access_token': '-tdmTUbaEXZLussxTD7NDUzakQ.VrpS4hOml1-
bw_5pkUlikqEs3jjvKOrPcE2hg4yNBBk', 'expires_in': 3599, 'scope': [''],
'token_type': 'bearer', 'expires_at': 1512371155.7248588}

このアクセス・トークンを使用して、クライアントやポリシーなどを作成する実際のタスクを実行できます。

まとめ

これで皆さんは、作成するあらゆる API にサード・パーティーがセキュアにアクセスできるよう、API で Hydra を使用できるようになったはずです。Hydra を使用すれば、セキュリティーの詳細を懸念することなく、安全かつセキュアにユーザーの ID を確認する方法を作り出すことができます。例えば、データベースにユーザーのパスワードを保管して、そこからユーザーがサインアップするようにした場合、データベースから情報が洩れたとすると、重大な法的責任が問われることになります。そうではなく、OAuth2 承認フローをアプリケーションや Web サイトに実装すれば、ユーザーの個人データを保管するという点に関して懸念する必要性が大幅に減ります。その上、ユーザーにとってもサインアップが遥かに簡単になります。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=セキュリティ
ArticleID=1060672
ArticleTitle=Hydra のブートストラップ方法を学ぶ
publish-date=07052018