Tìm hiểu OAuth với OpenID Connect

  • Thật tuyệt vời khi đăng nhập vào ứng dụng web hay app mobile (ví dụ: Trello) bằng thông tin đăng nhập và thông in của bạn đã được lữu trữ nơi khác chẳng hạn như Google? hay Facebook?. Vâng đúng vậy OAuth2OpenID Connect chúng mang lại cho chúng ta cảm giác thật tuyệt phải không, vì chúng ta đâu có cần phải nhập lại mật khẩu đôi khi còn quên hay một số thông tin cơ bản để truy cập để sử dụng dịch vụ trong cùng một phiện làm việc.

  • Chúng ta sẽ đi ìm hiểu 2 thằng này nó hoạt động ra sao nhé. Trước tiên chúng ta cùng xem trước thằng OAuth2 nó hoạt động ra sao trước rồi tới thằng OpenID Connect . VÌ OpenID Connect nó được phát triển từ OAuth2 mà.

I. OAuth2

1. Vậy nó OAuth2.0 nó là gì

OAuth2.0 là giao thức cho phép người dùng cấp quyền truy cập hạn chế tài nguyên của họ trên một web site, đến một web site khác mà không tiết lộ thông tin đăng nhập của họ.

The như OAuth‘s website giao thức không giống khóa valet:

Có rất nhiều con luxury cá ngày này đi kèm với một chìa khóa valet. Đó là một chia khóa đặc biệt mà bạn cung cấp cho nhân viễn đỗ xe và không giống với chìa khóa thông thường của bạn, nó sẽ không cho phép của bạn đi quá 1 dăm hay 2 dặm được. Một số phím trên khóa cũng không mở, trong khi một số thì chặn truy cập thông tin của bạn. Bạn trao cho ai đó quyền truy cập vào chiếc xe của bạn và bị hạn chế một sô quyền ,trong khi bạn thân bạn thì chỉ cần khóa thông thường là có thể mở toàn bộ.

  • Để có quyền truy cập vào các tài nguyên được bảo vệ, OAuth2.0 đã sử dụng access token, nó là một chuỗi đại diện cho các quyền truy cập.

    • Access Token format bởi mặc định access token được sinh ra cho việc Authorization ở định dạng JWT. JWTs gồm có 3 thành phần: header, playload và signature
      1. Header thì chứa metadata về loại thông báo và thuật toán mã hóađẻ bảo mật nội dung của nó.
      2. Payload chứa một tập yêu cầu, yêu cầu về quyền nên được cho phép và các thông tin khác như đối tượng dự định và thời gian hết hạn.
      3. Signture được sử dụng để xác thực mã thông báo đáng tin cậy hay không bị làm giả.
  • Quyền truy cập đươc đại diện bởi access token, trong OAuth 2.0 gọi là scope. Khi một ứng dụng muốn xác thực với Auth, nó sẽ chỉ định scope nó muốn. Nếu các scope này được người dùng ủy quyền thì access token sẽ được đại diện cho scope được ủy quyền này.

  • Ví dụ : Contact API có thể châp nhận 3 câp ủy quyền khác nhau thì scope : read:contacts, create:contacts, delete:contacts.

  • OAuth roles Trong bất kỳ flow OAuth2.0 chúng tôi có thể xác định roles sau:

    1. Resource Owner: là thực thể có quyền truy cập vào tài nguyên thưowngf là enduser.
    2. Resource Server: Máy chủ lữu trữ các tài nguyên, đây chính là API mà bạn muốn truy cập.
    3. Client: Đây là app bên thứ 3 muốn truy cập vào tài nguyên được bảo vệ thay mặt cho Resource Owner.
    4. Authorization Server: Máy chủ xác thực Resource Owner và phát hành access token sau khi nhận đươc sự ủy quyền.

2. Protocol flow

Bây giờ chúng ta sẽ có cái nhìn chi tiết về cách giao thức hoạt động Nó hoạt động bằng cách ủy quyền xác thực người dùng cho dịch vụ lữu trữ tài khoản người dùng. Để mọi người dễ hình dùng luồng hoạt động thì hay nhìn hình sau:

  1. Ứng dụng (Khách hàng) yêu cầu ủy quyền từ Chủ sở hữu tài nguyên để truy cập tài nguyên.

  2. Với điều kiện Chủ tài nguyên cho phép quyền truy cập này, Ứng dụng sẽ nhận được Cấp phép. Đây là một chứng chỉ đại diện cho ủy quyền của Chủ sở hữu tài nguyên.

  3. Ứng dụng yêu cầu Mã thông báo truy cập bằng cách xác thực với Máy chủ ủy quyền và cấp Cấp quyền.

  4. Với điều kiện Ứng dụng được xác thực thành công và Cấp phép ủy quyền hợp lệ, Máy chủ ủy quyền sẽ phát hành Mã thông báo truy cập và gửi đến Ứng dụng.

  5. Ứng dụng yêu cầu quyền truy cập vào tài nguyên được bảo vệ bởi Máy chủ tài nguyên và xác thực bằng cách hiển thị Mã thông báo truy cập.

  6. Với điều kiện Mã thông báo truy cập hợp lệ, Máy chủ tài nguyên sẽ phục vụ yêu cầu của Ứng dụng.

