Slide 1

Slide 1 text

わかった 気になる ! OpenID Connect 2020-02-29 第22回 岡山Ruby, Ruby on Rails勉強会 株式会社リゾーム 尾古 豊明

Slide 2

Slide 2 text

修正履歴 ● 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エンドポイントの説明に、フォーマットが標準化されていることがメリットであることを記述し た。

Slide 3

Slide 3 text

目次 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. まとめ

Slide 4

Slide 4 text

自己紹介 名前:尾古 豊明(おこ とよあき) twitter: @patorash 所属:株式会社リゾーム システム開発部 役職:専門職 仕事内容: ショッピングセンターに関連するサービス開発 Ruby on Railsで自社サービスの開発・運用(7年目) ここ最近はMacのRubyがセグメンテーション違反を吐き始め、 開発に支障が出まくっているので開発環境のAll Docker化に取り組んでいる 4

Slide 5

Slide 5 text

この発表のゴールについて ● この発表のゴール ○ OAuth2.0がどういうものかをわかってもらう ○ OpenID Connectがどういうものかをわかってもらう ○ RailsでOpenID Connectする方法をざっくりわかってもらう ● この発表でしないこと ○ OAuth2.0やOpenID Connectの細かいところは説明しない ○ OAuth2.0の危険なところ等についても(詳しくは)説明しない

Slide 6

Slide 6 text

