- vừa được xem lúc

Web Sign-In with OpenID Connect

0 0 5

Người đăng: Nguyễn Nam Thắng

Theo Viblo Asia

Ở bài trước chúng ta đã tìm hiểu về Roles and Grants of OAuth2 and OIDC rồi, trong bài ngày hôm nay hãy đi vào với kịch bản phổ biến nhất là Web Sign-In.

Trước khi thực sự đi vào cơ chế của nó, tôi phải giới thiệu vài khái niệm và thuật ngữ mà chúng ta sử dụng trong bối cảnh OAuth2 và OpenID Connect. Đặc biệt, tôi muốn nói về Confidential Client.

Confidential client trong OAuth2 là bất kỳ ứng dụng nào mà authorization server có thể gán một thông tin xác thực nào đó (client_id, client_secret) - điều này cho phép ứng dụng chứng minh danh tính của nó như là một registered client trong bất kỳ yêu cầu nào.

  • Client này phải được đăng ký với authorization server trước khi nó được đưa vào hoạt động.

The Implicit Grant with form_post

Grant mà chúng ta sẽ sử dụng ở đây là implicit grant với formpost. Đây là cách dễ nhất để đạt được Web Sign-In sử dụng OpenID Connect và nó thực sự giống với SAML. Thực tế, nó cơ bản tuân theo các bước tương tự mà tôi đã mô tả khi tôi giới thiệu luồng SAML trong bài đầu tiên, Giới thiệu về Digital Identity.

Grant này cho phép một điều mà chỉ OpenID Connect mới có thể làm, đó là kết hợp việc đăng nhập vào một trang web với việc cấp quyền cho trang web đó để truy cập API trong tương lai. Những gì chúng ta sẽ làm bây giờ là nghiên cứu một nửa của giao dịch đó, nghĩa là sẽ chỉ xem phần đăng nhập. Khi chúng ta nói về APIs, chúng ta sẽ xem nửa còn lại.

  • Hai nửa đó có thể được kết hợp để trải nghiệm cho người dùng thực sự mượt mà. Ngoài ra, về mặt thiết kế, việc kết hợp đăng nhập và khả năng gọi API cho phép một ứng dụng đóng nhiều vai trò. Đây là một kịch bản rất mạnh mẽ mà trước khi OpenID Connect được giới thiệu, thì không thể thực hiện được.

Về cơ bản, bạn cần đăng ký client của mình ở authorization server và thiết lập endpoint để nhận token được trả về từ authorization server. Sau đó bạn chỉ cần thiết lập một middleware trước ứng dụng của mình và trỏ nó đến discovery endpoint mà mình đã đề cập đến trong bài Roles and Grants of OAuth2 and OIDC.

A detailed walkthrough

Giả sử chúng ta có một người dùng với một trình duyệt, một ứng dụng web được bảo vệ bởi một middleware triển khai OpenID Connect, và một authorization server.

Hãy xem chi tiết cách implicit grant với form_post hoạt động.

image.png

Ý tưởng là, ngay khi ứng dụng web này hoạt động, middleware sẽ liên hệ với discovery endpoint và học tất cả những gì nó cần biết về authorization server. Đặc biệt, nó sẽ nhận được địa chỉ của authorization endpoint và key để kiểm tra chữ ký.

(1): Yêu cầu Đường dẫn được bảo vệ trên Web App

Trong bước đầu tiên, khi bạn truy cập vào ứng dụng web với một path cụ thể, và tình cờ nó được bảo vệ nên không thể truy cập bởi các yêu cầu ẩn danh.

(2): Authorization Request Redirect

Middleware chặn cuộc gọi này và tạo ra một authorization request gửi đến cho authorization server. HTTP response có một mã trạng thái HTTP 302, tức là một redirect request, và có một số tham số nhằm truyền đạt đến authorization server tất cả các thông tin cần thiết để thực hiện hoạt động xác thực.

