Bảo mật API REST Mã thông báo được lưu trữ so với JWT so với OAuth


104

Tôi vẫn đang cố gắng tìm giải pháp bảo mật tốt nhất để bảo vệ API REST, vì số lượng ứng dụng di động và API đang tăng lên mỗi ngày.

Tôi đã thử nhiều cách xác thực khác nhau, nhưng vẫn có một số hiểu lầm, vì vậy tôi cần lời khuyên của một người có kinh nghiệm hơn.

Hãy để tôi nói, làm thế nào tôi hiểu tất cả những thứ này. Nếu tôi hiểu điều gì đó không chính xác, xin vui lòng cho tôi biết.

Theo như API REST không trạng thái cũng như WEB nói chung, chúng tôi cần gửi một số dữ liệu xác thực trong mỗi yêu cầu (cookie, mã thông báo ....). Tôi biết ba cơ chế được sử dụng rộng rãi để xác thực người dùng

  1. Mã thông báo với HTTPS. Tôi đã sử dụng phương pháp này rất nhiều lần, nó đủ tốt với HTTPS. Nếu người dùng cung cấp mật khẩu và đăng nhập chính xác, anh ta sẽ nhận được mã thông báo để phản hồi và sẽ sử dụng nó cho các yêu cầu tiếp theo. Mã thông báo được tạo bởi máy chủ và được lưu trữ, ví dụ trong bảng riêng biệt hoặc giống với nơi lưu trữ thông tin người dùng. Vì vậy, đối với mỗi máy chủ yêu cầu kiểm tra xem người dùng có mã thông báo hay không và nó giống như trong cơ sở dữ liệu. Mọi thứ đều khá đơn giản.

  2. Mã thông báo JWT. Mã thông báo này là tự mô tả, nó chứa tất cả thông tin cần thiết về chính mã thông báo, người dùng không thể thay đổi ví dụ ngày hết hạn hoặc bất kỳ khiếu nại nào khác, bởi vì mã thông báo này được tạo bởi máy chủ với từ khóa bí mật. Điều này cũng rõ ràng. Nhưng một vấn đề lớn, cá nhân đối với tôi, làm thế nào để vô hiệu hóa mã thông báo.

  3. OAuth 2. Tôi không hiểu tại sao nên sử dụng phương pháp này khi giao tiếp được thiết lập trực tiếp giữa máy chủ và máy khách. Theo tôi hiểu, máy chủ OAuth được sử dụng để phát hành mã thông báo với phạm vi hạn chế để cho phép các ứng dụng khác truy cập thông tin người dùng mà không lưu trữ mật khẩu và đăng nhập. Đây là giải pháp tuyệt vời cho các mạng xã hội, khi người dùng muốn đăng ký trên một số trang, máy chủ có thể yêu cầu quyền để lấy thông tin người dùng, ví dụ từ twitter hoặc facebook, và điền vào các trường đăng ký với dữ liệu người dùng, v.v.

Xem xét khách hàng di động cho cửa hàng trực tuyến.

Câu hỏi đầu tiên tôi có nên thích JWT hơn mã thông báo loại đầu tiên không? Theo như tôi cần người dùng đăng nhập / đăng xuất trên máy khách di động, tôi cần lưu trữ mã thông báo ở đâu đó hoặc trong trường hợp JWT, mã thông báo sẽ bị vô hiệu khi đăng xuất. Các cách tiếp cận khác nhau được sử dụng để vô hiệu hóa mã thông báo, một trong số đó là tạo danh sách mã thông báo không hợp lệ (danh sách đen). Hừm. Bảng / tệp sẽ có kích thước lớn hơn nhiều so với nếu mã thông báo được lưu trữ trong bảng và được liên kết với người dùng và chỉ bị xóa khi đăng xuất.

Vậy lợi ích của mã thông báo JWT là gì?

