Tùy chọn xác thực cho các hệ thống phân tán


9

Tôi đang trong quá trình thiết kế 3 thành phần sẽ hoạt động trong giao hưởng với nhau:

  • Một dịch vụ web RESTful yêu cầu BasicAuthqua HTTPS trên tất cả các cuộc gọi và đó là những gì thực sự làm tất cả các công việc nặng nề cho hệ thống của tôi (thực hiện công việc)
  • Giao diện người dùng web chuyển các hành động của người dùng cuối thành các lệnh gọi API sang dịch vụ web được đề cập ở trên; do đó UI được "hỗ trợ bởi" WS
  • Một công cụ giao diện dòng lệnh (CLI) mà các nhà phát triển có thể cài đặt và chạy cục bộ, cũng dịch các lệnh thành các lệnh gọi API đến WS (do đó nó cũng được "hỗ trợ bởi" WS)

Một trong những rào cản đầu tiên tôi đang cố gắng vượt qua là liên quan đến xác thực và ủy quyền.

Hãy giả vờ rằng WS sử dụng dịch vụ thư mục LDAP / (như AD hoặc có lẽ là Apache DS) làm lãnh vực xác thực của nó. Có nghĩa là, khi một cuộc gọi API đến qua mạng (giả sử, HTTPS GETđối với một số tài nguyên), BasicAuththông tin đăng nhập được trích xuất từ ​​yêu cầu và được chuyển tiếp đến dịch vụ LDAP để xác định xem đây có phải là người dùng hợp lệ hay không. Nếu chúng được xác thực, thì hãy nói rằng một lĩnh vực ủy quyền riêng biệt, có lẽ là cơ sở dữ liệu, được sử dụng để xác định liệu người dùng được xác định có thể thực hiện những gì họ đang cố gắng trong yêu cầu HTTPS hay không. Càng xa càng tốt.

Trong trường hợp công cụ CLI, người dùng sẽ phải xác thực trước khi chạy bất kỳ lệnh nào và do đó mô hình này hoạt động tốt, vì một người dùng sẽ chỉ vận hành cùng một thể hiện CLI tại một thời điểm nhất định.

Vấn đề xảy ra khi chúng tôi thử tích hợp ứng dụng web (UI) với WS, bởi vì nhiều người có thể đăng nhập vào ứng dụng cùng một lúc, tất cả đều có các quyền khác nhau cho phép các lệnh gọi API cơ bản mà họ được phép thực hiện.

Theo như tôi thấy, có vẻ như tôi có nhưng 4 tùy chọn ở đây:

  • Thông tin đăng nhập lưu trữ : Sau khi đăng nhập vào ứng dụng, các thông tin được bằng cách nào đó, ở đâu đó lưu trữ (như vậy mà các ứng dụng này có quyền truy cập vào chúng), và các ứng dụng không thực thi bất kỳ loại chính sách quyền riêng của mình. Khi người dùng cố gắng thực hiện những việc tạo ra các lệnh gọi API trong phần mềm, thông tin đăng nhập của họ được tra cứu từ bộ đệm và được chuyển tiếp bằng các lệnh gọi API. Nếu WS xác định họ không được ủy quyền, nó sẽ gửi lại lỗi.
  • Tài khoản cấp dịch vụ : Cả ứng dụng và WS đều sử dụng cùng một lĩnh vực xác thực / ủy quyền, ngoại trừ giao diện người dùng web hiện thực thi ủy quyền đối với những gì người dùng thực sự có thể nhìn thấy và làm trong ứng dụng. Nếu họ được phép thực hiện điều gì đó tạo cuộc gọi API cơ bản, ứng dụng sẽ gửi thông tin đăng nhập tài khoản dịch vụ (ví dụ myapp-admin-user) với mỗi cuộc gọi API thay mặt cho người dùng.
  • OAuthv2 : Tôi không biết OAuth là gì hoặc nếu nó áp dụng cho kịch bản này, nhưng cảm thấy nó có thể là một giải pháp ở đây bằng cách nào đó.
  • Máy chủ mã thông báo: Sử dụng máy chủ mã thông báo như CAS hoặc có thể là Kerberos để xác nhận cho người dùng, theo cách tương tự như tùy chọn Tài khoản cấp dịch vụ hoạt động. Tại đây, khi người dùng đăng nhập vào ứng dụng thành công, máy chủ mã thông báo sẽ gửi lại ứng dụng UUID phiên và cũng đăng ký UUID đó với WS. Mỗi khi ứng dụng tạo lệnh gọi API, nó sẽ xử lý UUID theo yêu cầu, sau đó xác nhận hợp lệ ở phía WS.

