Tại sao lại có một luồng ủy quyền mã luồng trong OAuth2 khi luồng Implicit có thể hoạt động tốt như vậy?


264

Với luồng "tiềm ẩn", máy khách (có thể là trình duyệt) sẽ nhận được mã thông báo truy cập, sau khi Chủ sở hữu tài nguyên (tức là người dùng) đã cấp quyền truy cập.

Tuy nhiên, với luồng "Mã ủy quyền", máy khách (thường là máy chủ web) chỉ nhận được mã ủy quyền sau khi Chủ sở hữu tài nguyên (tức là người dùng) cấp quyền truy cập. Với mã ủy quyền đó, khách hàng sau đó thực hiện một cuộc gọi khác tới API thông qua client_id và client_secret cùng với mã ủy quyền để lấy mã thông báo truy cập. Tất cả được mô tả tốt ở đây .

Cả hai luồng đều có cùng kết quả chính xác: mã thông báo truy cập. Tuy nhiên, luồng "ngầm" đơn giản hơn nhiều.

Câu hỏi: Tại sao phải bận tâm với luồng "Mã ủy quyền", khi các đường nối dòng chảy "ngầm" sẽ ổn? Tại sao không sử dụng "Implicit" cho máy chủ web?

Đó là công việc nhiều hơn cho cả nhà cung cấp và khách hàng.



1
Cảm ơn, đọc nó rồi. Không trả lời câu hỏi mặc dù.
Aron Woost

1
Câu hỏi hay thực sự và hiếm khi trả lời :) Xem bên dưới.
Nicolas Garnier

1
@AronWoost Tôi nghĩ bạn hiểu nhầm ứng dụng web và ứng dụng trình duyệt của máy chủ
onmyway133

@entropy Đó là câu hỏi của tôi; Tại sao không sử dụng luồng trình duyệt cho máy chủ là tốt.
Aron Woost

Câu trả lời:


293

tl; dr: Đây là tất cả vì lý do bảo mật.

OAuth 2.0 muốn đáp ứng hai tiêu chí sau:

  1. Bạn muốn cho phép các nhà phát triển sử dụng URI chuyển hướng không HTTPS vì không phải tất cả các nhà phát triển đều có máy chủ hỗ trợ SSL và nếu họ không luôn luôn được định cấu hình đúng (chứng chỉ SSL không tự ký, chứng chỉ SSL đáng tin cậy, đồng hồ máy chủ được đồng bộ hóa ...).
  2. Bạn không muốn tin tặc có thể đánh cắp các mã thông báo truy cập / làm mới bằng cách chặn các yêu cầu.

Chi tiết bên dưới:

Luồng ngầm chỉ có thể có trong môi trường trình duyệt vì lý do bảo mật:

Trong luồng ngầm định , mã thông báo truy cập được truyền trực tiếp dưới dạng một đoạn băm (không phải là tham số URL). Một điều quan trọng về đoạn băm là, một khi bạn theo liên kết có chứa đoạn băm, chỉ có trình duyệt biết về đoạn băm. Các trình duyệt sẽ chuyển đoạn băm trực tiếp đến trang web đích (URI chuyển hướng / trang web của khách hàng). Đoạn băm có các thuộc tính sau:

  • Chúng không phải là một phần của yêu cầu HTTP do đó chúng không thể được đọc bởi máy chủ và do đó chúng không thể bị chặn bởi các máy chủ / bộ định tuyến trung gian (điều này rất quan trọng).
  • Chúng chỉ tồn tại trên trình duyệt - phía máy khách - vì vậy cách duy nhất để đọc đoạn băm là sử dụng JavaScript chạy trên trang.

Điều này cho phép truyền trực tiếp Mã thông báo truy cập đến máy khách mà không có nguy cơ bị máy chủ trung gian chặn. Điều này có sự cảnh báo chỉ là phía khách hàng có thể và cần javascript chạy phía máy khách để sử dụng mã thông báo truy cập.