シングルサインオン(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

Slide 7

Slide 7 text

シングルサインオンのイメージ ・ ・ ・ GitHubにログインしていれば、様々なサービスを利用できる。 メリットは、個々のサービス毎にID、パスワードを管理しなくてもよいこと。

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

これが スコープ!

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

OAuth2.0とOpenID Connectの違い OAuth2.0 OpenID Connect やること 認可 発行するもの プロフィール参照API アプリケーション毎に任意 (GitHubでは存在する) スコープ アプリケーション毎に任意

Slide 17

Slide 17 text

認証に成功

Slide 18

Slide 18 text

OAuth2.0とOpenID Connectの違い OAuth2.0 OpenID Connect やること 認可 発行するもの アクセス・トークン プロフィール参照API アプリケーション毎に任意 (GitHubでは存在する) スコープ アプリケーション毎に任意

Slide 19

Slide 19 text

初回でプロフィール情 報を取得 クライアントで プロフィールAPIから 識別子を取得し、 認証に利用

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

OAuth2.0とOpenID Connectの違い OAuth2.0 OpenID Connect やること 認可 発行するもの アクセス・トークン プロフィール参照API アプリケーション毎に任意 (GitHubでは存在する) スコープ アプリケーション毎に任意

Slide 23

Slide 23 text

OAuth2.0とOpenID Connectの関係

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

ここ以外、OAuth2.0と ほぼ同じ!! 仕様上、必須のAPI

Slide 27

Slide 27 text

OpenID Connectをわかった気になる

Slide 28

Slide 28 text

OAuth2.0との違いはIDトークンの有無 ● フォーマットは署名付きJWT ● JWT(JSON Web Token)とは? ○ 読み方は「ジョット」らしい ○ ヘッダー、ペイロード、署名の 3つのJSON文字列をBASE64URLエンコードして ピリオドで連結したもの(ヘッダー .ペイロード.署名)

Slide 29

Slide 29 text

IDトークン(ヘッダー) ● typ...JWT ● alg...RS256など、署名アルゴリズムを指定 ● kid...公開鍵のID

Slide 30

Slide 30 text

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(ユーザ識別子)を取得できた時点で認証完了。 署名を検証することで改ざんはなかったと保証できるので安全と言える。

Slide 31

Slide 31 text

IDトークン(署名) ● ヘッダー+’.’+ペイロードを秘密鍵で署名したものを BASE64URLエンコーディングした文字列 ● 共通鍵方式と公開鍵方式があるが、公開鍵方式が一般的 ● IDプロバイダは、秘密鍵で署名する ● リライング・パーティはIDプロバイダから公開鍵を取得して、 署名を検証する ● 署名の方式は、ヘッダーのalgに定義されている ● 公開鍵はJWK(JSON Web Key)形式で配布される ● Authorization Code Flowの場合は署名の検証が必須ではない ○ 署名の検証をしなくても、認可コードのやり取りでリライング・パーティーと IDプロバイダ間で通信していることが明白なため、らしい ● Implicit Flowの場合は署名の検証が必須 ● ヘッダー+ペイロード == 復号化した署名 ○ 一致しなければ、改ざんされている

Slide 32

Slide 32 text

最後にUserInfoエンドポイントにアクセス ● UserInfoエンドポイントにはアクセス・トークンを使う ● OpenID Connectは個人情報取得のためのAPIの実装が必須 ● 認証以外の目的でユーザ情報を利用する場合に利用 ● レスポンスにはsubクレーム(ユーザ識別子)が必ず含まれる ○ IDトークンで取得済みのユーザ識別子と UserInfoエンドポイントで取得した ユーザ識別子が一致することを必ず確認しなければならない。 ● フォーマットが標準化されているため、パースしやすい。 (OAuth2.0の場合はフォーマットが定義されていないため、  認可サーバ毎に独自のフォーマットを採用)

Slide 33

Slide 33 text

ここ以外、OAuth2.0と ほぼ同じ!! この時点で認証完了! 仕様上、必須のAPI IDトークンのユーザ識別 子とUserInfo レスポンスの識別子の比 較でアクセス・トークンの すり替えに気付くことが できる

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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アプリなら、 普通はこれになる。

Slide 36

Slide 36 text

Implicit Grantが危険という話 ● クライアントがブラウザアプリorスマホアプリであるということ ● リバースエンジニアリングに弱い ○ DevToolsやデバッガ経由でアクセス・トークンが盗まれる危険性 DevToolsでレスポンスボディを 見たら、アクセス・トークンが 丸見えじゃん。 このアクセス・トークンを 俺が作った悪意あるアプリで 使っちゃうぞ~!!

Slide 37

Slide 37 text

アクセス・トークンが盗まれたときの危険性 ● アクセス・トークンは認可のためにある(認証ではない) ● アクセス・トークンを利用して依頼した処理は、 認可サーバでは、「あなたが本当に依頼したかどうか」は、判別できない ○ アクセス・トークンが漏洩して、大量の DMを送られたとする。 それはあなたが依頼したことですか?違いますね? ● アクセス・トークンは切符と同じ ○ 電車に乗るための認可の証 ○ 電車に乗るのが誰なのかは、切符に紐づいていない ○ あなたの切符を使って第三者が電車に乗るということ

Slide 38

Slide 38 text

仕様を満たしている≠安全

Slide 39

Slide 39 text

RailsでOAuthするには?

Slide 40

Slide 40 text

gem doorkeeperを使え!

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

RailsでOpenID Connectするには?

Slide 43

Slide 43 text

gem doorkeeper-openid_connect を使え!

Slide 44

Slide 44 text

gem doorkeeper-openid_connect ● doorkeeperでOAuthの認可サーバが構築できていることが前提 ○ OpenID ConnectはOAuth2.0の拡張だから ● OpenID Connectの機能を追加する ● OpenID Connectの知識がないと設定ファイルの意味が全くわからない ● 日本語どころか、英語でも情報が少ない

Slide 45

Slide 45 text

時間があって、コードが動けばデモ

Slide 46

Slide 46 text

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は必須)

Slide 47

Slide 47 text

リライング・パーティ(クライアント)側 ● 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 ○ 認証情報からユーザを取得する処理を追加する

Slide 48

Slide 48 text

デモ

Slide 49

Slide 49 text

まとめ ● 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の理解は必要

Slide 50

Slide 50 text

参考文献 ● OAuth徹底入門 ○ https://amzn.to/2I48EtP ● 雰囲気で使わずきちんと理解する!整理してOAuth2.0を使うためのチュートリアル ガイド ○ https://amzn.to/2TcmLnn ● OAuth、OAuth認証、OpenID Connectの違いを整理して理解できる本 ○ https://authya.booth.pm/items/1550861

Slide 51

Slide 51 text

謝辞 資料を公開後、誤っている箇所をご指摘いただきました。 ありがとうございました。 @authyasan @ritou