image.png

  • Authorization endpoint: nơi mà authorization server tiếp nhận các authorization request. Trong trường hợp này là https://flosser.auth0.com/authorize
  • Client ID: là định danh của ứng dụng mà bạn đã đăng ký tại authorization server.
  • Response type: Tham số response_type chỉ ra những gì mà chúng ta muốn. Trong trường hợp cụ thể này, tôi muốn đăng nhập, vì vậy tôi cần một ID token. Do đó, giá trị của tham số response_type sẽ là id_token.
  • Response mode: Response mode là cách mà tôi muốn nhận lại các dữ liệu được trả về từ authorization server.
    • Chúng ta có tất cả các lựa chọn mà HTTP cung cấp. Có thể nhận mọi thứ thông qua query string, nhưng điều này thường là một ý tưởng tồi vì các thông tin sẽ được lưu trữ và hiển thị trong lịch sử của trình duyệt.
    • Có thể nhận các thông tin trong một đoạn (fragment), vẫn là một phần của URL nhưng không được truyền đến máy chủ, vì vậy nó không phù hợp trong trường hợp này.
    • Cuối cùng chúng ta có thể nhận thông tin dưới dạng form_post, đó là những gì chúng ta đang sử dụng ở đây.
  • Redirect URI: Tham số redirect_uri có một vai trò rất quan trọng. Nó đại diện cho địa chỉ trong ứng dụng của chúng ta, nơi mà các thông tin hoặc token được authorization server trả về.
    • Giá trị này phải khớp với thông tin mà bạn đăng ký với authorization server.
  • Scope: Tham số scope đại diện cho những thông tin mà tôi yêu cầu từ authorization server. Trong ví dụ trên, chúng ta chỉ định openid, profile, và email, đó là các scopes ám chỉ rằng authorization server cần phát hành một ID Token với những thông tin bổ sung.
    • Nó hơi thừa với chức năng đăng nhập, trên thực tế scope tối thiểu để thực hiện một yêu cầu đăng nhập là openid, những scopes khác thường là những thông tin bổ sung mà client muốn để làm phong phú thêm thông tin người dùng của họ. Chúng ta sẽ tìm hiểu thêm về các scopes dành cho các yêu cầu APIs trong bài tiếp theo.
  • Nonce: Tham số nonce chủ yếu là một mẹo để ngăn chặn token injection, một loại tấn công bảo mật.
    • Tại thời điểm middleware phát hành yêu cầu uỷ quyền đến authorization server, nó tạo ra một chuỗi bất kỳ (nonce) và lưu trữ ở đâu đó (như trong một cookie). Nonce được gửi đến authorization server, và cuối cùng, ID token mà chúng ta nhận lại sẽ có một claim là nonce với giá trị chính xác là những gì chúng ta đã gửi đi. Tại thời điểm đó, tôi sẽ có thể so sánh claim đó với giá trị nonce mà tôi đã lưu trữ, và sẽ tự tin rằng token tôi nhận được là cái được trả về từ authorization server.
    • Nếu chúng ta nhận được một token có một giá trị nonce khác cái mà chúng ta đã gửi (hoặc không có), chúng ta phải kết luận rằng phản hồi đã bị giả mạo và token đã bị tiêm.

(3): Authorization Request

Bước tiếp theo của trình duyệt là tuân thủ chuyển hướng 302 và thực hiện GET tới authorization endpoint với tất cả các tham số mà tôi vừa mô tả.

Từ bây giờ, authorization server sẽ làm bất cứ điều gì nó cho là cần thiết để xác thực người dùng và yêu cầu đồng ý. Cách thức này diễn ra không được OAuth2 hay OpenID Connect quy định. Cơ chế xác thực người dùng, thu thập thông tin xác thực và tương tự là một vấn đề hoàn toàn riêng tư của authorization server, miễn là phản hồi cuối cùng tuân theo định dạng quy định bởi tiêu chuẩn. Bạn có thể có xác thực đa yếu tố, nhiều trang, hoặc chỉ một trang. Không quan trọng, miễn là bạn có kết quả tiêu chuẩn.

(4): Authorization Response

Khi mọi thứ hoạt động, bạn nhận được một HTTP response với mã trạng thái 200. Điều này có nghĩa là bạn đã xác thực thành công với authorization server.

  • Authorization server sẽ thiết lập một cookie đại diện cho session chứng minh bạn đã xác thực thành công. Vì vậy, nếu sau này bạn được chuyển hướng đến authorization endpoint một lần nữa, miễn là session còn hiệu lực thì bạn sẽ không cần phải xác thực lại nữa.

Phần quan trọng khác cần lưu ý ở đây là ID token, cái mà chúng ta đã yêu cầu, nó đang được trả lại như một tham số trong form post. Bạn có thể thấy trong thân của HTML được trả lại, rằng sự kiện JavaScript onload được cấu hình để tự động gửi một form.

(5): Gửi Token đến Ứng dụng

Ngay khi trang được trả lại bởi authorization server được render, nó sẽ gửi form đến ứng dụng của chúng ta. Điều này có nghĩa là ID token yêu cầu cuối cùng được gửi callback endpoint mà bạn đã đăng ký với authorization server trước đó.

(6): Token Validation and Web App Sessions Creation