Các loại cấp phép


  • Ví dụ như khi bạn truy cập vào website thương mại điện tử ở form tạo account nó có button sign in with facebook
  <%= link_to "Sign in with facebook", %q(https://www.facebook.com/v3.2/dialog/oauth?client_id=#{your_app_id]}&scope#{your_app_permissions}&redirect_uri=#{redirect_uri}"), class:  "btn btn-primary"%>

Như các bạn thấy thì để button hoạt động thì cần có tham số bắt buộc như :

  • client_id app_id cái này khi bạn đã có account thì sẽ có cái này nhưng phải vào facebook for developers của bạn mới xem được.
  • scope cái này chỉ định quyền truy cập vào email, name, số điện thoại.. mà app muốn yêu cầu từ bạn.
  • redirect_uri Sau khi bạn xác nhận quyền truy cập ( permissions) tức là khi bạn kết thúc quá trình ủy quyền của facebook và đấy chính là nó.

Tham só scope thì không bắt buộc phải có nhưng 2 tham số client_idredirect_uri thì bắt buộc.

Khi bạn vào website đăng nhập với facebook thì website này sẽ yêu cầu được trao quyền để láy các thông tin như email, username.. trên facebook của bạn. Lúc này website thưc hiện việc này băng cách chuyển tiếp người dùng về trang facebook service provider.

https://www.facebook.com/v2.8/dialog/oauth?response_type=token&display=popup&client_id=145634995501895&redirect_uri=https%3A%2F%2Fdevelopers.facebook.com%2Ftools%2Fexplorer%2Fcallback&scope=email

Như trên là một ví dụ. Trên trang của người dùng Facebook service provider đồng ý trao quyền (Màn hình request permission)

Sau khi bạn châp nhận trao quyền thì facbook sẽ tạo cho bạn một access token cho website trên. Sau khi có được access token vừa có được thì website này sẽ gửi request cho Facebook để lấy cá thông tin của bạn mà được cho phép truy cập.

  1. Có thể nôm na như thế này khi bạn đăng nhập tài khoản facebook (giả sử bạn đã có account facebook nhé ) với ứng dụng bên thứ 3 thì nó sẽ yêu cầu trao cho nó quyền truy cập để sử dụng một số tài nguyên của bạn như: email, avatar... .
  2. Ứng dụng bên thứ 3 sẽ chuyển đến login dialog của facebook, lúc này tạo một reuquest gửi lên gồm có Application IDApplication secret (Khi bạn có account facebbook thì sẽ ) . Tất nhiên là khi đến đây sẽ yêu cầu bạn phải đăng nhập h nếu phiên làm viêc còn thì sẽ hiển thị một số quyền cho bạn, khi đo bạn sẽ đồng ý được truy cập vào những thông tin nào.
  3. Khi bạn chấp nhận quyền truy cập nó sẽ trở lại ứng Facebook sẽ trao cho bạn một acess token đế lấy các thông tin từ hồ sơ của bạn.

II. Open ID Connect

  1. OnpenID Connect là một lớp nhận dang đơn được phát triển dựa trên giao thức OAuth2.0, cho phép client xác định định danh của enduser dựa trên xác thực được thực hiện bởi máy chủ authorization hoặc identity provider (IdP) cũng như để có được thông tin enduser theo cách giống như RESTfull HTTP. OnpenID Connect chỉ đinh API HTTP RESTfull sử dụng JSON làm đinh dạng dữ liệu.

  2. Nó là giao thức ngày càng phổ biến. Mỗi khi ứng dụng nhắc chúng ta đăng nhập với Facebook hoặc Google thì ứng dụng đó có thể OpenID Connect

  3. Hỗ trợ khá nhiều client bao gồm web based, mobile, Javascript client để yêu cầu và nhận các thông tin về phiên xác thực và endusers.

  4. OneLogin cung cấp tùy chọn kết nối dễ dàng tùy chỉnh cấu hình ứng dụng. OpenID Connect của bạn có thể sử dụng OneLogin là nhà cung cấp nhận dạng (IDP) trong luông hoạt động của OpenId Connect.

Các bước cơ bản của giao thức:
  • (A) Người dùng sẽ truy cập bên thứ ba và yêu cầu truy cập.
  • (B) Bên thứ 3 gửi authentication request cho OpenID provider, mô tả scope sẽ được yêu cầu và response_type muốn nhận được.
  • (C)OpenID provider yêu cầu user xác nhận danh tính sau đó sẽ cho phép bên thứ 3 các quyền trong scope
  • (D) OpenID provider gửi lại bên thứ 3 authentication Response chứa thông tin muốn ở bước (A) thương sẽ là ID Token và Access Token.
  • (E, F) Bên thứ 3 sẽ dùng access token để trao đổi thông tin mà mình mong muốn.

OpenID Connect Authorization flow
  1. Code Flow

    • Người dùng yêu cầu đăng nhập vào ứng dụng bên thứ 3 (trello, lazada...)
    • Bên thứ 3 sẽ redirect đến OpenID provider( lúc này người dùng cung câp các thông tin để xác thức đây là tao), kèm theo đó là thông tin như:

    client_id: mã đăng ký đinh danh với OpenID provider

    scope: quyên mà bên thức 3 được cấp

    response_type: code

    redirect_uri: Nếu xác thực thành công thì bên OpenId provider sẽ redirect lại bên app thứ 3

    • OpenId provider render trang đăng nhập và yêu cầu cấp quyền. Nếu thành công sẽ quay trở lại uri ở bước 2 kem theo đó authorization code. Bên thứ 3 sẽ gửi request cùng với token. Đây là lý do mà response_type là code ở bước 2.
    • Lúc này người dùng đã qua lại ứng dụng bên thứ 3 đã được xác thực thành công. Sẽ lại gửi một request tới OpenId provider với dữ liệu gồm code, grant_type(chỉ định dang xác thực/ đăngký ).Nếu thành công thì OpenId provider trả lại ID Token có thể kèm theo access token.
    • Bên thứ 3 sẽ xác thực lại ID Token thành công thì có thể truy cập vào để lấy dữ liệu từ resource server.

2. Implicit Flow, Password Flow

  • Flow này cũng giống bước 1và 2.
  • Tại bước 3 cũng tương tự nhưng response_type: id_token (và token). Ở flow này thì không yêu cầu xác thực một cách tường minh như bước 4 ở trên nên nó mới có tên Implicit flow. Điểm khác nữa của implicit flow là token trả về cho client được gắn vào phần fragment (hay hash) của callback url chứ không phải query.
  1. Hybrid Flow
  • Các bước của flow này hoàn toàn giống với authorization code flow. Ngoại trừ response_type gửi đi ở authentication request (bước 2) là code và id_token để lấy ID token và hoặc token để lấy access token hoặc cả 3. Sau đó OpenId provider trả lại authorization code và id token để gửi token request như bước 4. Bên thứ 3 nhận được authentication response sẽ có access token để sử dụng đồng thời vẫn có authorization code để trao đổi lấy refresh token để dùng dài lâu (chú ý rằng vòng đời của access token là khá ngắn, chỉ vài chục phút).

3. Example OpenID authentication

Ví dụ chuyển hướng xác thực cho OP:

Bây giờ chúng ta sẽ thông qua một ví dụ xem làm thế nào nhận được ID Token từ OpenID Connect băng cách sử dụng authorisation code flow khá thông dụng

Bước 1 Bước 2
Purpose 1. Authenticate user 2. Receive user consent 1. Authenticate client (optional) 2. Exchange code for token(s)
Via Front-channel request (browser redirection) Back-channel request (app to web server)
To Authorisation endpoint Token endpoint
Result on success Authorisation code ID token
  • Code flow: bước 1

Bên thứ 3 bắt đầu xác thực người dùng bằng cách chuyển hướng trình duyệt đến điểm cuối ủy quyền OAuth 2.0 của OpenID Provider. Yêu cầu xác thực OpenID về cơ bản là yêu cầu ủy quyền OAuth 2.0 để truy cập danh tính người dùng, được biểu thị bằng giá trị openid trong tham số scope.

HTTP/1.1 302 Found
Location: https://openid.c2id.com/login?
          response_type=code
          &scope=openid
          &client_id=s6BhdRkqt3
          &state=af0ifjsldkj
          &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb

Các tham số yêu cầu được mã hóa trong truy vấn URI:

  1. answer_type: Thiết lập code để chỉ ra luồng mã ủy quyền.

  2. scope Được sử dụng để chỉ định phạm vi ủy quyền được yêu cầu trong OAuth. Giá trị phạm vi openid báo hiệu một yêu cầu xác thực OpenID và mã thông báo ID.

  3. client_id Mã định danh khách của bên thứ 3 tại OpenID Provider . Mã định danh này được chỉ định khi bên thứ 3 được đăng ký với OpenID Provider , thông qua API đăng ký máy khách, bảng điều khiển dành cho nhà phát triển hoặc một số phương pháp khác.

4.'state Giá trị mờ được đặt bởi bên thứ 3 để duy trì trạng thái giữa yêu cầu và gọi lại.

  1. redirect_uri URI gọi lại bên thứ 3 cho phản hồi xác thực.

Tại OpenID Provider , người dùng thường sẽ được xác thực bằng cách kiểm tra xem họ có phiên hợp lệ không (được thiết lập bởi cookie trình duyệt) và trong trường hợp không có điều đó, bằng cách nhắc người dùng đăng nhập. Sau đó, người dùng thường sẽ được hỏi liệu họ có đồng ý đăng nhập vào bên thứ 3 hay không.

OpenID Provider sau đó sẽ gọi cho máy khách redirect_uri bằng mã ủy quyền (khi thành công) hoặc mã lỗi (nếu quyền truy cập bị từ chối hoặc một số lỗi khác xảy ra, yêu cầu không đúng định dạng đó đã được phát hiện).

HTTP/1.1 302 Found
Location: https://client.example.org/cb?
          code=SplxlOBeZQQYbYS6WxSbIA
          &state=af0ifjsldkj
  • Code flow: bước 2

OpenID Provider phải xác thực tham số state và sử dụng code để tiến hành bước tiếp theo - trao đổi code cho ID token.

Authorisation code là một thông tin trung gian thu được từ bước 1. Do đó nó không mấy hưu ích với bên thứ 3 mà chỉ có ý nghĩa với OpenID Provider. Để lấy lại ID Token, bên thứ 3 phải gửi mã cho OpenID Provider, nhưng lần này với yêu cầu kênh ngược trực tiếp. Điều này được thực hiện vì hai lý do:

  1. Để xác thực khách hàng bí mật với OpenID Provider trước khi tiết lộ mã thông báo;

  2. Để phân phối mã thông báo trực tiếp đến bên thứ 3 , do đó, tránh để lộ chúng ra trình duyệt.

Việc trao đổi code-for-token xảy ra tại token endpoint của OpenID Provider:

POST /token HTTP/1.1
Host: openid.c2id.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

grant_type=authorization_code
 &code=SplxlOBeZQQYbYS6WxSbIA
 &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb

ID Khách hàng và truyền bí mất thông qua Authorization header. Ngoài xác thực cơ bản HTTP, OpenID Connect còn hỗ trợ JWT, không tiết lộ thông tin xác thực ứng dụng khách với yêu cầu token request, đã hét hạn và do đó bảo mật hơn.

Các tham số yêu token request được mã hóa theo mẫu sau:

  1. grant_type gán giá trị authorization code.
  2. code thu được từ bước 1.
  3. redirect_uri lặp lại uri ở bước 1

Khi thành công OpenID Provider trả về Object JSON:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc
    yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5
    NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ
    fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz
    AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q
    Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ
    NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd
    QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS
    K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4
    XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg"
  "access_token": "SlAV32hkKG",
  "token_type": "Bearer",
  "expires_in": 3600,
}

