$30 off During Our Annual Pro Sale. View Details »

簡單易懂的 OAuth 2.0

簡單易懂的 OAuth 2.0

Note: 300+ Pages ,推薦下載 PDF

這年頭不管什麼 app 都要串別人的 API ,但如果你要造 API 給別人串,除了規劃 endpoint 和 JSON 資料結構之外,還有更重要的「存取管制」,以及「user 的存在」,例如,你會希望 API request 可以知道「要改哪個 user 的資料」,但不希望 client 儲存 user 的帳號密碼。

利用 OAuth 2 通訊協定,可以實作出 API 的存取管制,讓 API 得知要操作的對象 user 是誰,並且讓你做出像 Facebook 登入那樣子的登入流程。然而 OAuth 2.0 的 spec 根本就是個 [tl;dr] 的東西,但沒讀過 spec 也沒辦法輕鬆實作,更別說套現成的 gem 擋在 API 的前面。本演講會簡單介紹 OAuth 2 是怎麼一回事,並示範如何從零建立一個用 OAuth 2 鎖住的 Grape API。若您沒有 Ruby / Rails 的經驗,也可以大略得知製造 OAuth 2.0 API 鎖的方法。

延伸閱讀:

* 我 Blog 裡面的 OAuth 2 相關文章 http://blog.yorkxin.org/tags/OAuth
* Demo 的簡單 OAuth 2 Guard 實作 https://github.com/chitsaou/oauth2-api-sample

Yu-Cheng Chuang

November 26, 2013
Tweet

More Decks by Yu-Cheng Chuang

Other Decks in Programming