Những gì xảy ra bây giờ khá giống với những gì đã nghiên cứu trước đó trong kịch bản đăng nhập web trong chương đầu tiên, Giới thiệu về Digital Identity. Ứng dụng nhận ID token và quyết định liệu nó có thích đáng tin cậy hay không theo tất cả các quy tắc tin cậy khác nhau, và những gì nó đã học từ discovery endpoint. Nếu nó hài lòng, ứng dụng sẽ phát hành một HTTP 302 response với cookie của chính nó.

Về cơ bản, sau khi quá trình verify diễn ra thành công, ứng dụng sẽ phát hành một session mới đại diện cho phiên đăng nhập của bạn, chúng ta sẽ không cần phải yêu cầu ID Token từ authorization server nữa miễn là session trên ứng dụng còn hiệu lực.

  • Cuối cùng ứng dụng phát hành một HTTP 302 response, điều này sẽ chuyển hướng trình duyệt đến đường dẫn ban đầu mà nó đã yêu cầu.

Note: Liệu bạn có để ý thấy chúng ta có hai session cookies không? một ở authorization server, một ở client. Vì vậy đừng nhầm lẫn chúng nhé.

(7): Yêu cầu Đường dẫn được Bảo vệ với Authorization

Khi trình duyệt tuân thủ chuyển hướng, chúng ta kết thúc tại nơi đã bắt đầu: chúng ta đang yêu cầu một đường dẫn được bảo vệ, nhưng lần này chúng ta đính kèm thêm session cookie.

(8): Yêu cầu Đường dẫn được Bảo vệ với Authorization

Chúng ta có thể nhận được phản hồi HTTP 200 response. Từ bây giờ trở đi, mọi yêu cầu tiếp theo đối với ứng dụng sẽ mang theo session cookie, chứng minh rằng bạn đã được xác thực.

Anatomy of an ID Token

Như chúng ta đã thảo luận trước đó, ID token là một hiện vật chứng minh rằng một xác thực thành công đã xảy ra. Chúng ta có hai cách để yêu cầu nó: sử dụng tham số response_type với giá trị id_token hoặc sử dụng tham số scope với giá trị openid.

Lý do chúng ta có hai cơ chế là các tác giả của các đặc tả muốn có thể sử dụng OpenID Connect ngay cả khi SDK của bạn chỉ dựa trên OAuth2.

  • Thực tế, vào thời OAuth2, không có ID token trong danh sách các loại phản hồi. Vì các phạm vi hoàn toàn chung chung như một tham số, khả năng sử dụng một phạm vi cụ thể sẽ khiến authorization server trả lại một ID token là một cách tuyệt vời để tương thích ngược.

OpenID Connect định nghĩa ID token theo một định dạng cố định, định dạng JSON Web Token (JWT). Đặc tả thực sự định nghĩa không chỉ định dạng mà còn danh sách các claims phải có trong một ID token. Ngoài ra, nó còn cho bạn biết bằng thuật ngữ quy phạm những gì bạn cần làm để xác thực một số claims đó.

image.png

Hình bên trên là những gì một JWT token thường trông như thế nào, với các thành phần được mã hóa Base64 của nó. Nếu bạn đi đến jwt.io, bạn có thể copy ID token của mình và thấy nó được giải mã tự động.

image.png

Bằng cách kiểm tra nội dung HEADER, chúng tôi phát hiện rằng token này ở định dạng JWT, thuật toán nào đã được sử dụng để ký nó và một tham chiếu đến key cần thiết để xác minh chữ ký.

Nếu bạn nhìn vào PAYLOAD, sẽ thấy rằng nó chứa thông tin thực tế mà chúng ta mong đợi sẽ truy xuất.

  • Issuer (iss), là một chuỗi đại diện cho nguồn gốc của token, đó là thực thể đằng sau authorization server - giống như khóa, cũng được tìm thấy qua discovery endpoint.
  • Audience (aud), đại diện cho ứng dụng cụ thể mà token đã được phát hành cho. Điều rất quan trọng là phải kiểm tra claim này. Khi một ứng dụng nhận được token này, middleware được sử dụng để xác minh nó sẽ so sánh những gì đã được cấu hình để trở thành định danh ứng dụng (trong trường hợp đăng nhập và ID tokens, điều đó sẽ tương ứng với client ID của ứng dụng) với audience claim. Nếu có sự không khớp, điều đó có nghĩa là ai đó đã lấy cắp token từ nơi khác, và họ đang cố gắng lừa ứng dụng chấp nhận nó.
  • Issued-at (iat)expiration (exp) là các dữ liệu được sử dụng để đánh giá liệu token này còn hiệu lực hay đã hết hạn. Chúng ta sẽ thấy trong phần thảo luận về API rằng access tokens và ID tokens thường có thời gian hiệu lực giới hạn.