Câu hỏi thứ hai về OAuth, tôi có nên sử dụng nó trong trường hợp liên lạc trực tiếp với máy chủ của mình không? Mục đích của một lớp nữa giữa máy khách và máy chủ chỉ để phát hành mã thông báo, nhưng giao tiếp sẽ không phải với máy chủ oauth mà với máy chủ chính. Theo tôi hiểu, máy chủ OAuth chỉ chịu trách nhiệm cấp quyền cho ứng dụng của bên thứ ba (mã thông báo) để truy cập thông tin cá nhân của người dùng. Nhưng ứng dụng khách trên thiết bị di động của tôi không phải là bên thứ ba.


Cảm ơn, tôi đã tự hỏi điều này gần đây. Tôi đã đi với quản lý phiên (Beaker) và xóa mã thông báo phiên sau một giờ. Oauth dường như không phù hợp.
JasTonAChair

Câu trả lời:


86

Hãy xem xét trường hợp đầu tiên. Mỗi khách hàng nhận được một ID ngẫu nhiên kéo dài trong suốt thời gian của phiên - có thể là vài ngày nếu bạn muốn. Sau đó, bạn lưu trữ thông tin liên quan đến phiên đó ở đâu đó phía máy chủ. Nó có thể là trong một tập tin hoặc cơ sở dữ liệu. Giả sử bạn chuyển ID qua cookie nhưng bạn có thể sử dụng URL hoặc tiêu đề HTTP.

ID phiên / Cookies

Ưu điểm:

  • Dễ dàng mã cả máy khách và máy chủ.
  • Dễ dàng phá hủy một phiên khi ai đó đăng xuất.

Nhược điểm:

  • Phía máy chủ cần định kỳ xóa các phiên hết hạn mà khách hàng không đăng xuất.
  • Mỗi yêu cầu HTTP yêu cầu tra cứu lưu trữ dữ liệu.
  • Yêu cầu lưu trữ tăng lên khi nhiều người dùng có phiên hoạt động.
  • Nếu có nhiều máy chủ HTTP giao diện người dùng, dữ liệu phiên được lưu trữ cần phải được truy cập bởi tất cả chúng. Điều này có thể là một công việc nhiều hơn một chút so với việc lưu trữ nó trên một máy chủ. Vấn đề lớn hơn là kho dữ liệu trở thành một điểm thất bại duy nhất và nó có thể trở thành nút cổ chai.

Mã thông báo web JSON (JWT)

Trong trường hợp thứ hai, dữ liệu được lưu trữ trong JWT được truyền xung quanh thay vì trên máy chủ.

Ưu điểm:

  • Các vấn đề lưu trữ phía máy chủ đã biến mất.
  • Mã phía khách hàng là dễ dàng.

Nhược điểm:

  • Kích thước JWT có thể lớn hơn ID phiên. Nó có thể ảnh hưởng đến hiệu suất mạng vì nó được bao gồm trong mỗi yêu cầu HTTP.
  • Dữ liệu được lưu trữ trong JWT được khách hàng đọc được. Đây có thể là một vấn đề.
  • Phía máy chủ cần mã để tạo, xác nhận và đọc JWT. Nó không khó nhưng có một chút về đường cong học tập và bảo mật phụ thuộc vào nó.

    Bất cứ ai có được một bản sao của khóa ký có thể tạo JWT. Bạn có thể không biết khi nào điều này xảy ra.

    Có một lỗi trong một số thư viện chấp nhận bất kỳ JWT nào được ký với thuật toán "không" để bất kỳ ai cũng có thể tạo JWT mà máy chủ sẽ tin tưởng.

  • Để thu hồi JWT trước khi hết hạn, bạn cần sử dụng danh sách hủy bỏ. Điều này đưa bạn trở lại các vấn đề lưu trữ phía máy chủ mà bạn đang cố gắng tránh.

Ôi