Luồng ẩn cũng có các vấn đề bảo mật đòi hỏi logic hơn nữa để khắc phục / tránh:

  • Kẻ tấn công có thể nhận được mã thông báo truy cập từ người dùng trên một trang web / ứng dụng khác (giả sử nếu anh ta là chủ sở hữu của trang web / ứng dụng khác), đăng nhập mã thông báo trên trang web của họ và sau đó chuyển nó dưới dạng thông số URL trên trang web của bạn do đó mạo danh người dùng trên trang web của bạn. Để tránh điều này, bạn cần kiểm tra ID khách hàng được liên kết với mã thông báo truy cập (ví dụ: Google, bạn có thể sử dụng điểm cuối tokeninfo) để đảm bảo mã thông báo được cấp với ID khách hàng của riêng bạn (tức là bằng ứng dụng của riêng bạn) hoặc kiểm tra chữ ký nếu bạn đang sử dụng IDToken (nhưng điều đó đòi hỏi bí mật của khách hàng của bạn).
  • Nếu yêu cầu xác thực không bắt nguồn từ tài sản của riêng bạn (được gọi là các cuộc tấn công Sửa lỗi phiên), để tránh điều này, bạn sẽ muốn tạo một hàm băm ngẫu nhiên từ trang web của mình, hãy lưu nó vào cookie và chuyển cùng hàm băm đó trong thông số URL trạng thái của yêu cầu xác thực, khi người dùng quay lại, bạn kiểm tra thông số trạng thái với cookie và nó phải khớp.

Trong luồng mã ủy quyền , không thể chuyển trực tiếp mã thông báo truy cập trong tham số URL vì tham số URL là một phần của Yêu cầu HTTP, do đó, bất kỳ máy chủ / bộ định tuyến trung gian nào mà yêu cầu của bạn sẽ vượt qua (có thể là hàng trăm) đọc mã thông báo truy cập nếu bạn không sử dụng kết nối được mã hóa (HTTPS) cho phép những gì được gọi là tấn công trung gian.

Về mặt lý thuyết, việc chuyển mã thông báo truy cập trong một thông số URL có thể khả thi nhưng auth sever sẽ phải đảm bảo URI chuyển hướng đang sử dụng HTTPS với mã hóa TLS và chứng chỉ SSL 'đáng tin cậy' (thường là từ Cơ quan cấp chứng chỉ không miễn phí) để chắc chắn rằng máy chủ đích là hợp pháp và yêu cầu HTTP được mã hóa hoàn toàn. Việc tất cả các nhà phát triển mua chứng chỉ SSL và định cấu hình SSL đúng cách trên miền của họ sẽ là một nỗi đau lớn và sẽ làm chậm quá trình áp dụng. Đây là lý do tại sao một "mã ủy quyền" sử dụng một lần trung gian được cung cấp rằng chỉ người nhận hợp pháp mới có thể trao đổi (vì bạn cần bí mật của khách hàng) và mã sẽ vô dụng đối với các tin tặc tiềm năng chặn các yêu cầu đối với các giao dịch không được mã hóa (vì họ không '

Bạn cũng có thể lập luận rằng luồng ngầm là kém an toàn hơn, có các vectơ tấn công tiềm năng như giả mạo tên miền khi chuyển hướng - ví dụ: bằng cách chiếm đoạt địa chỉ IP của trang web của khách hàng. Đây là một trong những lý do tại sao luồng ngầm chỉ cấp mã thông báo truy cập (được cho là có thời gian sử dụng hạn chế) và không bao giờ làm mới mã thông báo (không giới hạn thời gian). Để khắc phục vấn đề này, tôi khuyên bạn nên lưu trữ các trang web của mình trên máy chủ hỗ trợ HTTPS bất cứ khi nào có thể.


12
@AndyDufresne Hai yêu cầu này phải được thực hiện qua HTTPS (bắt buộc) vì chúng là các yêu cầu đến máy chủ OAuth chỉ phải hỗ trợ HTTPS. Chỉ có máy chủ / máy chủ yêu cầu không phải hỗ trợ HTTPS, vì vậy chỉ Auth Codecó khả năng được gửi rõ ràng qua HTTP. Nhưng Auth Codevô dụng nếu không có ID khách hàng / Bí mật. Về cơ bản, quan điểm của luồng Mã OAuth là gánh nặng của việc có máy chủ hỗ trợ SSL là trên Nhà cung cấp OAuth (Google / Facebook, v.v.) chứ không phải cho người dùng API (bạn, tôi).
Nicolas Garnier

5
Ok, bây giờ tôi theo dõi mã xác thực có thể được chuyển qua HTTP đơn giản và có nguy cơ bị đánh hơi. Làm cho nó trở thành mã sử dụng một lần và chấp nhận bí mật của khách hàng để đổi nó thành mã thông báo truy cập, máy chủ ủy quyền có thể ngăn chặn cuộc tấn công Man-in-the-middle. Nhưng điều này cũng không áp dụng cho mã thông báo truy cập? Vì người dùng API có thể sử dụng HTTP đơn giản, nên sẽ không có nguy cơ mã thông báo truy cập bị tin tặc đánh hơi? Tái bút - Tôi đánh giá cao những nỗ lực của bạn trong việc giải thích khái niệm ngay cả sau khi đã được một thời gian kể từ khi chủ đề này hoạt động. Cảm ơn !
Andy Dufresne

8
không pb :) Các yêu cầu đối với API - đó là khi mã thông báo truy cập được gửi qua dây (để ủy quyền cho yêu cầu) - cũng được thực hiện qua HTTPS một cách bắt buộc. Về lý thuyết, khách hàng không bao giờ nên gửi mã thông báo truy cập qua mạng HTTP đơn giản bất cứ lúc nào.
Nicolas Garnier