Tất cả các claims khác hầu hết là thông tin identity về người dùng, chỉ có trong ID token vì chúng ta đã yêu cầu profileemail trong tham số scope, thường thì chúng ta không cần phải verify những thông tin này.

Principles of Token Validation

Chúng ta đã nói về việc xác minh tokens khá nhiều, dựa trên trực giác rằng nó liên quan đến việc xác minh chữ ký và thực hiện metadata discovery. Hãy khám phá vấn đề này chi tiết hơn!

Chúng ta đã thấy chức năng của tokens thực hiện trong một vài kịch bản, cách đăng nhập bằng SAML, cách sử dụng access tokens để gọi APIs, và đặc biệt, ngay bây giờ, chúng ta đã thấy cách sử dụng một ID token để đăng nhập. Tất cả các kịch bản đó liên quan đến một thực thể, tài nguyên, nhận một token và đưa ra quyết định về việc liệu nó có cho phép người gọi thực hiện bất kỳ hoạt động nào mà người gọi đang cố gắng thực hiện hay không. Làm thế nào để resource đưa ra quyết định đó?

Subject Confirmation

Subject confirmation là một khái niệm mà chúng được thừa hưởng từ SAML. Đặc biệt, phương pháp subject confirmation xác định cách mà tài nguyên quyết định liệu một token có được sử dụng đúng cách hay không.

Bearer là đơn giản nhất, nó tương tự như việc tìm thấy 20$ trên sàn, bạn nhặt nó lên, đi bất cứ đâu bạn muốn sử dụng số tiền này, sử dụng nó, và bạn sẽ nhận được hàng hóa hoặc dịch vụ mà bạn đang trả tiền. Không có câu hỏi thêm nào được đặt ra vì tất cả những gì cần để sử dụng 20$ là sở hữu 20$ đó và để chúng đổi chủ. Đó là bản chất của phương pháp bearer subject confirmation, nếu bạn có token trong tay, bạn được phép sử dụng nó.

Proof of possession là thứ gì đó tiên tiến hơn. Bạn có một token nhưng nó được ký bởi bên phát hành, khi bạn nhận được token, nó thường kèm theo key hoặc hướng dẫn để bạn có thể verify token và sử dụng.

  • Cơ chế này an toàn hơn bearer: một kẻ tấn công chặn request và tiến hành thay đổi nội dung token, nhưng hắn không thể giả mạo chữ ký vì vậy client sẽ phát hiện gian lận và từ chối chúng.

Format Driven Validation Checks

Trong OAuth2, access tokens không có định dạng. Đặc tả không quy định bất kỳ định dạng nào chủ yếu vì ban đầu, nó được thiết kế cho một kịch bản mà authorization server và resource server nằm ở một nơi và chúng có thể chia sẻ bộ nhớ.

Tuy nhiên, trong trường hợp OpenID Connect, nó đã được xác định một định dạng cụ thể cho ID token. Chúng mong đợi người nhận thực sự nhìn vào bên trong một token và thực hiện các bước xác minh. Điều này thường xảy ra khi resource server và authorization server không ở cùng một nơi, do đó không thể sử dụng bộ nhớ chia sẻ để giao tiếp.

Ngoài ra, trong trường hợp SAML, chúng tôi đã xác định một định dạng, một tập hợp hướng dẫn về cách mã hóa một token.

Trong trường hợp kiểm tra xác thực dựa trên định dạng, có một số ràng buộc áp dụng khá nhiều cho mọi định dạng, và đặc biệt, cho JWT:

  • Signature for integrity: Token của bạn phải được ký để đảm bảo nguồn gốc của token và ngăn chặn việc giả mạo trong quá trình truyền qua internet. Token phải cung cấp một số chỉ dẫn về khóa và thuật toán được sử dụng để người nhận của nó có thể kiểm tra chữ ký.
  • Infrastructural claims: Các định dạng token sẽ thường bao gồm các infrastructural claims, nhằm cung cấp thông tin mà người nhận token phải xác minh để xác định xem token nhận được có nên được chấp nhận hay không.
    • Một ví dụ đáng chú ý của các loại claim này là issuer, tức là định danh của thực thể đã phát hành (và ký) token, và phải tương ứng với một trong các nhà phát hành được tin cậy bởi người nhận dự định.
    • Một claim cơ sở hạ tầng phổ biến khác là audience, cho biết token này dành cho ai. Bạn cần audience để có cách xác minh rằng token thực sự dành cho một người nhận cụ thể.
    • Bạn cũng cần kiểm tra expiration times claims để biết liệu token này còn hạn sử dụng hay không.