Thông thường OAuth được sử dụng để xác thực (tức là danh tính) nhưng nó có thể được sử dụng để chia sẻ dữ liệu khác như danh sách nội dung mà người dùng đã mua và được quyền tải xuống. Nó cũng có thể được sử dụng để cấp quyền truy cập để ghi vào dữ liệu được lưu trữ bởi bên thứ ba. Bạn có thể sử dụng OAuth để xác thực người dùng và sau đó sử dụng bộ nhớ phía máy chủ hoặc JWT cho dữ liệu phiên.

Ưu điểm:

  • Không có mã để người dùng đăng ký hoặc đặt lại mật khẩu của họ.
  • Không có mã để gửi email với một liên kết xác nhận và sau đó xác nhận địa chỉ.
  • Người dùng không cần phải tìm hiểu / ghi lại tên người dùng và mật khẩu khác.

Nhược điểm:

  • Bạn phụ thuộc vào bên thứ ba để người dùng sử dụng dịch vụ của bạn. Nếu dịch vụ của họ ngừng hoạt động hoặc họ ngừng sử dụng thì bạn cần phải tìm ra thứ khác. Ví dụ: làm thế nào để bạn di chuyển dữ liệu tài khoản của người dùng nếu danh tính của họ thay đổi từ "foo@a.com" sang "bar@b.com"?
  • Thông thường bạn phải viết mã cho mỗi nhà cung cấp. ví dụ: Google, Facebook, Twitter.
  • Bạn hoặc người dùng của bạn có thể có mối quan tâm riêng tư. Các nhà cung cấp biết người dùng nào của họ sử dụng dịch vụ của bạn.
  • Bạn đang tin tưởng nhà cung cấp. Nhà cung cấp có thể phát hành mã thông báo hợp lệ cho một người dùng cho người khác. Điều này có thể cho mục đích hợp pháp hoặc không.

Điều khoản khác

  • Cả ID phiên và JWT đều có thể được sao chép và sử dụng bởi nhiều người dùng. Bạn có thể lưu trữ địa chỉ IP của máy khách trong JWT và xác thực nó nhưng điều đó ngăn khách hàng chuyển vùng từ Wi-Fi sang di động.

Để thêm vào câu trả lời của bạn, oAuth có thể không hữu ích khi người dùng muốn đăng ký bằng tài khoản công ty của họ thường không được liên kết hoặc liên kết với bất kỳ trang web mạng xã hội hoặc google nào.
Aftab Naveed

5
Tôi không biết tại sao đây là câu trả lời được chấp nhận? nó không trả lời câu hỏi thực sự, chỉ cần cải cách đề cập theo cách khác
AMD

1
Bạn nói: "Dữ liệu được lưu trữ trong JWT có thể đọc được bởi khách hàng. Đây có thể là một vấn đề .. Tại sao không sử dụng JWE nếu đó là một vấn đề?
Bạc

Câu trả lời này gây nhầm lẫn giữa táo và cam. Bạn không nên so sánh chúng với OAuth 2.0 (thông số "ủy quyền"). Những gì OP cần biết là: "Luồng mật khẩu của chủ sở hữu tài nguyên" - đó là xác thực dưới dạng cấp.
Onur Yıldırım

5

Hãy tự hỏi tại sao bạn cần làm mất hiệu lực mã thông báo ban đầu.

Một người dùng đăng nhập, một mã thông báo được tạo và tắt ứng dụng.

Người dùng nhấn đăng xuất, một mã thông báo mới được tạo và thay thế mã thông báo gốc. Một lần nữa, tất cả đều tốt.

Bạn dường như đang lo lắng về trường hợp cả hai mã thông báo treo xung quanh. Điều gì xảy ra nếu người dùng đăng xuất và sau đó bằng cách nào đó thực hiện yêu cầu bằng cách sử dụng mã thông báo đã đăng nhập. Kịch bản này thực tế như thế nào? Đây chỉ là một vấn đề trong quá trình đăng xuất hoặc có nhiều tình huống có thể xảy ra khi nhiều mã thông báo có thể là một vấn đề?