Transcript

  1. • ⇯௾č⊫ტӵĎ • Rails Developer at KKBOX, working at the

    KKTIX team • chitsaou, @yorkxin, blog.yorkxin.org
  2. Today’s Target • ୆὜ᆩ֡ OAuth 2 Protocol ᄸ喁஝ • ୆὜ु֤׭

    99% ࠎᧄ OAuth 2 ֻ֥೘ٚ API ໓ࡱ • ୆὜ᆩ֡ᄸ喁Ⴈ OAuth 2 ⅞୆֥ API
  3. Agenda • OAuth 2 ൞മ喁ĤॖၛଦῲἓખĤ • OAuth 2 ๙⇫⇐קᄸ喁஝ •

    ⚧ᄯ OAuth 2 Provider ֥ٚم • ֻ၂ՑႨ Rails + Grape API ᆜކ OAuth 2 ࣼഈ൭
  4. The Old-School Way… • App ေ୆℻ೆ≷ὂૡđὕ℥ૼ҂὜⁙۞ • ୆ေྐ಩ App ҂὜ଦ୆֥ૡ⁙۞

    • ࣼෘ App ޓܭđФἓሼὕ൞㢻ࣷ • ҂ܵ୆ྐ҂ྐđ໡ّᆞ൞҂ྐ……
  5. OAuth ೂޅࢳ㢯≾ἠ↜ⅳ • ↌ᅟิ܂ܲٚࢸ૫đ⃸୆ॖၛ൱⃴ӱൔ൐Ⴈ⊷ਘ • ӱൔթ֥൞ Token ط٤≷ὂૡ
 ္Ⴈ Token

    ಀյ API • Token ॖၛἲקթ౼ữ↏čscopes, ೂğݺႶਙіĎ • Token Ⴕ௹ཋط౏ॖၛ⅗ℭӜ⇍č҂ஃФἓሼĎ
  6. OAuth 2 䥰૫֥࢘೤ • Resource Owner - ⊷ਘ∭Ⴕᆀđ๙ӈ൞ದ  (User) •

    Client - ࠧ App đေթ౼ User ֥⊷ਘ֥ӱൔ • Authorization Server - ⊺ܵ၂్൱⃴൙↩ • Resource Server - Client ạ≾䥰ଦ⊷ਘđࠧ API
  7. Resource Owner = User • ࣼ൞୆↌ᅟ֥ User • API ঘ֥֞൞۵

    User ႵἬ֥⊷ਘ • ২ೂݺႶ଀Ẫaྐࡱ⤨ಸ • ൱⃴с⇜ῂႮЧದ⃤ሱ⃷⃾
  8. Resource Owner = Client • ≾⊕౦㣐㢻Ⴕದ֥թᄝb • ২ğ஁܄Ῐ⊷ਘ • Twitter

    Ẁ㬪 App-Only Authorization • Facebook Ẁ㬪 App Access Token
  9. Client с⇜൙༵䩏⤳ • “Client Registration” • Client ID • Client

    Secret čℶ㬪ૡĎ • Redirect URI ← ≾ἠޓᇗေ
  10. Redirect URI • User Чದ⃤ሱ⃷⃾ᆭᗥđْ߭᾵ݔ֞ Client • ေ൙༵ᆷקđ೏҂၂ᇁ≣҂ॖ Redirect Ἶಀ

    • ॖၛᆷק؟⊾đ֌๙ӈ൞၂⊾đࠇ൞Ῐⅽ၂ᇁ • ቋݺ൞ HTTPS č҂ルᇅđ২ೂ൭Ὠ App ࣼḰ҂֞Ď
  11. Public v.s. Confidential Client • ۴ῌwି҂ିЌὊ⊷ਘxῲ⃯ٳ • Confidential - Server-Side

    Application • Public - ൭Ὠ App / ም૫ӱൔ / JavaScript App / Browser Extension
  12. Client Authorization (⃾⊈) • ԛൕ Client ID + Secret ཟ

    Auth. Server ⃾⊈ሱ࠭ • ္ࣼ൞䪌 Client ေ֨ೆ֞ Auth. Server • ᆺℳႨ Confidential Client
  13. Client • Ⴕ ID / Secret Ⴈᧄ⃾⊈ • Ⴈ Redirect

    URI ⃷Ќ⏟´ఖ⊨ᆶ֞ᆞ⃷֥ Client • Public / Confidential Ⴕ۲ሱℳႨ֥൱⃴ੀӱ
  14. Endpoints • Authorization Endpoint - Ⴈῲἡ User Чದ⃷⃾൱⃴ • Token

    Endpoint - Ⴈῲ⃸ Client ౼֤ᆇᆞ֥ Token • Redirection Endpoint - Client Ⴈῲ൬⊷ਘႨ
  15. Authorization Endpoint • ἡ User Чದ⃷⃾൱⃴ • ൞၂ἠ↌∉ • ଦ֥֞൞

    “Grant” č൱⃴⊯Ďط҂൞ Token • User ճڭᆭᗥđ὜⊨߭ Client ֥ Redirect URI
  16. Redirection Endpoint • Ⴈῲạ⏟´ఖࢤ൬ Auth. Server ῲ֥⊷ਘ • Ῐᄝ Client

    ط҂൞ Auth. Server • Client 䩏⤳ℭေ⇔֥ “Callback URL” • Auth. Server ὜⇼⊈ Redirect URI ൞ڎཌྷژҌ⊨ᆶ
  17. SSL! SSL! SSL! • Auth. Server ഈ૫֥ Endpoints с⇜ഈ HTTPS

    • Client с⇜⇼⊈ SSL Certificate ൞ڎކ۬ • Client Redirection Endpoint ҂ルᇅđ֌ିഈቋݺഈ
 ↌ᅟ → ቋݺഈ
 ൭Ὠ / ም૫ App → 㢻Ḱمॖၛ҂ေഈ
  18. Resource Server • Client с⇜ԛൕ Token ҌିΆಀଦ⊷ਘ • Client ᆺေԛൕ

    Token ࣼିΆಀଦ⊷ਘ • ॖၛႨ Scope ཋᇅ Token ିⴺ౼Ⴈ֥⊷ਘữ↏
  19. • RFC 6749: The OAuth 2.0 Authorization Framework • 77

    pages (PDF) • RFC 6750: The OAuth 2.0 Authorization Framework: Bearer Token Usage • 19 pages (PDF) tl;dr
  20. OAuth 2.0 Spec(s) • RFC 6749 - ק∕∻ Token ނứႵἬ֥

    Protocol • RFC 6750 - ק∕wBearer Tokenxᄸ喁Ⴈ
  21. RFC 6749: OAuth 2 Protocol • ק∕ਔ OAuth 2 ֥࢘೤a޺ọٚൔ

    • ק∕ਔ⊷ਘႵଧུaᄸ喁஝ • ק∕ਔނứa㍤ứ Token ֥֩ Protocol • ἲ὎ਔ 4 ⊕ӈᾖwℳކ൐Ⴈ OAuth 2 ֥ੀӱx
  22. RFC 6750: Bearer Token • RFC 6749 ᆺἲק൱⃴ٚൔđ㢻ἲק API ᄸ喁Ẳ

    • RFC 6750 ק∕၂⊕ࢡቓ “Bearer” ֥ Token Type • ۲⊕ type Ⴕ҂๝Ẳمđ Bearer ൞ᆰࢤ == ᾋҰ • ၂ओὐࢳℴğwᆰࢤଦῲࣼିႨđ҂Ⴈ⃐ῲ⃐ಀx
  23. Client ID / Secret • Ⴈᧄ Client ⃾⊈čClient ֨ೆ֞ Auth.

    ServerĎ • 䩏⤳֥ℭީứἡđ⁙ࣼྛ • HTTP Basic Auth ࠇЇᄝ Form 䥰૫č࣌Ⴈ URLĎ
  24. HTTP Basic Auth ID = abc, Secret = 123 abc:123

    concat with `:` YWJjOjEyMw== base64() Authorization: Basic YWJjOjEyMw== Basic Auth Header
  25. Token(s) • Access Token - յ API Ⴈ֥ • Refresh

    Token - Access Token Ἶ௹ॖၛ㍤ứྍ֥
  26. Access Token • ཟ Resource Server ေ⊷ਘđႨ Access Token •

    ॖၛḳ၂⊾ Scope • ॖၛ℟௹ཋđॖၛӜ⇍ (Revoke) • ൱⃴ੀӱ֥ଢṌࣼ൞ေଦ֞ Access Token
  27. Refresh Token • ㍤ứ Access Token Ⴈđᆺ὜ẖ֞ Auth. Server •

    ḳק၂ἠ Access Tokenđ⅗ Access Token ၂ఏނứ • ႨἾࣼാི
 ྍ֥ Access Token ὜ḳྍ֥ Refresh Token
  28. State • Ⴈῲٝᆸ CSRF ۾ὧ • Client 㲗 Browser 㲗

    Auth. Server ൞ޓາ↿ˀ • State ẖ֞ Auth. Server ࣼေჰٿ҂ọْ߭ • Client ⇼⊈ᆭ • ⁙ᆴࣼྛđ္ॖၛႨ HMAC ⃐
  29. ౼֤൱⃴֥ੀӱ 1. Client ཟ Res. Owner ౼֤ “Grant” č൱⃴⊯Ď 2.

    Client Ⴈ “Grant” ཟ Authorization Server ㍤ Token 3. Token ଦ֞ਔđॖၛಀյ API ᆜἠ Protocol ቋₒ֥ᄝ≾䥰
  30. ቋӈᾖ֥ Scenario Ⴕ↌ᅟ Facebook đ୆༐ຬᄝପഈ૫֥ User 
 ἡ୆֥↌ᅟ⃴ཋđॖၛồ౼ପ User ֥⊷ਘ

    Resource Owner Client Token Resource Server ๩Ἶ Facebook ֥ Authorization Server
  31. Resource Owner Browser Client ! Authorization Server (A) (A) ID,

    Redirect URI, Scope, State ※Ӓሱ spec Authorization Endpoint Token Endpoint Redirection Endpoint
  32. Resource Owner Browser Client ! Authorization Server (A) (A) ID,

    Redirect URI, Scope, State (B) (B) ↜ Resource Owner ※Ӓሱ spec Authorization Endpoint Token Endpoint Redirection Endpoint
  33. Resource Owner Browser Client ! Authorization Server (A) (A) ID,

    Redirect URI, Scope, State (B) (B) ↜ Resource Owner (C) Grant Code, Scope, State ※Ӓሱ spec Authorization Endpoint Token Endpoint Redirection Endpoint
  34. Resource Owner Browser Client ! Authorization Server (A) (A) ID,

    Redirect URI, Scope, State (B) (B) ↜ Resource Owner (C) Grant Code, Scope, State (D) Grant Code, Client Auth ※Ӓሱ spec Authorization Endpoint Token Endpoint Redirection Endpoint
  35. Resource Owner Browser Client ! Authorization Server (A) (A) ID,

    Redirect URI, Scope, State (B) (B) ↜ Resource Owner (C) Grant Code, Scope, State (D) Grant Code, Client Auth (E) Token ※Ӓሱ spec Authorization Endpoint Token Endpoint Redirection Endpoint
  36. Authorization Server ֥ọቔ 1. ۴ῌ Client ID ᅳ Client 2.

    ⃷⃾ Redirect URI ۵൙༵䩏⤳֥ཌྷژ • ೏҂ᆞ⃷≣ေ₵ấ↪đ҂ॖ⊨߭ἐ URI 3. ⃷⃾མണ⃪֥ scope ᆞ⃷č۬ൔa⤨ಸ֩Ď 4. 㢻↜ⅳࣼ↜ Resource Owner ေ҂ေ൱⃴ (B)
  37. Authorization Server ֥ọቔ • ೏ᄍ⇝đ≣⊨߭ Client đڸഈ Grant Code •

    ೏҂ᄍ⇝đ≣⊨߭ Client đ❣ڸഈấ↪⇫༏ • ೏἗἗Ⴕẖ state Ἶῲđ≣ჰٿ҂ọڸഈ
  38. (D) ଦ Code ㍤ Token • Client ᄝᗥ෻ቓ≾ࡱ൙ • POST

    ֞ Auth. Server ֥ Token Endpoint ㍤ Token • Client Authentication • grant_type=code, code, redirect_uri, client_id (Ᾱ Public Client)
  39. POST /oauth/access_token HTTP/1.1
 Host: graph.facebook.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=authorization_code
 
 &code=AQABIWdeO3miePq0uH2VCUvhGr- voXz3zunrCiX5Bz9IFF8m82bmP(...)
 
 &redirect_uri=http%3A%2F%2Flocalhost %3A3000%2Fusers%2Fauth%2Ffacebook%2Fcallback ※ ൙ℯഈ Facebook Ⴈ GET đ҂ކṌ⊵đ༯ⅾ⃪ሱྛₔṘ
  40. POST /oauth/access_token HTTP/1.1
 Host: graph.facebook.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=authorization_code
 
 &code=AQABIWdeO3miePq0uH2VCUvhGr- voXz3zunrCiX5Bz9IFF8m82bmP(...)
 
 &redirect_uri=http%3A%2F%2Flocalhost %3A3000%2Fusers%2Fauth%2Ffacebook%2Fcallback Token Endpoint ※ ൙ℯഈ Facebook Ⴈ GET đ҂ކṌ⊵đ༯ⅾ⃪ሱྛₔṘ
  41. POST /oauth/access_token HTTP/1.1
 Host: graph.facebook.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=authorization_code
 
 &code=AQABIWdeO3miePq0uH2VCUvhGr- voXz3zunrCiX5Bz9IFF8m82bmP(...)
 
 &redirect_uri=http%3A%2F%2Flocalhost %3A3000%2Fusers%2Fauth%2Ffacebook%2Fcallback Token Endpoint Client Authentication ※ ൙ℯഈ Facebook Ⴈ GET đ҂ކṌ⊵đ༯ⅾ⃪ሱྛₔṘ
  42. POST /oauth/access_token HTTP/1.1
 Host: graph.facebook.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=authorization_code
 
 &code=AQABIWdeO3miePq0uH2VCUvhGr- voXz3zunrCiX5Bz9IFF8m82bmP(...)
 
 &redirect_uri=http%3A%2F%2Flocalhost %3A3000%2Fusers%2Fauth%2Ffacebook%2Fcallback Token Endpoint іൕw໡ଦ֥֞൱⃴⊯൞ Grant Codex Client Authentication ※ ൙ℯഈ Facebook Ⴈ GET đ҂ކṌ⊵đ༯ⅾ⃪ሱྛₔṘ
  43. POST /oauth/access_token HTTP/1.1
 Host: graph.facebook.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=authorization_code
 
 &code=AQABIWdeO3miePq0uH2VCUvhGr- voXz3zunrCiX5Bz9IFF8m82bmP(...)
 
 &redirect_uri=http%3A%2F%2Flocalhost %3A3000%2Fusers%2Fauth%2Ffacebook%2Fcallback Token Endpoint іൕw໡ଦ֥֞൱⃴⊯൞ Grant Codex Grant Code Client Authentication ※ ൙ℯഈ Facebook Ⴈ GET đ҂ކṌ⊵đ༯ⅾ⃪ሱྛₔṘ
  44. POST /oauth/access_token HTTP/1.1
 Host: graph.facebook.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=authorization_code
 
 &code=AQABIWdeO3miePq0uH2VCUvhGr- voXz3zunrCiX5Bz9IFF8m82bmP(...)
 
 &redirect_uri=http%3A%2F%2Flocalhost %3A3000%2Fusers%2Fauth%2Ffacebook%2Fcallback Token Endpoint іൕw໡ଦ֥֞൱⃴⊯൞ Grant Codex Grant Code ჰ Redirect URI Client Authentication ※ ൙ℯഈ Facebook Ⴈ GET đ҂ކṌ⊵đ༯ⅾ⃪ሱྛₔṘ
  45. Authorization Server ֥ọቔ • ⃷⃾ Client Authentication (ID / Secret)

    ᆞ⃷ • ᅳ֞ἐ Grant Code đ⃷⃾ః Redirect URI ၂ଆ၂∄ • 㢻↜ⅳ֥ὐࣼứ Token
  46. (E) ứ Token • Client ֥ Token Request ֥ Response

    • ൞ JSON Response • ॖၛ၂⟸ứ Refresh Token • User ൱⃴֥ Scope ೏∻ണ⃪ℭ҂၂ᇁ≣ေڸഈ
  47. HTTP/1.1 200 OK
 Content-Type: application/json;charset=UTF-8
 Cache-Control: no-store
 Pragma: no-cache
 {


    "access_token":"2YotnFZFEjr1zCsicMWpAA",
 "token_type":"Bearer",
 "expires_in":3600,
 "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
 "scopes":"email"
 }
  48. HTTP/1.1 200 OK
 Content-Type: application/json;charset=UTF-8
 Cache-Control: no-store
 Pragma: no-cache
 {


    "access_token":"2YotnFZFEjr1zCsicMWpAA",
 "token_type":"Bearer",
 "expires_in":3600,
 "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
 "scopes":"email"
 } Access Token
  49. HTTP/1.1 200 OK
 Content-Type: application/json;charset=UTF-8
 Cache-Control: no-store
 Pragma: no-cache
 {


    "access_token":"2YotnFZFEjr1zCsicMWpAA",
 "token_type":"Bearer",
 "expires_in":3600,
 "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
 "scopes":"email"
 } Access Token іൕ≾ἠ Token ൞ Bearer Token
  50. HTTP/1.1 200 OK
 Content-Type: application/json;charset=UTF-8
 Cache-Control: no-store
 Pragma: no-cache
 {


    "access_token":"2YotnFZFEjr1zCsicMWpAA",
 "token_type":"Bearer",
 "expires_in":3600,
 "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
 "scopes":"email"
 } Access Token іൕ≾ἠ Token ൞ Bearer Token 3600 ૰ᆭᗥἾ௹
  51. HTTP/1.1 200 OK
 Content-Type: application/json;charset=UTF-8
 Cache-Control: no-store
 Pragma: no-cache
 {


    "access_token":"2YotnFZFEjr1zCsicMWpAA",
 "token_type":"Bearer",
 "expires_in":3600,
 "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
 "scopes":"email"
 } Access Token іൕ≾ἠ Token ൞ Bearer Token 3600 ૰ᆭᗥἾ௹ Access Token Ớ∣֥ Refresh Token
  52. HTTP/1.1 200 OK
 Content-Type: application/json;charset=UTF-8
 Cache-Control: no-store
 Pragma: no-cache
 {


    "access_token":"2YotnFZFEjr1zCsicMWpAA",
 "token_type":"Bearer",
 "expires_in":3600,
 "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
 "scopes":"email"
 } Access Token іൕ≾ἠ Token ൞ Bearer Token 3600 ૰ᆭᗥἾ௹ Access Token Ớ∣֥ Refresh Token ೏ scope ∻ണ⃪ℭ ҂၂ᇁ≣ေڸഈ
  53. ൭Ὠ App / ም૫ App • ℶ㬪 Public đClient Authentication

    ҂ॖྐ • Token Request ေڸഈ Client ID
 ⃷Ќ Token ứἡᆞ⃷֥ Client • App ⅹܥק URI đೂ
 kktix-app:oauth2-callback
  54. What about JavaScript App • “User-Agent-Based Client” • Public Client

    • Redirect Endpoint ္㢻Ḱمⅹሱị Protocol • Auth. Code Grant Flow ҂ॖႨđᄸ喁ḰĤ
  55. Implicit Grant Flow • ⊦⁽ἡ Public Client Ⴈ • Grant

    ҂ẖ֞ Client đᆰࢤứ Token • ҂ῂἾ Token Endpoint • ứ֥ Token ๙ӈ൞؋ི௹đࢆ֮Ф๦֥ἀ↿ • ҂ἡ Refresh TokenđἾ௹ᇗྍ஝ണ⃪ੀӱ
  56. Resource Owner Browser Client (JS) ! Authorization Server ※Ӓሱ spec

    Authorization Endpoint Client’
 (Web Server) Redirection Endpoint
  57. Resource Owner Browser Client (JS) ! Authorization Server (A) (A)

    ID, Redirect URI, Scope, State ※Ӓሱ spec Authorization Endpoint Client’
 (Web Server) Redirection Endpoint
  58. Resource Owner Browser Client (JS) ! Authorization Server (A) (A)

    ID, Redirect URI, Scope, State (B) (B) ↜ Resource Owner ※Ӓሱ spec Authorization Endpoint Client’
 (Web Server) Redirection Endpoint
  59. Resource Owner Browser Client (JS) ! Authorization Server (A) (A)

    ID, Redirect URI, Scope, State (B) (B) ↜ Resource Owner (C) Token (in Frag.), Scope, State ※Ӓሱ spec Authorization Endpoint Client’
 (Web Server) Redirection Endpoint
  60. Resource Owner Browser Client (JS) ! Authorization Server (A) (A)

    ID, Redirect URI, Scope, State (B) (B) ↜ Resource Owner (C) Token (in Frag.), Scope, State ※Ӓሱ spec Authorization Endpoint Client’
 (Web Server) Redirection Endpoint (D) GET Redirect URI (no Token)
  61. Resource Owner Browser Client (JS) ! Authorization Server (A) (A)

    ID, Redirect URI, Scope, State (B) (B) ↜ Resource Owner (C) Token (in Frag.), Scope, State (E) JavaScript (to Decode Token) ※Ӓሱ spec Authorization Endpoint Client’
 (Web Server) Redirection Endpoint (D) GET Redirect URI (no Token)
  62. Resource Owner Browser Client (JS) ! Authorization Server (A) (A)

    ID, Redirect URI, Scope, State (B) (B) ↜ Resource Owner (C) Token (in Frag.), Scope, State (E) JavaScript (to Decode Token) ※Ӓሱ spec Authorization Endpoint Client’
 (Web Server) Redirection Endpoint (D) GET Redirect URI (no Token) (F)
  63. Resource Owner Browser Client (JS) ! Authorization Server (A) (A)

    ID, Redirect URI, Scope, State (B) (B) ↜ Resource Owner (C) Token (in Frag.), Scope, State (E) JavaScript (to Decode Token) ※Ӓሱ spec Authorization Endpoint Client’
 (Web Server) Redirection Endpoint (D) GET Redirect URI (no Token) (G) Assign Access Token (F)
  64. (C) ~ (G) ޽ളസଊℿ • (C) Auth. Server ࢡ Browser

    ⊨߭ Redirect URI • https://client.com/oauth2/callback#access_token=… • (D) Browser ὜ಀ GET ἐ URL đ֌҂ݣ # č฿ྟĎ • Token ሱọЌ਽ᄝ Browser ֥ Fragment Part 䥰૫
  65. (C) ~ (G) ޽ളസଊℿ • (E) ᄜ❟߭၂ἠ JavaScript Ⴈῲࢳԛ #

    䥰૫֥ Token • (F) Browser ሱọ run ≾ἠ JavaScript ࢳԛ Token • (G) Ϝࢳԛῲ֥ Token ❟ἡ JavaScript App
  66. ෮ၛ㬪൉喁ླေ Client’ ٳദ • JavaScript ҂ିῘ Redirection Endpoint
 ෮ၛႨ Web

    Server Ῐ • 䥰૫ࣼ൞၂ἠ JavaScript code Ⴈῲࢳԛ Token
 ❣ẖἡ JavaScript App (ᆇ Client)
  67. Redirection Endpoint ֥⤨ಸ <script>
 var access_token = [extract token from

    frag];
 // store token in local storage or cookie
 </script>
  68. Implicit Grant Flow Usage • Facebook JavaScript SDK • ൭Ὠ

    App aም૫ App ္ℳႨ
 Facebook: WebView ᾄⅹܥק Redirect URI
 ሂԛ #access_token
  69. What if ሱ㸗ሱႨĤ • ሱ࠭⇔֥ script མေႨ Token ಀյ API

    • Server App ၘῂթਔ≷ὂૡđམڿӮ OAuth 2
  70. Resource Owner Client ! Authorization Server (B) Client Auth, Username,

    Password, Scopes ※Ӓሱ spec Token Endpoint (A) Username, Password
  71. Resource Owner Client ! Authorization Server (B) Client Auth, Username,

    Password, Scopes (C) Token ※Ӓሱ spec Token Endpoint (A) Username, Password
  72. Resource Owner Password Credentials Grant Flow • ླေ൞ Resource Owner

    ۚ؇ྐῳ Client • ቔ∊༢ⅼ⤨ࡹ֥∣ႨӱൔčOS X ֥ Twitter ᆜކĎ • ܲٚ∣ႨӱൔčGitHub.appĎ • ౏ః෰⦁֥ੀӱ׻҂ℳႨ
  73. Resource Owner Password Credentials Grant Flow • No “state” ၹ㬪҂ῂἾ

    Browser • No “Redirect URI” ၹ㬪㢻Ⴕ redirection • ᆰࢤ POST ಀ Token Endpoint ଦ Token
  74. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=password
 
 &username=chitsaou
 &password=12345678
 
 &scope=email
  75. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=password
 
 &username=chitsaou
 &password=12345678
 
 &scope=email Token Endpoint
  76. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=password
 
 &username=chitsaou
 &password=12345678
 
 &scope=email Token Endpoint Client Authentication
  77. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=password
 
 &username=chitsaou
 &password=12345678
 
 &scope=email Token Endpoint іൕw໡ଦ֥֞൱⃴⊯൞
 User ֥ Passwordx Client Authentication
  78. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=password
 
 &username=chitsaou
 &password=12345678
 
 &scope=email Token Endpoint іൕw໡ଦ֥֞൱⃴⊯൞
 User ֥ Passwordx Credentials Client Authentication
  79. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=password
 
 &username=chitsaou
 &password=12345678
 
 &scope=email Token Endpoint іൕw໡ଦ֥֞൱⃴⊯൞
 User ֥ Passwordx Credentials Client Authentication མေ⃪౰֥⃴ཋữ↏čScopesĎ
  80. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=client_credentials
 
 &scope=search_timeline Token Endpoint
  81. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=client_credentials
 
 &scope=search_timeline Token Endpoint Client Authentication
  82. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=client_credentials
 
 &scope=search_timeline Token Endpoint іൕw໡ Client ေണ⃪ Token ሱႨx Client Authentication
  83. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=client_credentials
 
 &scope=search_timeline Token Endpoint іൕw໡ Client ေണ⃪ Token ሱႨx Client Authentication མေ⃪౰֥⃴ཋữ↏čScopesĎ
  84. 4 built-in grant flows • Authorization Code • Implicit •

    Resource Owner Password Credentials • Client Credentials
  85. Errors on Authorization Endpoint 1. ⃾҂ԛ ClientaRedirect URI ҂ژ 2.

    Ṛ⅂ẖấ / Authorization Server 㢻ℯቔଖུۿି 3. Resource Owner ऋ䌉൱⃴ 4. Internal Server Error
  86. Client ⃾҂֤aRedirect URI ҂ژ • Redirect URI 㢻ἡ / ҂ᆞ⃷

    / 㢻൙༵䩏⤳ • ေℶ㬪۾ὧđ҂ॖၛ Redirect ֞ἐ Redirect URI • ေิൕࣞۡ⇫༏ἡ Resource Owner
  87. ః෰ấ↪ • ေ⊨߭ Redirect URI ཟ Client ۡᆩấ↪ • ᄝ

    URI ᗥ૫ڸഈ error parameters • Auth Code Grant Flow - Ⴈ Query ?error=... • Implicit Grant Flow - Ⴈ Fragment #error=...
  88. Error Parameters • error - Error Code đсแđ༯⇈ • error_description

    - ᾏẪ䪌ૼấ↪ • error_uri - ၂ἠ↌ᆶᆷ֞⇈↱䪌ૼ↌∉ • state - ẖ߭ Client ֥ state ჰᆴđᆭభႵἡࣼсแ • ଖུὕ὜ἡ error_subcode čႭఃᇏἽ֥↌ᅟĎ
  89. http://localhost:3000/users/auth/facebook/ callback? error=access_denied
 
 &error_description=User Denies Authrization
 
 &error_uri=https://doc.example.com/...
 


    &state=446c63696b24b4b6687cdff62eabce3a9c9d63 33d7c807e6 Redirection Endpoint ấ↪ ᾏඍấ↪൞൉喁 ु⇈↱䪌ૼ֥ URL
  90. http://localhost:3000/users/auth/facebook/ callback? error=access_denied
 
 &error_description=User Denies Authrization
 
 &error_uri=https://doc.example.com/...
 


    &state=446c63696b24b4b6687cdff62eabce3a9c9d63 33d7c807e6 Redirection Endpoint ấ↪ ჰٿ҂ọ֥ State ᆴ ᾏඍấ↪൞൉喁 ु⇈↱䪌ૼ֥ URL
  91. error = Meaning invalid_request 㢻ἡсေṚ⅂aἡਔ҂ᆞ⃷֥Ṛ⅂a
 ᇗ♶ἡṚ⅂aࠇః෰ჰၹẹᇁ↥مࢳồb unauthorized_client Client ҂ሙႨ≾⊕ Response

    Type
 ῲ౼֤ Authorization Codeb unsupported_response_type Authorization Server ҂ᆦჱ൐Ⴈ≾⊕ Response Typeb invalid_scope ෮ေ౰֥ scope ҂ᆞ⃷a
 ҂ૼa↥مࢳồb Client ᄯӮ֥ấ↪
  92. error = Meaning server_error Authorization Server მ֞ၩຓ֥౦㣐ط
 ↥مẕ৘⃪౰b temporarily_unavailable Authorization

    Server ӑ≘ࠇ→ྩᇏđ
 ↥مẕ৘b Authorization Server Internal Server Error
  93. error = Meaning server_error Authorization Server მ֞ၩຓ֥౦㣐ط
 ↥مẕ৘⃪౰b temporarily_unavailable Authorization

    Server ӑ≘ࠇ→ྩᇏđ
 ↥مẕ৘b Q: 㬪൉喁҂ିႨ 500 ߭Ĥ Authorization Server Internal Server Error A: ၹ㬪 500 ҂ᆦჱ Location ⊨ᆶđerror ẖ҂߭ Client
  94. Errors on Token Endpoint 1. Auth. Server ⃾҂֤ Client 2.

    Ṛ⅂ẖấ / Authorization Server 㢻ℯቔଖུۿି 3. ൱⃴⊯ (Grant) ҂ᆞ⃷ 4. Internal Server Error
  95. ߭∣ٚൔ • ၂ੰЇΆ JSON ߭ • ๙ӈ߭ 400 Bad Request

    • ೏ Client ⃾⊈ാḮ & Ⴈ Authorization Header ⃾⊈
 → ೖ WWW-Authenticate header
  96. Error Parameters (≅ Auth E.P.) • error • error_description •

    error_uri • ଖུὕ὜ἡ error_subcode čႭఃᇏἽ֥↌ᅟĎ • No state (ၹ㬪㢻Ⴕ state ẖΆῲά)
  97. HTTP/1.1 401 Unauthorized
 Content-Type: application/json;charset=UTF-8
 WWW-Authenticate: Basic
 Cache-Control: no-store
 Pragma:

    no-cache
 {
 "error":"invalid_client",
 "error_description":"Client Authentication Failed",
 "error_uri":"https://doc.example.com/..."
 }
  98. HTTP/1.1 401 Unauthorized
 Content-Type: application/json;charset=UTF-8
 WWW-Authenticate: Basic
 Cache-Control: no-store
 Pragma:

    no-cache
 {
 "error":"invalid_client",
 "error_description":"Client Authentication Failed",
 "error_uri":"https://doc.example.com/..."
 } ۲Ⴕࡹ∗֥ Response Code
  99. HTTP/1.1 401 Unauthorized
 Content-Type: application/json;charset=UTF-8
 WWW-Authenticate: Basic
 Cache-Control: no-store
 Pragma:

    no-cache
 {
 "error":"invalid_client",
 "error_description":"Client Authentication Failed",
 "error_uri":"https://doc.example.com/..."
 } ۲Ⴕࡹ∗֥ Response Code Client ๩Ἶ Basic Auth
 ⃾⊈ാḮ≣ೖ≾ἠ header
  100. HTTP/1.1 401 Unauthorized
 Content-Type: application/json;charset=UTF-8
 WWW-Authenticate: Basic
 Cache-Control: no-store
 Pragma:

    no-cache
 {
 "error":"invalid_client",
 "error_description":"Client Authentication Failed",
 "error_uri":"https://doc.example.com/..."
 } ۲Ⴕࡹ∗֥ Response Code Client ๩Ἶ Basic Auth
 ⃾⊈ാḮ≣ೖ≾ἠ header ấ↪
  101. HTTP/1.1 401 Unauthorized
 Content-Type: application/json;charset=UTF-8
 WWW-Authenticate: Basic
 Cache-Control: no-store
 Pragma:

    no-cache
 {
 "error":"invalid_client",
 "error_description":"Client Authentication Failed",
 "error_uri":"https://doc.example.com/..."
 } ۲Ⴕࡹ∗֥ Response Code Client ๩Ἶ Basic Auth
 ⃾⊈ാḮ≣ೖ≾ἠ header ấ↪ ᾏඍấ↪൞൉喁
  102. error = Meaning invalid_client Client ⃾⊈ാḮ Authorization Server ⃾҂ԛ Client

    ေ߭ 401 Unauthorized ೂݔ൞Ⴈ Basic Auth ෂԛ Client Auth đ≣ေڸഈ WWW-Authenticate: Basic
  103. error = Meaning invalid_grant ิԛ֥ Grant ࠇ൞ Refresh Token ҂ᆞ⃷a

    Ἶ௹aФӜ⇍đࠇ Redirection URI ҂ژđ ࠇ۴Чࣼ҂൞ἡ୆≾ἠ Clientb ൱⃴⊯҂ᆞ⃷
  104. error = Meaning invalid_request 㢻ἡсေṚ⅂aἡਔ҂ᆞ⃷֥Ṛ⅂a
 ᇗ♶ἡṚ⅂aࠇః෰ჰၹẹᇁ↥مࢳồb unauthorized_client Client ҂ሙႨ≾⊕ Response

    Type
 ῲ౼֤ Authorization Codeb unsupported_grant_type Authorization Server ҂ᆦჱ൐Ⴈ≾⊕
 Grant Typeb invalid_scope ෮ေ౰֥ scope ҂ᆞ⃷a
 ҂ૼa↥مࢳồb Client ᄯӮ֥ấ↪
  105. error = Meaning — — Q: 㬪൉喁㢻ႵĤ Authorization Server Internal

    Server Error A: ၹ㬪൞ Client ᆰࢤứ Request ֞ Serverđᆰࢤ₵ 500 ࣼྛ
  106. HTTP/1.1 200 OK
 Content-Type: application/json;charset=UTF-8
 Cache-Control: no-store
 Pragma: no-cache
 {


    "access_token":"2YotnFZFEjr1zCsicMWpAA",
 "token_type":"Bearer",
 "expires_in":3600,
 "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
 "scopes":"email"
 }
  107. Bearer Token • RFC 6750 ק∕đ၂⊕ OAuth 2.0 ֥ Token

    • ႨمቋᾏẪğԛൕ Token ἡ Resource Server • Token ⤨ಸ⁙ࣼྛ • Spec ᆺἲקԛൕ Token ֥ٚൔ & ấ↪⇫༏
  108. ԛൕ Token ֥ٚم • (in Header) Authorization: Bearer 2YotnFZF... •

    (in Body) &access_token=2YotnFZF... • (in URL) ?access_token=2YotnFZF... ҂๷ᾑ ቋ๷ᾑ
  109. Authorization: Basic XXXXXXXX • с⇜ᆦჱ • ᆰࢤϜ Token ሳԱ٢Ά Header

    ࣼྛਔ ቋ๷ᾑ GET /me.json HTTP/1.1
 Host: api.example.com
 Authorization: Bearer 2YotnFZF...
  110. in Request Body • ℳႨᧄ "Form" ᆭ ֥ request (POST, PATCH

    etc.) • ҂ॖၛ൞ multi-part • Content-Type: application/x-www-form-urlencoded
  111. ҂๷ᾑ in URL Query Param • ҂๷ᾑđၹ㬪ॖି὜Фὸᄝ log 䥰 •

    ေ⃷Ќ response ൞ non-cacheable • Ⴕ Form ିႨࣼ᾽ਈႨ Form Body
  112. error = Status Meaning invalid_request 400 㢻ἡсေṚ⅂aἡਔ҂ᆞ⃷֥Ṛ⅂
 ᇗ♶ἡṚ⅂aᇗ♶ԛൕ Access Token


    ࠇః෰ჰၹẹᇁ↥مࢳồb invalid_token 401 Access Token Ἶ௹aФӜ߭a↥مࢳồb Client ॖၛᇗྍണ⃪၂ἠ Token ᄜℷb insufficient_scope 403 Token ֥ scope ⃴ཋ҂ቀb Error ॖၛڸഈ scope= ῲิൕ෮ླ⃴ཋb
  113. HTTP/1.1 401 Unauthorized
 WWW-Authenticate: Bearer realm="The API"
 error="invalid_token"
 error_description="Token is

    not usable." HTTP/1.1 403 Forbidden
 WWW-Authenticate: Bearer realm="The API",
 error="insufficient_scope",
 error_description="Scope not sufficient.",
 scope="friend_list photo"
  114. Token Refresh • ଦ Access Token ނứℭ֥ Refresh Token ಀ㍤ứ

    • ჰЧ㢻Ⴕứ Refresh Token đࣼ҂ି㍤ứ • POST ֞ Token Endpoint
  115. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=refresh_token
 
 &refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
 
 &scope=search_timeline
  116. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=refresh_token
 
 &refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
 
 &scope=search_timeline Token Endpoint
  117. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=refresh_token
 
 &refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
 
 &scope=search_timeline Token Endpoint Client Authentication
  118. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=refresh_token
 
 &refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
 
 &scope=search_timeline Token Endpoint іൕw໡ Client ေ㍤ứྍ֥ Tokenx Client Authentication
  119. POST /token HTTP/1.1
 Host: oauth.example.com
 Authorization: Basic YWJjOjEyMw==
 Content-Type: application/x-www-form-

    urlencoded
 
 grant_type=refresh_token
 
 &refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
 
 &scope=search_timeline Token Endpoint іൕw໡ Client ေ㍤ứྍ֥ Tokenx Client Authentication scope ॖസ੻đ҂ॖնᧄ
 Access Token ണ⃪Ἶ֥⃴ཋ
  120. Service spec ཌྷಸ ᆦჱ֥ Grant Types scope ٳۯ Refresh Token

    Client ⃾⊈ Facebook ✕ Auth Code, Implicit, Client Cred. comma △ (ሱ⚧) GET GitHub ✕ Auth Code, Password (ሱ⚧) comma ✕ POST Twitter ̋ Client Cred. (↥ scope) ✕ Basic Google ✕ Auth Code, Implicit space ̋ POST Microsoft ✕ Auth Code, Implicit ĤĤĤ ̋ POST Dropbox ̋ Auth Code, Implicit (↥ scope) ✕ Basic, POST Amazon ̋ Auth Code, Implicit space ̋ Basic, POST Bitly ✕ Auth Code (϶ሱ⚧), Password (↥ scope) ✕ POST (Auth Code), Basic (Password) ྍশັѰ ✕ Auth Code comma ✕ Basic, GET ׸ϵ ✕ Auth Code, Implicit comma ̋ POST BOX ✕ Auth Code (↥ scope) ̋ POST Basecamp ✕ Auth Code (↥ scope) ̋ POST
  121. ⦁ದᄸ喁ቓč҂ݺ֥ٚ૫Ď ✘ ్ Scope ޓ؟ದႨ `,` ✘ Client ⃾⊈҂ᾖ֤׻ᆦჱ HTTP

    Basic Auth ✘ Bearer Token ҂၂ק൞Ⴈ
 “Bearer” Authorization Header
  122. Ⴕ Spec ॖၛ Follow ࣼ Follow ✔ ్ Scope Ⴈॢ۬

    ✔ Client ⃾⊈ᇀഒေᆦჱ Basic Auth ✔ Bearer Token ࣼႨ
 “Bearer” Authorization Header
  123. Client Registration (CRUD) • id • secret čℶ㬪ૡĎ • Redirect

    URI ّᆞ҂൞ἡದὸ֥ ෮ၛള⁙ࣼྛ } ← ေ౰ Developer ൙༵ᆷק
  124. Authorization Endpoint • ๙ӈῘᄝᇶᅟđٚьᆰࢤ⃸ User Ⴈ Cookie ֨ೆ • ⚧ቔ၂ἠ

    Dialog ⃸ User 㢯קေ҂ေᄍ⇝൱⃴ • User ߭ճᆭᗥđRedirect ߭ Client • ὜ Redirect ߭ Client đ෮ၛေ༵⃷Ќ Client ᆞ⃷
  125. Authorization Endpoint halt if !(client_id and redirect_uri matches) error(invalid_scope) if

    !(valid_scope?) error(unsupported_response_type)
 if !(valid_response_type?) # other errors (incomplete pseudo code)
  126. Authorization Endpoint result = ask_user_for_authorization! if result == Authorized then


    if response_type == Code
 callback_params = generate_grant_code()
 else if response_type == Token
 callback_params = generate_token() else if result == Denied then
 callback_params = generate_error_code(access_denied)
  127. Token Endpoint authorize_client! or error(invalid_client) verify_redirect_uri! or error(invalid_request) error(invalid_scope) if

    scope_given and !valid_scope? # other errors token = issue_token(expires_in: 30.days) token_response_by_json(token)
  128. “Resource Server Guard” fetch_token(from: header, form, query) error(401) if !(token_given?)

    error(400) if !(token_decodable?) error(invalid_token) if expired? or revoked? error(insufficient_scope) if scope_sufficient? yield to API
  129. ֻ၂Ցč੻Ďࣼഈ൭ • Ⴈ Devise ള User (Resource Owner) • Ⴈ

    Doorkeeper ἒ Authorization Server • Ⴈ Grape ἒ API (Resource Server) • ሱ࠭ख़ Resource Server Guard ῲ⅞ API
  130. Why ሱ࠭ख़ Guard • doorkeeper_for ൞ Rails-Only • Rack::OAuth2 ປӮ؇ޓۚđ֌с⇜ሱ࠭ᆜކ

    • Warden::OAuth2 ۵ Devise वᄝ၂ఏ໡҂὜ࢳ • Grape::Middleware::Auth::Oauth2 ۴Ч㢻ቓປ ✔ Best Choice
  131. ᄯ API class SecretAPI < Grape::API
 namespace "secret"
 format :json


    get "hello" do
 {
 greeting: "Hi,#{current_user.email}"
 }
 end
 end
  132. Ῐ Authorization Server $ gem install doorkeeper
 $ rails g

    doorkeeper:install
 $ rails g doorkeeper:migration
 $ rake db:migrate
  133. ℟ק⃾⊈ Resource Owner ֥ٚൔ # ⃾⊈ Resource Owner ֥ٚمđᆰࢤࢤ Devise


    resource_owner_authenticator do
 current_user ||
 warden.authenticate!(:scope => :user)
 end config/initializers/doorkeeper.rb ※ Ӓܲٚ໓ࡱ
  134. New Tables • oauth_application - Clients Registration • oauth_access_grant -

    Stores Auth Grant Codes • oauth_access_token -
 ᆇᆞނứԛಀ֥ Access Tokensđ
 ЇݣỚ∣֥ Refresh Token č≁℟ἬṅĎ
  135. New Routes Action(s) Path Ⴈ๯ new /oauth/authorize Authorization Endpoint create

    /oauth/authorize User ⇝ॖ൱⃴ℭ֥ action destroy /oauth/authorize User ऋ䌉൱⃴ℭ֥ action show /oauth/authorize/:code Local ṦℷႨ update /oauth/authorize Ĥ create /oauth/token Token Endpoint show /oauth/token/info Token Debug Endpoint resources /oauth/applications Clients ܵ৘ࢸ૫ (CRUD) index /oauth/authorized_applications User ܵ৘൱⃴Ἶ֥ Clients destroy /oauth/authorized_applications/:id
  136. Doorkeeper Built-In™ ✔ Authorization Endpoint & Token Endpoint ✔ Token

    Debug Endpoint
 čᄝ Implicit Flow ⇼⊈ Token ֥ᆇℯྟĎ ✔ Client Registration Interface (CRUD) ✔ User ܵ৘൱⃴Ἶ֥ Clients ֥ࢸ૫čॖ RevokeĎ
  137. Building Resource Server Guard • Fetch Access Token via Rack::OAuth2

    • Find Access Token from Model • Validate if Token is not Expired && not Revoked • Validate if Token has Sufficient Scopes • If All Valid, Pass to Grape API
  138. Fetch Access Token via Rack::OAuth2 • use Rack::OAuth2::Server::Resource::Bearer • ൙ℯഈᆺἌ≡Ϝ

    yield ԛῲ֥ Token թᄝଖẕ • ೂݔ Request ҂ầ Token ࣼᆰࢤ Pass ֞༯ἠ stack • ෮ၛ໡ᆺଦ෱ῲ Fetch Token
  139. included do |base|
 # OAuth2 Resource Server Authentication
 use Rack::OAuth2::Server::Resource::Bearer,


    'The API' do |request|
 # Authenticator only fetches the raw token string
 
 # Must yield access token to store it in the env
 request.access_token
 end
 end
  140. def validate(token, scopes: [])
 if token.expired?
 return EXPIRED
 
 elsif

    token.revoked?
 return REVOKED
 
 elsif !self.sufficent_scope?(token, scopes)
 return INSUFFICIENT_SCOPE
 
 else
 return VALID
 end
 end Token#expired?, Token#revoked?
 ൞ Doorkeeper ⤨ࡹ֥
  141. def sufficent_scope?(token, scopes)
 if scopes.blank?
 # no scope required =>

    any token is valid
 return true
 else
 # scopes required
 #=> Check sufficiently by Set comparison
 required_scopes = Set.new(scopes)
 authorized_scopes = Set.new(token.scopes)
 
 return authorized_scopes >= required_scopes
 end
 end ≾൞ቋᾏẪ֥ࠢކбᾱ ୆ॖၛ၇ླ౰ℯቔဆෘم
  142. ቓ guard! ᄝ Grape 䥰૫Ẳᇾ class SecretAPI < Grape::API
 get

    "hello" do
 guard!
 {
 greeting: "Hi,#{current_user.email}"
 }
 end
 end
  143. def guard!(scopes: [])
 token_string = get_token_string()
 
 if token_string.blank?
 raise

    MissingTokenError
 
 elsif (
 access_token = find_access_token(token_string)
 ).nil?
 raise TokenNotFoundError (in helpers block)
  144. def guard!(scopes: [])
 token_string = get_token_string()
 
 if token_string.blank?
 raise

    MissingTokenError
 
 elsif (
 access_token = find_access_token(token_string)
 ).nil?
 raise TokenNotFoundError ༵ሂԛ Token String (in helpers block)
  145. def guard!(scopes: [])
 token_string = get_token_string()
 
 if token_string.blank?
 raise

    MissingTokenError
 
 elsif (
 access_token = find_access_token(token_string)
 ).nil?
 raise TokenNotFoundError ༵ሂԛ Token String ሂ֥֞൞ॢሳԱđіൕ㢻ἡ Token (in helpers block)
  146. def guard!(scopes: [])
 token_string = get_token_string()
 
 if token_string.blank?
 raise

    MissingTokenError
 
 elsif (
 access_token = find_access_token(token_string)
 ).nil?
 raise TokenNotFoundError ༵ሂԛ Token String ሂ֥֞൞ॢሳԱđіൕ㢻ἡ Token Ⴕἡ֌ᅳ҂֞đ൞ Invalid Token (in helpers block)
  147. else
 case validate_access_token(access_token, scopes)
 when Oauth2::AccessTokenValidationService
 ::INSUFFICIENT_SCOPE
 raise InsufficientScopeError.new(scopes)
 when

    Oauth2::AccessTokenValidationService::EXPIRED
 raise ExpiredError
 when Oauth2::AccessTokenValidationService::REVOKED
 raise RevokedError
 when Oauth2::AccessTokenValidationService::VALID
 @current_user = User.find(access_token
 .resource_owner_id)
 ennnd
  148. else
 case validate_access_token(access_token, scopes)
 when Oauth2::AccessTokenValidationService
 ::INSUFFICIENT_SCOPE
 raise InsufficientScopeError.new(scopes)
 when

    Oauth2::AccessTokenValidationService::EXPIRED
 raise ExpiredError
 when Oauth2::AccessTokenValidationService::REVOKED
 raise RevokedError
 when Oauth2::AccessTokenValidationService::VALID
 @current_user = User.find(access_token
 .resource_owner_id)
 ennnd Scope ҂ژ
  149. else
 case validate_access_token(access_token, scopes)
 when Oauth2::AccessTokenValidationService
 ::INSUFFICIENT_SCOPE
 raise InsufficientScopeError.new(scopes)
 when

    Oauth2::AccessTokenValidationService::EXPIRED
 raise ExpiredError
 when Oauth2::AccessTokenValidationService::REVOKED
 raise RevokedError
 when Oauth2::AccessTokenValidationService::VALID
 @current_user = User.find(access_token
 .resource_owner_id)
 ennnd Scope ҂ژ Ἶ௹ਔ
  150. else
 case validate_access_token(access_token, scopes)
 when Oauth2::AccessTokenValidationService
 ::INSUFFICIENT_SCOPE
 raise InsufficientScopeError.new(scopes)
 when

    Oauth2::AccessTokenValidationService::EXPIRED
 raise ExpiredError
 when Oauth2::AccessTokenValidationService::REVOKED
 raise RevokedError
 when Oauth2::AccessTokenValidationService::VALID
 @current_user = User.find(access_token
 .resource_owner_id)
 ennnd Scope ҂ژ Ἶ௹ਔ Ӝ⇍ਔ
  151. else
 case validate_access_token(access_token, scopes)
 when Oauth2::AccessTokenValidationService
 ::INSUFFICIENT_SCOPE
 raise InsufficientScopeError.new(scopes)
 when

    Oauth2::AccessTokenValidationService::EXPIRED
 raise ExpiredError
 when Oauth2::AccessTokenValidationService::REVOKED
 raise RevokedError
 when Oauth2::AccessTokenValidationService::VALID
 @current_user = User.find(access_token
 .resource_owner_id)
 ennnd Scope ҂ژ Ἶ௹ਔ Ӝ⇍ਔ ׻ OK ࣼ℟ current_user
  152. def oauth2_bearer_token_error_handler
 Proc.new {|e|
 response = case e
 when MissingTokenError


    Rack::OAuth2::Server::Resource
 ::Bearer::Unauthorized.new
 when TokenNotFoundError
 Rack::OAuth2::Server::Resource
 ::Bearer::Unauthorized.new(
 :invalid_token,"Bad Access Token.")
 # etc. etc.
 end
 response.finish
 }
 end (in ClassMethods module)
  153. guard_all! class SecretAPI < Grape::API
 guard_all!
 get "hello" do
 {


    greeting: "Hi,#{current_user.email}"
 }
 end
 end
  154. $ curl -i http://localhost:3000/api/v1/sample/secret
 HTTP/1.1 401 Unauthorized
 WWW-Authenticate: Bearer realm="The

    API"
 Content-Type: application/json
 Cache-Control: no-cache
 {"error":"unauthorized"}
  155. $ curl -i http://localhost:3000/api/v1/sample/secret \
 > -H "Authorization: Bearer XXXXXXXX"


    HTTP/1.1 401 Unauthorized
 WWW-Authenticate: Bearer realm="Protected by OAuth 2.0", error="invalid_token", error_description="Token is expired. You can either do re-authorization or token refresh."
 Content-Type: application/json
 Cache-Control: no-cache
 {"error":"unauthorized"} č⁙แ TokenĎ
  156. Final Notes • Doorkeeper ≁℟㢻Ⴕ⅞Ῐ Client ֥⃴ཋđ୆ὸ֤ေ⅞ • Doorkeeper ҂ିᆷקᆺῘଧུ

    Flows
 ໡Ῐਔ PR ὕ㢻 merge… • 㢻Ⴕྩ insufficient_scope Error
 ಌ WWW-Authenticate ֥↜ⅳ
  157. Conclusion • OAuth 2 Spec ồປҌ὜ᆩ֡෰ᄝἓખ • ồປ Spec →

    ෮Ⴕ API ෮Ⴕ Library ୆׻ु֤׭ • ሱ࠭ᆜކ Grape ބ OAuth 2 ఃℯ㢻Ⴕޓₒ
 ᆺေ׭ Spec ࣼ҂ₒ…
  158. References • RFC 6749 (Spec) tools.ietf.org/html/rfc6749 • RFC 6750 (Spec)

    tools.ietf.org/html/rfc6750 • My Notes: blog.yorkxin.org/tags/OAuth • Many OAuth2-based API Documents