5
Mã thông báo truy cập trong bước này là một phần của phản hồi yêu cầu HTTPS từ Máy khách đến máy chủ tài nguyên. Phản hồi này vẫn được mã hóa.
Nicolas Garnier

13
Về cơ bản các yêu cầu được bắt đầu từ máy khách đến máy chủ tài nguyên được thực hiện thông qua HTTPS (vì máy chủ sở hữu tài nguyên phải hỗ trợ HTTPS). Đó chỉ là những yêu cầu được bắt đầu từ một nơi khác đến máy khách có thể được thực hiện qua HTTP (vì máy chủ của máy khách có thể không hỗ trợ HTTPS). Ví dụ, chuyển hướng xảy ra trong luồng xác thực sau khi người dùng cấp quyền trên trang gant là chuyển hướng được bắt đầu từ trình duyệt đến máy chủ của khách hàng và có thể được thực hiện bằng HTTP.
Nicolas Garnier

8

Các dòng chảy ngầm làm cho toàn bộ dòng chảy khá dễ dàng, nhưng cũng kém an toàn .
Vì ứng dụng khách, thường là JavaScript chạy trong Trình duyệt ít được tin cậy hơn, không có mã thông báo làm mới nào cho truy cập lâu dài được trả lại.
Bạn nên sử dụng luồng này cho các ứng dụng cần truy cập tạm thời (một vài giờ) vào dữ liệu của người dùng.
Trả lại mã thông báo truy cập cho các máy khách JavaScript cũng có nghĩa là ứng dụng dựa trên trình duyệt của bạn cần được chăm sóc đặc biệt - nghĩ về Tấn công XSS có thể rò rỉ mã thông báo truy cập vào các hệ thống khác.

https://labs.hybris.com/2012/06/05/oauth2-the-implicit-flow-aka-as-the-client-side-flow


Tôi hy vọng rằng khi một người có lỗ hổng XSS, thì ngay cả luồng mã ủy quyền cũng không giúp được gì nhiều. Nhưng tôi đồng ý rằng cách thức mã thông báo truy cập được chuyển đến javascript trong luồng Implicit được chuẩn hóa (dưới dạng đoạn băm) và nếu có lỗ hổng XSS trong trang web, thì hãy xây dựng một cuộc tấn công đọc mã thông báo truy cập từ hàm băm URL mảnh khá dễ dàng Với dòng mã ủy quyền, mặt khác, giả mạo yêu cầu chéo trang web có thể có thể.
Marcel