Các " Credentials Cached " tùy chọn chỉ cảm thấy giống như một thác loạn của tất cả những gì là tốt và lành mạnh trong an ninh-đất. Nó chỉ cảm thấy sai để thông tin bộ nhớ cache bất cứ nơi nào, bao giờ.

Các " token server " tùy chọn dường như hợp lệ cho một loại thiết lập SSO, nhưng không phải trong trường hợp cụ thể này và cảm thấy lúng túng với tôi. Tôi cũng nghĩ rằng không có cách nào tốt để sử dụng khái niệm UUID phiên BasicAuth / HTTPS cùng một lúc.

Vì vậy, điều này để lại OAuthv2, mà tôi không biết gì và " Tài khoản cấp dịch vụ (SLA) * " là các tùy chọn duy nhất còn lại. Tùy chọn SLA có vẻ ổn, nhưng có một vài nhược điểm sau:

  • Nó đòi hỏi tài khoản dịch vụ về cơ bản phải có "đặc quyền của chúa" đối với WS. Nói cách khác, một khi ứng dụng cho rằng người dùng được phép nhấp vào nút hoặc làm điều gì đó trong Giao diện người dùng, điều đó chuyển thành lệnh gọi API vô điều kiện bởi tài khoản dịch vụ đang được UI sử dụng. Điều này chỉ cảm thấy xấu, mkay?
  • Tôi nhận thấy rằng việc duy trì hai bộ quyền (bộ quyền cho mỗi người dùng ứng dụng và sau đó bộ quyền cho tài khoản dịch vụ được ứng dụng sử dụng đối với WS) có thể dẫn đến việc các quyền thoát khỏi đồng bộ với nhau bằng cách nào đó

Vì vậy, có vẻ như tôi không thực sự có bất kỳ lựa chọn tốt ở đây. Chắc chắn tôi không thể là nhà phát triển đầu tiên gặp phải vấn đề này, nhưng việc hỏi Google Gods đã không giúp tôi nhiều ở đây. Có ý kiến ​​gì không?

Câu trả lời:


6

Có nhiều lý do để không sử dụng lược đồ xác thực cơ bản để bảo vệ các dịch vụ API Web.

Để sử dụng dịch vụ, khách hàng cần giữ mật khẩu ở đâu đó trong văn bản rõ ràng để gửi cùng với mỗi yêu cầu.

Việc xác minh mật khẩu phải rất chậm (để chống lại các cuộc tấn công vũ phu), điều này sẽ cản trở khả năng mở rộng dịch vụ của bạn. Mặt khác, xác thực mã thông báo bảo mật có thể nhanh chóng (xác minh chữ ký số).

OAuth2 cung cấp giải pháp cho từng trường hợp sử dụng của bạn. Ứng dụng web của bạn có thể sử dụng cấp mã , cung cấp cho nó mã thông báo truy cập mà nó có thể sử dụng để nói chuyện với API của bạn.

Ứng dụng web của bạn sẽ chuyển hướng trình duyệt của người dùng đến máy chủ ủy quyền. Nó sẽ nhắc người dùng về thông tin đăng nhập (hoặc thẻ thông minh hoặc mã xác thực hai yếu tố) và trả lại mã cho trình duyệt mà ứng dụng khách (ứng dụng web của bạn) có thể sử dụng để nhận mã thông báo truy cập từ máy chủ ủy quyền.

Ứng dụng của bạn cũng sẽ nhận lại mã thông báo làm mới mà nó có thể nhận được mã thông báo truy cập mới nếu mã thông báo hiện tại hết hạn.

Ứng dụng CLI của bạn có thể sử dụng cấp thông tin xác thực chủ sở hữu tài nguyên . Bạn sẽ nhắc người dùng về thông tin đăng nhập và gửi chúng đến máy chủ ủy quyền để có được quyền truy cập và làm mới mã thông báo. Khi ứng dụng CLI của bạn có mã thông báo, bạn có thể loại bỏ mật khẩu của người dùng trong bộ nhớ.

Cả máy khách (ứng dụng web và máy khách dòng lệnh) cần được đăng ký trước với máy chủ ủy quyền.

Máy chủ ủy quyền của bạn cũng có thể nói chuyện với dịch vụ thư mục LDAP / (nhà cung cấp nhận dạng hoặc IdP) để thực hiện xác thực.

Dịch vụ API web của bạn chỉ cần xác minh mã thông báo JWT đến và thiết lập những gì người dùng được phép làm (ủy quyền).