Tóm lại OpenID thì về xác thực (Sử dụng thông tin đăng nhập từ OpenID provider để đăng nhâp ứng dụng thứ 3) còn OAuth là ủy quyền cho phép ứng dụng bên thứ 3 truy cập thông tin. Về cơ bản thì Flow của OpenId Connect giống như quy trình ủy quyển OAuth 2.0 nhưng vẫn có điểm khác như:

  • Ngoài access-token thì authorization server còn trả về Id-token
  • Có thể truyền thêm scope khi call Authorization server
  • Id-token chưa thông tin người dùng đã được xác thực

OpenId Connect tiêu chuẩn khá nhiều thứ mà OAuth2.0 lại là sự lựa chọn như có thể đinh nghĩa cụ thể quyên truy cập vào username, email.. đại loại rất chi tiết, endpoint discovery, đăng ký khá linh động cho client. Điều này giúp nhà phát triển để người dùng có nhiều lựa chon nhà cung cấp nhận dạng.

Link tham khảo

https://stackoverflow.com/questions/1087031/whats-the-difference-between-openid-and-oauth https://developers.onelogin.com/openid-connect https://digimed.vn/2017/05/30/openid-connect-1-0-cho-nguoi-moi-bat-dau/ https://connect2id.com/learn/openid-connect http://techastute.blogspot.com/2012/05/openid-authentication-oauth.html

All Rights Reserved