Bản thân tôi không nghĩ rằng nó đáng để lo lắng. Nếu ai đó đang chặn và giải mã dữ liệu https được mã hóa của bạn thì bạn có vấn đề lớn hơn nhiều.

Bạn có thể cung cấp cho mình một số bảo vệ bổ sung bằng cách đặt thời gian hết hạn trên mã thông báo gốc. Vì vậy, nếu cuối cùng bị đánh cắp hoặc một cái gì đó thì nó sẽ chỉ tốt trong một khoảng thời gian ngắn.

Nếu không, tôi nghĩ bạn sẽ cần phải có thông tin trạng thái trên máy chủ. Không mã thông báo danh sách đen mà thay vào đó hãy liệt kê danh sách chữ ký của mã thông báo hiện tại.


2
Nếu bạn cho rằng một số khách hàng của bạn là độc hại, thì dễ dàng thấy rằng một phiên sẽ được sao chép và sử dụng lại, và bạn cần phải chống lại điều này trên máy chủ.
Michael Shaw

1
Ý tưởng tồi, điều này có thể được sử dụng sau này bởi tin tặc, hoặc chỉ bị ép buộc ...
CROSP

2
Hãy tưởng tượng người dùng muốn đăng xuất khỏi tất cả các thiết bị khác, sử dụng JWT là không thể.
AMD

@amd không được? Điều gì xảy ra nếu tôi thêm nonce = (ngẫu nhiên) và nếu người dùng đăng xuất, thay thế nonce. Có vẻ đơn giản và hiệu quả.
Simon B.

3

Bạn có thể xử lý các sự cố JWT mà bạn đã đề cập bằng cách lưu trữ giá trị muối cùng với người dùng và sử dụng muối làm một phần của mã thông báo cho người dùng. Sau đó, khi bạn cần vô hiệu hóa mã thông báo, chỉ cần thay đổi muối.

Tôi biết đó là một vài năm nhưng tôi thực sự sẽ làm điều này khác đi. Tôi nghĩ rằng tôi sẽ đảm bảo rằng các mã thông báo truy cập có thời gian tồn tại tương đối ngắn, nói một giờ. Tôi cũng chắc chắn sử dụng mã thông báo làm mới có trạng thái trên máy chủ và sau đó khi tôi muốn kết thúc phiên của ai đó, tôi sẽ thu hồi mã thông báo làm mới bằng cách xóa mã khỏi máy chủ. Sau một giờ, người dùng sẽ đăng xuất và sẽ phải đăng nhập lại để lấy lại quyền truy cập.


4
Nhưng một lần nữa, nó trở nên đầy trạng thái trong trường hợp này, vậy lý do để tạo muối hoặc sử dụng bất kỳ phương pháp nào khác, bạn có thể lưu trữ mã thông báo đơn giản trong bảng và xóa khi cần vô hiệu
CROSP

2
Bạn cũng có thể làm mất hiệu lực dựa trên thời gian.
RibaldEddie

Sự khác biệt giữa thời gian hết hạn trong trường hợp này là gì? Làm cách nào tôi có thể làm mất hiệu lực mã thông báo dựa trên thời gian khi người dùng muốn đăng xuất khỏi ứng dụng khách di động? Dường như không có cách nào để API không trạng thái trong trường hợp này. Giải pháp phù hợp và an toàn nhất là gì?
CROSP

2
Điều thích hợp nhất để đăng xuất từ ​​một thiết bị duy nhất là đảm bảo rằng bạn sử dụng clientId ngoài muối. Tôi đề nghị bạn nhìn vào thông số kỹ thuật mã thông báo mang Oauth-jwt để hiểu rõ hơn.
RibaldEddie

Cảm ơn câu trả lời, nhưng tôi không hiểu tại sao tôi nên sử dụng OAuth trong trường hợp này.
CROSP
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.