Nếu bạn là nạn nhân của một cuộc tấn công trung gian và bạn mất mã thông báo truy cập của mình, kẻ tấn công chỉ có thời gian giới hạn (vòng đời mã thông báo) để sử dụng nó. Một mật khẩu thường có giá trị lâu hơn nhiều. Làm mới mã thông báo có thể bị thu hồi trong trường hợp chúng bị mất.


Cảm ơn về đầu vào vững chắc @ user18044 (+1). Còn các máy khách HTTP khác đối với dịch vụ web thì sao? Đây là một dịch vụ web RESTful, vì vậy bất kỳ ai cũng có thể xây dựng ứng dụng khách cho nó. Tùy chọn OAuthv2 nào sẽ sử dụng để xác thực từng yêu cầu? Giống như ứng dụng web (cấp mã)? Cảm ơn một lần nữa!
smeeb

Ngoài ra @ user18044 bạn có thể xác nhận rằng OAuthv2 chỉ xử lý khía cạnh xác thực chứ không phải ủy quyền? Nếu vậy, làm thế nào tôi có thể ánh xạ từng yêu cầu được xác thực (thành công) vào một nhóm vai trò / quyền có sẵn cho khách hàng?
smeeb

1
Tùy thuộc vào cách bạn tin tưởng những khách hàng này, họ được xác thực khác nhau. Ví dụ: bạn xây dựng một ứng dụng di động cho API của riêng bạn, bạn có thể sử dụng cấp thông tin xác thực của chủ sở hữu tài nguyên. Nhưng nếu ứng dụng khách di động được tạo bởi bên thứ 3 (một số ứng dụng từ cửa hàng ứng dụng), bạn sẽ sử dụng khoản trợ cấp ngầm.
MvdD