Alternative Validation Strategy: Introspection

Có một cách khác để xác minh tokens, được gọi là introspection.

Với cách tiếp cận này, tài nguyên nhận token không thể giải mã (hoặc nó đơn giản là không mang ý nghĩa gì) nó thường gặp trong trường hợp access_token. Vì access token chủ yếu dùng để thực hiện các yêu cầu uỷ quyền vì vậy nó không được thiết kế để tự tiêu thụ chính nó.

Trong trường hợp này, bạn có thể lấy token nhận được và gửi nó đến introspection endpoint, là một endpoint bổ sung mà có thể được authorization servers thêm vào. Authorization server kiểm tra token, xác định liệu token đó có hợp lệ hay không, và nếu có, bạn sẽ nhận lại được các thông tin liên quan thuộc về token.

Tóm lại, tokens sẽ được gửi đến authorization server và nói rằng, "Vui lòng cho tôi biết liệu nó có hợp lệ hay không." Authorization server có thể đưa ra quyết định và gửi nó lại cho client, cùng với các thông tin liên quan thuộc về token.

Metadata và Discovery

Cách này cũng khá đơn giản và phổ biến, Middleware chỉ cần trỏ tời URL ./well-known/openid-configuration, được định nghĩa bởi OpenID Connect, và truy xuất thông tin xác thực theo đặc tả.

Thông tin được public tại URL này thường chứa thông tin mà chúng ta cần có để verify token, như giá trị của issuer, các địa chỉ của authorization endpoint, và key dùng để verify chữ ký, cùng nhiều những thông tin khác.

Hãy xem cách middleware trích xuất thông tin xác thực từ discovery endpoint bằng cách theo dõi các bước được đánh số trong hình dưới đây.

image.png

Trong phần thực hành, mình sẽ nói chi tiết về cách chúng ta sử dụng ./well-known/openid-configuration để verify token cũng như cách hoạt động và luồng dựa trên JWK.

Conclusion

Trên đây là chi tiết về luồng Web Sign-In dựa trên OpenID Connect, ở bài tiếp theo chúng ta sẽ tìm hiểu nốt phần còn lại liên quan đến APIs, sau đó chuyển qua phần thực hành để xây dựng các thành phần có trong OAuth2 và OpenID Connect và một số chức năng bổ sung như:

  • Backchannel Logout
  • Withdrawable Check

Tài liệu tham khảo:

Again, nếu bạn thấy bài viết này hữu ích, hãy cho mình một upvote và follow để mình có thêm động lực viết những bài sau tốt và chất lượng hơn! Thank you!

Bình luận

Bài viết tương tự

- vừa được xem lúc

Sử dụng Misoca API (oauth2) với Python

Với bài viết này giúp chúng ta có thể nắm được. ・Tìm hiểu cách xử lý API misoca bằng Python.

0 0 48

- vừa được xem lúc

OAuth là gì? Cách thức hoạt động của OAuth

. OAuth cho phép các trang web và dịch vụ chia sẻ tài nguyên giữa những người dùng. Nó được sử dụng rộng rãi, nhưng hãy lưu ý về các lỗ hổng của nó.

0 0 52

- vừa được xem lúc

Giải thích về cách thức hoạt động của OAuth 2.0

OAuth2.0 là một giao thức authorization, cho phép truy cập tài nguyên của resource owner bằng cách bật client applications trên các dịch vụ HTTP như Facebook, GitHub, v.

0 0 38

- vừa được xem lúc

OAuth là gì ? Nó hoạt động như thế nào ?

Mở đầu. Khi bạn vào một trang web muốn sử dụng các dịch vụ của một trang web khác — chẳng hạn như đăng nhập vào bằng tài khoản Facebook — thay vì yêu cầu bạn chia sẻ tài khoản Facebook của mình của mì

0 0 53

- vừa được xem lúc

Từ OAuth đến OpenID Connect

Khi sử dụng các ứng dụng như Draw.io hay một số ứng dụng, trang web nào đó, bạn đã bao giờ gặp thông báo yêu cầu cấp quyền truy cập đến Google drive chưa.

0 0 102

- vừa được xem lúc

Tìm hiểu đôi chút về OAuth2

Chắc hẳn một trong số các bạn cũng đã từng nghe qua khái niệm OAuth trước đây. Về cơ bản, OAuth là một phương thức xác thực giúp một ứng dụng bên thứ 3 có thể được ủy quyền bởi người dùng để truy cập

0 0 34