Ngoài ra, nó không chỉ là về kịch bản chéo trang. Bất kỳ thư viện JavaScript nào đang chạy trong trang web của bạn đều có thể cố gắng đánh cắp mã thông báo truy cập (ví dụ: thư viện CDN của bên thứ ba hoặc thư viện nguồn mở mà khung javascript của bạn sử dụng).
Marcel

2
XSS hiện không phải là vấn đề lớn khi chúng tôi có các tiêu đề Chính sách bảo mật nội dung và băm toàn vẹn tài nguyên phụ (SRI).
Serge Ponomarev

4

Từ thông số kỹ thuật OAuth :

4.2. Cấp ẩn

Loại cấp quyền ngầm được sử dụng để nhận mã thông báo truy cập (loại này không hỗ trợ phát hành mã thông báo làm mới) và được tối ưu hóa cho các máy khách công cộng được biết là vận hành URI chuyển hướng cụ thể. Những ứng dụng khách này thường được triển khai trong trình duyệt sử dụng ngôn ngữ script như JavaScript.

Vì đây là luồng dựa trên chuyển hướng, nên máy khách phải có khả năng tương tác với tác nhân người dùng của chủ tài nguyên (thường là trình duyệt web) và có khả năng nhận các yêu cầu đến (thông qua chuyển hướng) từ máy chủ ủy quyền.

Không giống như loại cấp mã ủy quyền, trong đó khách hàng thực hiện các yêu cầu ủy quyền riêng biệt và cho mã thông báo truy cập, khách hàng nhận được mã thông báo truy cập do kết quả của yêu cầu ủy quyền.

Loại cấp quyền ngầm không bao gồm xác thực ứng dụng khách và phụ thuộc vào sự hiện diện của chủ sở hữu tài nguyên và đăng ký URI chuyển hướng. Vì mã thông báo truy cập được mã hóa vào URI chuyển hướng, nên nó có thể được hiển thị cho chủ sở hữu tài nguyên và các ứng dụng khác nằm trên cùng một thiết bị.

Vì vậy, những gì chúng ta có thể xem xét:

  1. Điều này dành cho OAuth công khai, tức là khi khách hàng không cần phải đăng ký và không có bí mật riêng của khách hàng. Nhưng những gì máy chủ auth kiểm tra url chuyển hướng và điều này thực sự đủ để bảo mật.

  2. Mã thông báo truy cập xảy ra trên thanh địa chỉ của trình duyệt để người dùng có thể sao chép url và gửi cho người khác và nó cũng được ghi lại dưới dạng người dùng, nghĩa là nó giống như phiên sửa lỗi. Nhưng trình duyệt thực hiện chuyển hướng bổ sung bằng cách thay thế lịch sử để xóa đoạn băm khỏi url. Cũng có thể tin tặc đánh cắp mã thông báo truy cập bằng cách đánh hơi các đề tài HTTP nhưng điều này có thể dễ dàng được bảo vệ bởi HTTPS. Một số tiện ích mở rộng trình duyệt độc hại có thể có quyền truy cập vào url từ thanh địa chỉ nhưng đây thực sự là tình huống xấu như chứng chỉ HTTPS bị hỏng. Và thậm chí dòng mã Auth không thể giúp đỡ ở đây ether. Vì vậy, những gì tôi có thể thấy là việc chuyển mã thông báo truy cập thông qua đoạn băm của url là an toàn tuyệt đối.

  3. Việc tách mã thông báo truy cập nhanh chóng và mã thông báo làm mới là vô ích khi sử dụng HTTPS và thành thật mà nói không hữu ích ngay cả trên HTTP thô. Nhưng thực tế là khách hàng thông qua luồng ngầm không thể nhận được mã thông báo làm mới cũng vô nghĩa.

Do đó, tôi nghĩ rằng chúng tôi nên giới thiệu một luồng cấp mới, An toàn ẩn ngầm hoạt động trên https, cho phép làm mới mã thông báo (hoặc chúng tôi nên loại bỏ chúng), và tốt hơn là luồng cấp quyền Auth Cose