1
@smeeb OAuth xác định phạm vi để cho biết khách hàng có thể làm gì. Có một số phạm vi được xác định trước, nhưng bạn có thể xác định phạm vi của riêng mình (ví dụ: để gọi các API cụ thể (xem tools.ietf.org/html/rfc6749#section-3.3 )
MvdD

1
Đừng lo lắng, bạn được chào đón. Phạm vi thực sự là một cơ chế để xác định những gì bên thứ 3 có thể làm trong API của bạn. Ví dụ: một ứng dụng tài chính chỉ có thể đọc số dư tài khoản của bạn trong trang web ngân hàng của bạn. Nhưng vì mã thông báo JWT chứa tên người dùng và các vai trò thậm chí tùy chọn, bạn có thể tra cứu trong cơ sở dữ liệu những gì người dùng hoặc người dùng trong vai trò được phép làm. Đó cũng là cách công ty của tôi đang làm điều đó.
MvdD 29/07/2015

2

Tôi đang làm việc trên một hệ thống tương tự như bây giờ, thực sự; Tôi sẽ nói dối nếu tôi nói rằng tôi biết cách "đúng" để thực hiện công việc này vì tôi vẫn đang thử nghiệm nhưng có lẽ đi qua những gì tôi thấy có thể làm việc có thể giúp ích. Thiết lập được lấy cảm hứng khá nhiều từ OAuth2 mặc dù nhược điểm của nó , một số trong đó tôi sẽ thảo luận.

TUYÊN BỐ TỪ CHỐI: Tôi không phải là người bảo mật bằng thương mại và những gì tôi đã xây dựng tôi đã xây dựng với sự trợ giúp của Google và nhiều ví dụ như tôi có thể tìm thấy.

Khi tôi lần đầu tiên bắt đầu nghiên cứu cách tôi xây dựng API web sẽ hỗ trợ (các) ứng dụng khách, tôi đã quyết định rằng tôi muốn thử và làm cho API không trạng thái nhất có thể. Một phần trong tôi đã cố gắng tiếp cận với auth cơ bản HTTP và khiến người dùng xác thực theo mọi yêu cầu, nhưng hai vấn đề xuất hiện khiến giải pháp đó dường như không khả thi:

  1. Việc tra cứu để xác thực thông tin đăng nhập là một chi phí thời gian không hề nhỏ, vì nó sẽ liên quan đến ít nhất một cuộc gọi cơ sở dữ liệu với mỗi yêu cầu
  2. Hệ thống này là một hệ thống nhiều người thuê; xác định đối tượng thuê nào mà người dùng thuộc về sẽ yêu cầu tham số thứ ba và không được hỗ trợ bởi xác thực cơ bản HTTP (1)

Sự phức tạp liên quan đến xác thực khiến tôi chọn hệ thống mã thông báo, trong đó người dùng sẽ yêu cầu xác thực đến điểm cuối sẽ phát lại mã thông báo nhận dạng và sau đó lưu trữ ở đâu đó sau đó máy chủ có thể sử dụng nó để xác thực các yêu cầu và liên kết với một số dữ liệu người dùng cần thiết. Nó không hoàn toàn không trạng thái và tôi đã xem mã thông báo web JSON như một cách tiếp cận khác, nhưng việc tra cứu mã thông báo có thể được thực hiện rất nhanh. (2)

Khách hàng sau đó bám vào mã thông báo đó cho đến khi máy chủ không còn chấp nhận mã thông báo đó nữa. Sau đó, khách hàng cố gắng xác nhận lại với máy chủ và truy xuất mã thông báo mới để xác thực các yêu cầu trong tương lai với. Đây là những gì bài đăng của bạn tham chiếu như chiến lược thông tin đăng nhập được lưu trong bộ nhớ cache và chúng tôi đã chọn sử dụng nó vì nó cho phép chúng tôi duy trì quyền kiểm soát nhiều hơn đối với quyền truy cập vào ứng dụng. Với điều kiện khách hàng có thể được tin cậy để giữ thông tin ủy quyền của riêng mình và chỉ kết nối qua một kết nối an toàn (chúng tôi buộc truy cập chỉ HTTPS vì lý do đó) không nhất thiết là cách xử lý mọi thứ, nếu chỉ từ góc độ UX. Đối với dịch vụ web, chúng tôi thực sự giữ mã thông báo trong bộ nhớ cục bộ của trình duyệt; vì nó chỉ là một nhận dạng tạm thời và không phải là sự kết hợp tên người dùng / mật khẩu thực tế của người dùng, nên chúng tôi đã coi đây là "

Các mã thông báo sau đó được gửi đến API web như một phần của tiêu đề Ủy quyền hoặc dưới dạng tham số GET cho các máy khách nơi tiêu đề HTTP tùy chỉnh không khả dụng. Điều này rất quan trọng vì nó cho phép mức độ linh hoạt cao hơn trong cách chúng tôi truy cập API từ một loạt các ứng dụng khách tiềm năng, giống như cách bạn cần hỗ trợ CLI và ứng dụng web. Mã thông báo mang là một thứ khá phổ biến nhưng chúng không thực sự hoàn hảo . Mặc dù vậy, mối quan tâm bảo mật của ứng dụng của chúng tôi không đủ quan trọng để dành thêm thời gian để cải thiện vấn đề này.

Khi mã thông báo được xác thực, ủy quyền sẽ được sử dụng. Những gì đòi hỏi có thể khác nhau rất nhiều, nhưng vào thời điểm đó trong ứng dụng, danh tính của người dùng được biết đến và do đó, một dịch vụ ủy quyền thuộc loại nào đó chỉ cần được cung cấp danh tính của người dùng đó và đối tượng / hành động để kiểm tra.

Ít nhất, nếu bạn muốn sử dụng loại chiến lược này, có rất nhiều thư viện được thiết kế để triển khai OAuth và OAuth2 ngoài kia; trừ khi bạn thích chúng tôi và có một số yêu cầu bên lề, tôi khuyên bạn nên sử dụng thư viện bảo mật của bên thứ ba đáng tin cậy vì rất có thể bạn sẽ không nhận được mọi thứ ngay lần đầu tiên thử. Tôi vẫn tìm kiếm một sự thay thế của bên thứ ba để thay thế hệ thống xác thực hiện tại của chúng tôi bởi vì tôi biết nó đầy lỗ hổng và các trường hợp cạnh mà tôi thậm chí không thể tưởng tượng được.


Chú thích

  1. Điều này sẽ không cần thiết nếu hệ thống của chúng tôi được xây dựng khác nhau, bằng cách sử dụng các điểm nhập khác nhau cho mỗi khách hàng; cách khác, tôi cũng cân nhắc việc lấy thông minh và tiền tố tên người dùng bằng mã định danh người thuê
  2. Tôi đã có một số ý tưởng về cách làm cho chuỗi mã thông báo dễ dàng xác thực hoàn toàn tính toán thay vì phải thực hiện tra cứu I / O như một mục tiêu dài hạn để cải thiện; ít nhất là các mã thông báo chứa một byte phiên bản sẽ cho phép nâng cấp xuống dòng nếu / khi quá trình giải mã cho nó thay đổi
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.