わかった気になる!OpenID Connect

Dc5157c1e1b11923f4cdd210ee27d4af?s=47 patorash
February 29, 2020

わかった気になる!OpenID Connect

OAuth2.0の挙動がどうなっているのかを掘り下げ、OpenID ConnectとOAuth2.0の仕様と挙動を比較しながら、OpenID Connectのことをざっくりとわかってもらうことをゴールとしています。
また、RailsでOAuth2.0を使う方法やOpenID Connectを使うための方法のヒントを書いています。デモでコードは見せましたが、資料にはコードは載せていません。

2020-03-03: 間違いの指摘を受けたので、内容を修正しました。
2020-03-04: UserInfoエンドポイントに関する箇所を修正しました。

Dc5157c1e1b11923f4cdd210ee27d4af?s=128

patorash

February 29, 2020
Tweet

Transcript

  1. わかった 気になる ! OpenID Connect 2020-02-29 第22回 岡山Ruby, Ruby on

    Rails勉強会 株式会社リゾーム 尾古 豊明
  2. 修正履歴 • 2020-03-03: ◦ OAuth認証の正体の箇所を、プロフィール APIから取得したユーザ識別子を認証機能として使った もの、に変更 ◦ IDトークンから安全にユーザ識別子が取得できた時点で認証完了と変更 以前はUserInfoエンドポイントとIDトークンのペイロードの内容を比較して認証完了としていたが、

    勘違いしていた ◦ UserInfoエンドポイントを必須のフローではなく、必須の APIに変更 リライング・パーティでプロフィールを使うときに利用するものだった。 以前は認証するために必要なフローの一部だと勘違いしていた。 ◦ OAuth2.0の流れから要点を押さえる、の箇所で twitterを題材にしていたが、 twitterはOAuth1.0とい う指摘を頂いたので GitHubに変更 • 2020-03-04 ◦ UserInfoエンドポイントのsubとIDトークンのsubを比較するすることでアクセス・トークンのすり替え に気付ける、という記述を削除。 OIDCだと別の確認手段があるため。 ◦ UserInfoエンドポイントの説明に、フォーマットが標準化されていることがメリットであることを記述し た。
  3. 目次 1. 自己紹介 2. この発表のゴールについて 3. シングルサインオン 4. OAuthは認証なのか?OAuth2.0の流れから要点を押さえる 5.

    OAuth2.0とOpenID Connectの関係 6. OpenID Connectをわかった気になる 7. OAuth2.0とOpenID Connectの付与方式 8. Implict Grantの危険性について 9. RailsでOAuthするには? 10. RailsでOpenID Connectするには? 11. まとめ
  4. 自己紹介 名前:尾古 豊明(おこ とよあき) twitter: @patorash 所属:株式会社リゾーム システム開発部 役職:専門職 仕事内容:

    ショッピングセンターに関連するサービス開発 Ruby on Railsで自社サービスの開発・運用(7年目) ここ最近はMacのRubyがセグメンテーション違反を吐き始め、 開発に支障が出まくっているので開発環境のAll Docker化に取り組んでいる 4
  5. この発表のゴールについて • この発表のゴール ◦ OAuth2.0がどういうものかをわかってもらう ◦ OpenID Connectがどういうものかをわかってもらう ◦ RailsでOpenID

    Connectする方法をざっくりわかってもらう • この発表でしないこと ◦ OAuth2.0やOpenID Connectの細かいところは説明しない ◦ OAuth2.0の危険なところ等についても(詳しくは)説明しない
  6. シングルサインオン(SSO)とは? 1つのIDとパスワードを入力して、複数のWebサービスやアプリケーションにログインする仕組み。
 入力や管理の手間を省き、セキュリティを強化することができる。
 例えば、メール、SNS、Google、Amazon、グループウェアなどのサービスごとに別々のIDとパスワードを設定すると、アクセスするた びにパスワードを入力する労力がかかる上、パスワードを忘れると再設定する手間もかかる。また、簡単なパスワードを設定して使 い回したり、メモなどで残したりすると、流出や漏えいのリスクが高くなる。
 シングルサインオンは1つのIDとパスワードでサービスが利用できるので、パスワードを管理する負担から解放され、利便性が向上 し、セキュリティリスクが減る。また、企業のシステム管理者の労力も省かれ、生産性が向上する。
 シングルサインオンを実現する認証方式は、大きく分けて4つある。Windows Server

    Active Directoryの認証に使われる「ケルベロス 認証方式」、WebブラウザーやWebアプリケーションのサーバーの間にリバースプロキシサーバーを設置する「リバースプロキシ方 式」、Webアプリケーションのサーバーにエージェントソフトを組み込む「エージェント方式」、パスワードの代わりに「チケット」と呼ばれ る情報を受け渡しする「フェデレーション方式」がある。
 
 シングルサインオン( SSO) | IT用語辞典 より https://www.otsuka-shokai.co.jp/words/single-sign-on.html
  7. シングルサインオンのイメージ ・ ・ ・ GitHubにログインしていれば、様々なサービスを利用できる。 メリットは、個々のサービス毎にID、パスワードを管理しなくてもよいこと。

  8. OAuthは認証なのか? OAuth2.0の流れから要点を押さえる (Authorization Code Grant)

  9. OAuth2.0とOpenID Connectの違い OAuth2.0 OpenID Connect やること 発行するもの プロフィール参照API スコープ

  10. None
  11. これが スコープ!

  12. OAuth2.0とOpenID Connectの違い OAuth2.0 OpenID Connect やること 発行するもの プロフィール参照API スコープ アプリケーション毎に任意

  13. None
  14. OAuth2.0とOpenID Connectの違い OAuth2.0 OpenID Connect やること 認可(委譲) 発行するもの プロフィール参照API スコープ

    アプリケーション毎に任意 ※認可(委譲)する対象はスコープに提示されている権限
  15. None
  16. OAuth2.0とOpenID Connectの違い OAuth2.0 OpenID Connect やること 認可 発行するもの プロフィール参照API アプリケーション毎に任意

    (GitHubでは存在する) スコープ アプリケーション毎に任意
  17. 認証に成功

  18. OAuth2.0とOpenID Connectの違い OAuth2.0 OpenID Connect やること 認可 発行するもの アクセス・トークン プロフィール参照API

    アプリケーション毎に任意 (GitHubでは存在する) スコープ アプリケーション毎に任意
  19. 初回でプロフィール情 報を取得 クライアントで プロフィールAPIから 識別子を取得し、 認証に利用

  20. OAuth認証の正体 • OAuth2.0の認可プロセスでは、アクセストークンの取得までで、 プロフィールなど一切取得していない。 • 認可後に、アクセストークンを使って、プロフィールAPIから取得した 識別子(ユーザID等)を認証機能に使っているだけ! • 認可サーバにもプロフィール用のAPIを作らなければならない という仕様はない

    ◦ 認可サーバの実装次第 ◦ クライアントの実装次第
  21. シングルサインオンのイメージ GitHubにログインしていれば、様々なサービスを利用できる。 メリットは、個々のサービス毎にID、パスワードを管理しなくてもよいこと。 デメリットは、悪意あるクライアントに過剰な権限を認可すると危険なこと。

  22. OAuth2.0とOpenID Connectの違い OAuth2.0 OpenID Connect やること 認可 発行するもの アクセス・トークン プロフィール参照API

    アプリケーション毎に任意 (GitHubでは存在する) スコープ アプリケーション毎に任意
  23. OAuth2.0とOpenID Connectの関係

  24. OpenID Connectとは? • OAuth2.0を拡張した認証プロトコル • 認証+認可 • アクセストークンとは別に、認証用にIDトークンを発行する • UserInfoエンドポイントを定義することが仕様に含まれる

    • プロフィール系のスコープを定義することが仕様に含まれる
  25. OAuth2.0とOpenID Connectの違い OAuth2.0 OpenID Connect やること 認可 認可+認証 発行するもの アクセス・トークン

    アクセス・トークン+IDトークン プロフィール参照API アプリケーション毎に任意 (GitHubでは存在する) UserInfoエンドポイントが必須 スコープ アプリケーション毎に任意 プロフィール系のスコープ定義が 必須。リソースはアプリケーション毎に 任意。 認証を目的としたIDトークンにユーザ識別子(ユーザ ID等)を設定する。 安全にユーザ識別子を取得できた時点で認証と言える。 (「安全に」については後述)
  26. ここ以外、OAuth2.0と ほぼ同じ!! 仕様上、必須のAPI

  27. OpenID Connectをわかった気になる

  28. OAuth2.0との違いはIDトークンの有無 • フォーマットは署名付きJWT • JWT(JSON Web Token)とは? ◦ 読み方は「ジョット」らしい ◦

    ヘッダー、ペイロード、署名の 3つのJSON文字列をBASE64URLエンコードして ピリオドで連結したもの(ヘッダー .ペイロード.署名)
  29. IDトークン(ヘッダー) • typ...JWT • alg...RS256など、署名アルゴリズムを指定 • kid...公開鍵のID

  30. IDトークン(ペイロード) • iss...Issuer(イシュアー)。IDトークン発行者 • aud...Audience(オーディエンス)。リライング・パーティのID • sub...Subject(サブジェクト)。エンドユーザーの識別子(ユーザIDとか) • iat...Issued At。JWTの発行時間。

    • exp...Expiration time。IDトークンの有効期限 • nonce...リプレイアタック防止用の文字列 これらは一部であり、その他のプロフィール等、色々と含ませることが可能 Authorization Code Flowの場合、 署名の検証なしでsub(ユーザ識別子)を取得できた時点で認証完了。 リライング・パーティとIDプロバイダ間で直接通信をしているため、 安全と言える。 Implicit Flowの場合、 署名を検証後にsub(ユーザ識別子)を取得できた時点で認証完了。 署名を検証することで改ざんはなかったと保証できるので安全と言える。
  31. IDトークン(署名) • ヘッダー+’.’+ペイロードを秘密鍵で署名したものを BASE64URLエンコーディングした文字列 • 共通鍵方式と公開鍵方式があるが、公開鍵方式が一般的 • IDプロバイダは、秘密鍵で署名する • リライング・パーティはIDプロバイダから公開鍵を取得して、

    署名を検証する • 署名の方式は、ヘッダーのalgに定義されている • 公開鍵はJWK(JSON Web Key)形式で配布される • Authorization Code Flowの場合は署名の検証が必須ではない ◦ 署名の検証をしなくても、認可コードのやり取りでリライング・パーティーと IDプロバイダ間で通信していることが明白なため、らしい • Implicit Flowの場合は署名の検証が必須 • ヘッダー+ペイロード == 復号化した署名 ◦ 一致しなければ、改ざんされている
  32. 最後にUserInfoエンドポイントにアクセス • UserInfoエンドポイントにはアクセス・トークンを使う • OpenID Connectは個人情報取得のためのAPIの実装が必須 • 認証以外の目的でユーザ情報を利用する場合に利用 • レスポンスにはsubクレーム(ユーザ識別子)が必ず含まれる

    ◦ IDトークンで取得済みのユーザ識別子と UserInfoエンドポイントで取得した ユーザ識別子が一致することを必ず確認しなければならない。 • フォーマットが標準化されているため、パースしやすい。 (OAuth2.0の場合はフォーマットが定義されていないため、  認可サーバ毎に独自のフォーマットを採用)
  33. ここ以外、OAuth2.0と ほぼ同じ!! この時点で認証完了! 仕様上、必須のAPI IDトークンのユーザ識別 子とUserInfo レスポンスの識別子の比 較でアクセス・トークンの すり替えに気付くことが できる

  34. おわかりいただけただろうか?

  35. OAuth2.0とOpenID Connectの付与方式 OAuth2.0 OpenID Connect(OIDC) 説明 Authorization Code Grant Authorization

    Code Flow クライアントがネット上に存在 最も推奨されている手法 Implicit Grant Implicit Flow クライアントがブラウザアプリ orスマ ホアプリなど 非推奨となっている(OAuthでは) Client Credentials Grant - リソースが個人に紐づいていない ケース マスターデータ配布等 Resource Owner Password Credentials Grant - IDとパスワードをクライアントに渡 す方式。普通は使わない。 ハイブリッドフロー ハイブリッドフロー Authorization Code FlowとImplicit Flowのハイブリッド • OAuthはGrant • OIDCはFlow セキュリティ的に最も優れているので オススメ。 クライアントがWebアプリなら、 普通はこれになる。
  36. Implicit Grantが危険という話 • クライアントがブラウザアプリorスマホアプリであるということ • リバースエンジニアリングに弱い ◦ DevToolsやデバッガ経由でアクセス・トークンが盗まれる危険性 DevToolsでレスポンスボディを 見たら、アクセス・トークンが

    丸見えじゃん。 このアクセス・トークンを 俺が作った悪意あるアプリで 使っちゃうぞ~!!
  37. アクセス・トークンが盗まれたときの危険性 • アクセス・トークンは認可のためにある(認証ではない) • アクセス・トークンを利用して依頼した処理は、 認可サーバでは、「あなたが本当に依頼したかどうか」は、判別できない ◦ アクセス・トークンが漏洩して、大量の DMを送られたとする。 それはあなたが依頼したことですか?違いますね?

    • アクセス・トークンは切符と同じ ◦ 電車に乗るための認可の証 ◦ 電車に乗るのが誰なのかは、切符に紐づいていない ◦ あなたの切符を使って第三者が電車に乗るということ
  38. 仕様を満たしている≠安全

  39. RailsでOAuthするには?

  40. gem doorkeeperを使え!

  41. gem doorkeeper • RailsアプリケーションにOAuth2.0の認可サーバ機能を付けるためのgem • チュートリアル通りにやれば、ほぼほぼハマることはない • インターネットに沢山情報がある。日本語の記事も豊富

  42. RailsでOpenID Connectするには?

  43. gem doorkeeper-openid_connect を使え!

  44. gem doorkeeper-openid_connect • doorkeeperでOAuthの認可サーバが構築できていることが前提 ◦ OpenID ConnectはOAuth2.0の拡張だから • OpenID Connectの機能を追加する

    • OpenID Connectの知識がないと設定ファイルの意味が全くわからない • 日本語どころか、英語でも情報が少ない
  45. 時間があって、コードが動けばデモ

  46. IDプロバイダ(認可サーバ)側 • gem ◦ devise ◦ doorkeeper ◦ doorkeeper-openid_connect •

    config/initializers/doorkeeper_openid_connect.rbで設定 ◦ issuerの設定 ◦ 秘密鍵の指定 ◦ 秘密鍵のアルゴリズムの指定 ◦ ユーザをアクセス・トークンで取得する方法の定義 ◦ subject(ユーザを一意に判定する値)の定義 ◦ claims(クレーム。要求のこと)の定義 ▪ IDトークンのペイロードと UserInfoエンドポイントに含まれる情報の定義 • doorkeeperにリライング・パーティの情報を登録 ◦ client_idとclient_secretの発行 ◦ callback urlの登録 ◦ スコープの登録(openidは必須)
  47. リライング・パーティ(クライアント)側 • gem ◦ devise ◦ omniauth-openid_connect • config/initializers/devise.rb ◦

    omniauthで認証するストラテジーの情報の定義 ▪ IDプロバイダに発行してもらった client_id, client_secretを設定 ▪ issuerの情報を登録 ▪ discovery: trueだと、公開鍵を探してくれる • /.well-known/openid-configuration • app/controllers/users/omniauth_callbacks_controller.rb ◦ リダイレクトしてきたときの処理を追加する • app/models/user.rb ◦ 認証情報からユーザを取得する処理を追加する
  48. デモ

  49. まとめ • OAuth2.0は、認可のプロトコル • OpenID Connectは、OAuth2.0を拡張した認証のプロトコル • 付与方式は、Authorization Code Grant(Flow)を使おう

    ◦ Implicit Grantはダメ、絶対(OAuthの場合) ◦ OpenID ConnectならImplicit Flowを使うのは有り(署名があるから) • アクセス・トークンは切符と同じ • OAuth2.0は仕様を満たしているからといって安全とは言えない場合がある • RailsでOAuth2.0のプロバイダを実装するならgem doorkeeperが楽 • RailsでOpenID Connectのプロバイダを実装するなら gem doorkeeper-openid_connectが楽 ◦ ただし、OpenID Connectの理解は必要
  50. 参考文献 • OAuth徹底入門 ◦ https://amzn.to/2I48EtP • 雰囲気で使わずきちんと理解する!整理してOAuth2.0を使うためのチュートリアル ガイド ◦ https://amzn.to/2TcmLnn

    • OAuth、OAuth認証、OpenID Connectの違いを整理して理解できる本 ◦ https://authya.booth.pm/items/1550861
  51. 謝辞 資料を公開後、誤っている箇所をご指摘いただきました。 ありがとうございました。 @authyasan @ritou