3

Đối với chúng tôi, khách hàng của chúng tôi muốn có thể xác thực với ứng dụng của chúng tôi trên điện thoại của họ một lần và không phải đăng nhập lại trong nhiều tuần. Với dòng mã, bạn nhận được mã thông báo làm mới cùng với mã thông báo truy cập của bạn. Luồng ngầm định không cung cấp cho bạn mã thông báo làm mới. Mã thông báo truy cập có thời gian hết hạn tương đối ngắn, nhưng mã thông báo làm mới có thể hết hạn tới 90 ngày. Bất cứ khi nào mã thông báo truy cập hết hạn, mã máy khách và máy chủ có thể sử dụng mã thông báo làm mới đó để nhận mã thông báo truy cập mới cộng với mã thông báo làm mới, tất cả đằng sau hậu trường, mà không cần bất kỳ sự can thiệp nào của người dùng. Mã thông báo làm mới chỉ có thể được sử dụng một lần. Bạn không thể làm điều này với Dòng chảy ngầm. Nếu bạn đang sử dụng Lưu lượng tiềm ẩn và người dùng của bạn không tương tác với ứng dụng của bạn trong hơn một giờ, họ sẽ phải đăng nhập lại khi họ quay lại. Điều đó không được chấp nhận trong trường hợp sử dụng của chúng tôi,

Điều này hoạt động và an toàn vì mã thông báo làm mới có thể bị thu hồi. Nếu một khách hàng nói rằng họ bị mất điện thoại hoặc máy tính xách tay của họ hoặc tin tặc đã truy cập vào máy tính để bàn của họ, chúng tôi chỉ có thể thu hồi tất cả các mã thông báo làm mới cho người dùng đó. Trong toàn bộ quá trình, không có thông tin nhận dạng cá nhân (PII) nào chạm vào mã của chúng tôi - cụ thể là mật khẩu của người dùng.

Dòng mã là tuyệt vời, nhưng nó đòi hỏi nhiều công việc hơn. Hiện tại MS không có thư viện Angular để xử lý nó, vì vậy tôi phải viết một cái. Nếu bạn quan tâm tôi có thể giúp bạn với nó.


2

Câu trả lời của tôi là: bạn không thể thực hiện luồng ngầm theo cách an toàn và đơn giản với máy chủ ứng dụng web.

Quá trình ủy quyền ứng dụng web liên quan đến tương tác của người dùng, vì vậy Máy chủ xác thực sẽ chuyển hướng trình duyệt của người dùng trở lại trang đích của ứng dụng web sau khi xác thực và đồng ý với người dùng (Tôi không thấy cách nào khác để chuyển người dùng trở lại ứng dụng web sau một số tương tác với Máy chủ xác thực).

Vì vậy, mã thông báo nên được chuyển đến ứng dụng web bằng URL chuyển hướng, phải không?

Như @NicolasGarnier đã giải thích trong câu trả lời và nhận xét của mình, không có cách nào để chuyển mã thông báo dưới dạng một đoạn URL - nó sẽ không đến được máy chủ ứng dụng web.

Và việc chuyển mã thông báo dưới dạng tham số URL của URL chuyển hướng sẽ không an toàn ngay cả trong HTTPS: nếu trang đích (hãy là "trang chào mừng") chứa tài nguyên (hình ảnh, tập lệnh, v.v.) tài nguyên này sẽ được trình duyệt lấy qua chuỗi trong số các yêu cầu HTTP (S) (mỗi yêu cầu có Referertiêu đề HTTP chứa URL chính xác của "trang chào" bao gồm các tham số URL). Đây là cách mã thông báo có thể bị rò rỉ.

Vì vậy, có vẻ như không có cách nào để chuyển mã thông báo trong URL chuyển hướng. Đó là lý do tại sao bạn cần cuộc gọi thứ hai (từ Máy chủ xác thực đến Máy khách (nhưng đến URL nào?) Hoặc từ Máy khách đến Máy chủ xác thực (cuộc gọi thứ hai trong luồng Mã ủy quyền))

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.