- Auth0 とは
— Auth0
— 機能 - OAuth2.0 や Open ID Connect とは
— それぞれをざっくりと…
— OAuth 2.0 というか, OAuth について
— Open ID Connect
— JWT - Ruby Sample を動かす
— まだまだ
— Quick Start
— Ruby Sample (1) ~ このサンプルは ~
— Ruby Sample (2) ~ Auth0 での API 作成 ~
— Ruby Sample (3) ~ .env ファイルの編集 ~
— Ruby Sample (4) ~ docker run ~
— Ruby Sample (5) ~ アクセストークンの取得 ~
— Ruby Sample (6) ~ アクセストークンを利用して private エンドポイントにアクセス ~ - ということで
- 参考
Auth0 とは
Auth0
- Auth0 とは認証, 認可機能を SaaS (IDaaS) で提供している会社 (サービス)で, Node.js ベースの FaaS にて運用されている
- アプリケーションに SaaS で認証基盤を提供し, SDK を利用して新規登録やログイン等の API を呼び出すことが出来る
ざっくり言うと, Auth0 は FaaS で認証, 認可を SaaS で提供するサービスである.
機能
Auth0 は以下のような機能を提供している.
- OAuth 2.0/OpenID Connect, SAML や Active Directory/LDAP に対応
- Identity 管理やソーシャルログイン等の機能を提供
- RESTful API (Authentication, Management API) が提供されており, SDK やサンプルが GitHub にて公開されている
- 既存のアプリケーションに簡単に統合出来る
等など. 当然, FaaS にて運用されている為, 高いスケーラビリティと共に信頼性も高いと思われる.
OAuth2.0 や Open ID Connect とは
それぞれをざっくりと…
Auth0 をイジる前に, OAuth2.0 や Open ID Connect についてざっくりと
OAuth 2.0 というか, OAuth について
OAuth は以下のような特徴を持つ認可情報委譲の為の仕様 (第1回 OAuthとは?―OAuthの概念とOAuthでできること:ゼロから学ぶOAuth|gihyo.jp … 技術評論社 より引用.) である.
- あらかじめ信頼関係を構築したサービス間で
- ユーザの同意のもとに
- セキュアにユーザの権限を受け渡しする
登場人物は以下の通り.
- OAuth Service Providers (ユーザーの認可情報を Consumers に渡すサービス)
- OAuth Consumers (ユーザーに代わって, Service Provider から認可情報を受け取って, 情報にアクセスするサービス)
- Users (Service Provider が Consumer に認可情報を渡すことを許可したり, 無効にしたりする)
これ以上, 詳しく書こうとすると, 1000 本くらい記事が書けそうので, OAuth とは…
- Instagram で共有した写真を Facebook や Twitter にも共有
- Facebook ID で他のサイトにログイン
のような機能を提供する為, 裏側で暗躍している認可委譲機能の仕様という理解で進めたいと思う…すいません.
Open ID Connect
- OAuth 2.0 を拡張したプロトコル
- 認証の技術である Open ID と認可の技術である OAuth 2.0 に属性取得機能をガッチャンコしたもの
登場人物 (用語) は以下の通り. (第一回 認証基盤のこれからを支えるOpenID Connect | オブジェクトの広場 より引用.)
用語 | 説明 |
---|---|
OpenID Provider (OP) | ユーザー認証とユーザー認証時に Relying Party から要求されたアイデンティティ情報を供給することができるサーバー |
Relying Party (RP) | OP に ID Token とアイデンティティ情報を要求するサーバーで SSO 対象のアプリケーションを指す |
ID Token | 認証と認可の情報を含む JWT (JSON Web Token) 形式のトークン |
Access Token | UserInfo エンドポイントにアクセスするためのトークン |
UserInfo | Access Token を提示するクライアントに対して, アイデンティティ情報を提供する |
JWT
OpenID Connect は OAuth 2.0 のフローにアイデンティティ情報のやり取りを行うレイヤーを追加したものであり, このやり取りは OpenID Provider と Relying Party で行われるが, ここでは JWT (JSON Web Token) という ID Token を用いてやり取りする.
この JWT (ID Token) は以下のような仕様 (RFC 7519 – JSON Web Token (JWT)) で定義されている. (第一回 認証基盤のこれからを支えるOpenID Connect | オブジェクトの広場 より引用.)
項目 | 値の例 | 説明 |
---|---|---|
iss | http://op.example.domain/URI | レスポンスの発行者の識別子(URL) |
sub | sampleuser | ログインユーザー名 |
aud | client123456 | ID Token の要求元(Relying Party)であるウェブアプリケーションやネイティブアプリケーションの識別子 |
exp | 1436784324 | トークンが無効になる時刻 (UTC で計測される 1970-01-01T0:0:0Z から秒数) |
iat | 1436784264 | トークン作成時刻 (UTC で計測される 1970-01-01T0:0:0Z から秒数) |
nonce | 18b88a6ab3…d58a0 | 認可エンドポイントの1回だけ使われるパラメータ |
JWT は, URL Safe(URLに含めることの出来ない文字列を含まない)で, デジタル署名で保護されたコンテンツを表現することが可能な JSON 型のトークンとなります.
Ruby Sample を動かす
まだまだ
OAuth 2.0 や OpenID Connect については勉強不足だけど, ひとまず, Auth0 の Ruby Sample を動かしてみる.
Quick Start
各言語のサンプルは Github で公開されていて, 簡単に試すことが出来る
auth0.com
今回は Ruby Sample を試してみたいと思う.
github.com
Ruby Sample (1) ~ このサンプルは ~
This sample demonstrates how to protect endpoints in an Ruby API by verifying an incoming JWT access token signed by Auth0. The token must be signed with the RS256 algorithm and must be verified against your Auth0 JSON Web Key Set.
README より引用. このサンプルは…ざっくり意訳すると, 以下のような感じ.
- Auth0 によって署名された JWT アクセストークンを検証することによって, Ruby API のエンドポイントを保護している
- トークンは RS256 アルゴリズムで署名する必要があり, Auth0 JSON Web Key Set に対して検証する必要がある
引続き, 以下のドキュメントを元に進めていく予定.
auth0.com
auth0.com
Ruby Sample (2) ~ Auth0 での API 作成 ~
上図のように, Name と Identifier (audience) 及び, Signing Algorithm を RS256
を指定して API を作成しておく.
Ruby Sample (3) ~ .env ファイルの編集 ~
以下のようにサンプルコードを clone してくる.
git clone https://github.com/auth0-community/auth0-ruby-api-samples.git cd auth0-ruby-api-samples/01-Authorization-RS256/
サンプルコードの中から .env ファイルを以下のように作成する.
AUTH0_DOMAIN=xxxx.auth0.com AUTH0_API_AUDIENCE=https://ruby.sample.com
AUTH0_DOMAIN
は Auth0 のアカウントを作成した際のアカウント名 (xxxx) + auth0.com
を指定し, AUTH0_API_AUDIENCE
には, 前のステップで Auth0 API を作成した際に指定した Identifier を指定する.
Ruby Sample (4) ~ docker run ~
Dockerfile とアプリケーションコードの一部を以下のように, ちょっとだけ弄ってみた.
$ git diff Dockerfile diff --git a/01-Authorization-RS256/Dockerfile b/01-Authorization-RS256/Dockerfile index 6580218..e987ed0 100644 --- a/01-Authorization-RS256/Dockerfile +++ b/01-Authorization-RS256/Dockerfile @@ -7,7 +7,3 @@ WORKDIR /myapp ADD Gemfile /myapp/Gemfile ADD Gemfile.lock /myapp/Gemfile.lock RUN gem install bundler && bundle install --jobs 20 --retry 5 -ADD . /myapp - -CMD ["ruby", "/myapp/lib/server_rs256.rb"] -EXPOSE 3010 $ git diff lib/server_rs256.rb diff --git a/01-Authorization-RS256/lib/server_rs256.rb b/01-Authorization-RS256/lib/server_rs256.rb index 6c96000..40a2e12 100644 --- a/01-Authorization-RS256/lib/server_rs256.rb +++ b/01-Authorization-RS256/lib/server_rs256.rb @@ -5,6 +5,7 @@ require 'sinatra/json' require 'jwt' require_relative 'jwt/json_web_token' require 'dotenv' +require 'sinatra/reloader' Dotenv.load
コードを弄りながら挙動を確認したかったので, Dockerfile から CMD や EXPOSE を外しておいて, sinatra/reloader
を require した上で,以下のように docker run してコンテナを起動する.
$ docker build -t auth0-ruby-sample . $ docker run --name=auth0-ruby-sample \ --env-file .env \ -v $(pwd):/myapp \ -p 3010:3010 -i -t -d \ auth0-ruby-sample \ ruby /myapp/lib/server_rs256.rb
起動後, 試しに以下のようにアクセスしてみる.
$ curl --request GET --url http://localhost:3010/api/public -w '\n' -i HTTP/1.1 200 OK Content-Type: application/json Content-Length: 91 X-Content-Type-Options: nosniff Server: WEBrick/1.3.1 (Ruby/2.3.3/2016-11-21) Date: Sun, 25 Mar 2018 14:32:44 GMT Connection: Keep-Alive {"message":"Hello from a public endpoint! You don't need to be authenticated to see this."} $ curl --request GET --url http://localhost:3010/api/private -w '\n' -i HTTP/1.1 401 Unauthorized Content-Type: application/json Content-Length: 59 X-Content-Type-Options: nosniff Server: WEBrick/1.3.1 (Ruby/2.3.3/2016-11-21) Date: Sun, 25 Mar 2018 14:33:11 GMT Connection: Keep-Alive {"error":"JWT::DecodeError","message":"Nil JSON web token"}
上記のように private エンドポイントへのアクセスには JWT が必要となる.
Ruby Sample (5) ~ アクセストークンの取得 ~
以下のように curl を利用してアクセストークンを取得する.
curl --request POST \ --url 'https://xxxx.auth0.com/oauth/token' \ --header 'content-type: application/json' \ --data '{"grant_type":"client_credentials","client_id": "xxxxxxxxxxxx","client_secret": "YOUR_CLIENT_SECRET","audience": "https://ruby.sample.com"}'
実行すると, 以下のようなレスポンスが返ってくる.
{ "access_token": "xxxxxxxxxxxx.yyyyyyyyyyyyyyyyy.zzzzzzzzzzzzzzz", "expires_in": 86400, "token_type": "Bearer" }
access_token はだいぶん端折っているが, .
で区切られた 3 つのパートで構成されている点に注目する. この access_token を利用して, 再度, アプリケーションにアクセスしてみる.
Ruby Sample (6) ~ アクセストークンを利用して private エンドポイントにアクセス ~
以下のように Authorization ヘッダに Bearer と 先に取得したアクセストークンを付与して private エンドポイントにアクセスする.
$ curl --request GET --url http://localhost:3010/api/private --header 'Authorization: Bearer xxxxxxxxxxxx.yyyyyyyyyyyyyyyyy.zzzzzzzzzzzzzzz' -w '\n' -i HTTP/1.1 200 OK Content-Type: application/json Content-Length: 86 X-Content-Type-Options: nosniff Server: WEBrick/1.3.1 (Ruby/2.3.3/2016-11-21) Date: Sun, 25 Mar 2018 14:52:01 GMT Connection: Keep-Alive {"message":"Hello from a private endpoint! You need to be authenticated to see this."}
正常にレスポンスが返ってきた!
ちなみに, アクセストークンには期限は設けられており, 期限切れのトークンを利用した場合には, 以下のような認証エラーレスポンスとなる.
$ curl --request GET --url http://localhost:3010/api/private --header 'Authorization: Bearer aaaaaaaaaaaaa.bbbbbbbbbbbbbbbb.ccccccccccccccc' -w '\n' -i HTTP/1.1 401 Unauthorized Content-Type: application/json Content-Length: 67 X-Content-Type-Options: nosniff Server: WEBrick/1.3.1 (Ruby/2.3.3/2016-11-21) Date: Sun, 25 Mar 2018 14:55:15 GMT Connection: Keep-Alive {"error":"JWT::ExpiredSignature","message":"Signature has expired"}
トークンが改ざんされた場合にも, 以下のような認証エラーレスポンスが返ってくる.
$ curl --request GET --url http://localhost:3010/api/private --header 'Authorization: Bearer xxxxxxxxxxxx.yyyyyyyyyyyyyyyyy.zzzzzzzzzzzzzzq' -w '\n' -i HTTP/1.1 401 Unauthorized Content-Type: application/json Content-Length: 76 X-Content-Type-Options: nosniff Server: WEBrick/1.3.1 (Ruby/2.3.3/2016-11-21) Date: Sun, 25 Mar 2018 14:57:17 GMT Connection: Keep-Alive {"error":"JWT::VerificationError","message":"Signature verification raised"}
フムフム.
ということで
今回は, Auth0 から OAuth 2.0 や Open ID Connect とはなんぞやをホントにかる~く触れた上で, Auth0 API の Ruby サンプルを動かしてみた.
このサンプルの実行結果と Auth0 の機能や, OAuth や Open ID Connect がどのように関連しているのか, まったく伝わってこないかもしれないが, ひとまず, こんな認証, 認可基盤が SaaS として提供されていて, 簡単にアプリケーションに組み込むことが出来るという雰囲気が味わえたの良しとしたい. (気付いたら, 色々と追記していくつもり)
引続き, この分野についても勉強していきたいと考えている.
参考
以下の記事を参考, 引用させて頂きました.
- Why Auth0 – Auth0
- Auth in a Serverless world
- Auth0でAWSの認証認可を強化
- Auth0 Ruby API SDK Quickstarts: Authorization
- 認証基盤サービス「Auth0」を使ってみる | Developers.IO
- 認証プラットフォーム Auth0 とは? – Qiita
- OpenID Connect 入門 〜コンシューマーにおけるID連携のトレンド〜
- 第一回 認証基盤のこれからを支えるOpenID Connect | オブジェクトの広場
- RFC 7519 – JSON Web Token (JWT)
- JSON Web Token (JWT)
有難うございました.
元記事はこちら
「Auth0 QuickStarts の Ruby API Authorization で学ぶ認証基盤の入り口の入り口」