Xử lý gia hạn mã thông báo / hết hạn phiên trong API RESTful


17

Tôi đang xây dựng API RESTful sử dụng mã thông báo JWT để xác thực người dùng (do loginđiểm cuối phát hành và được gửi trong tất cả các tiêu đề sau đó) và mã thông báo cần được làm mới sau một khoảng thời gian cố định (gọi renewđiểm cuối, trả về mã thông báo được gia hạn ).

Có thể phiên API của người dùng trở nên không hợp lệ trước khi mã thông báo hết hạn, do đó tất cả các điểm cuối của tôi bắt đầu bằng cách kiểm tra xem: 1) mã thông báo vẫn còn hiệu lực và 2) phiên của người dùng vẫn hợp lệ. Không có cách nào để vô hiệu hóa trực tiếp mã thông báo, bởi vì khách hàng lưu trữ cục bộ.

Do đó, tất cả các điểm cuối của tôi phải báo hiệu cho khách hàng của tôi về hai điều kiện có thể: 1) rằng đã đến lúc phải gia hạn mã thông báo hoặc 2) rằng phiên đã trở nên không hợp lệ và chúng không còn được phép truy cập hệ thống. Tôi có thể nghĩ ra hai lựa chọn thay thế cho các điểm cuối của mình để báo hiệu cho khách hàng của họ khi một trong hai điều kiện xảy ra (giả sử rằng các máy khách có thể được điều chỉnh theo một trong hai tùy chọn):

  1. Trả lại mã http 401 (trái phép) nếu phiên trở nên không hợp lệ hoặc trả lại mã 412 (điều kiện tiên quyết không thành công) khi mã thông báo đã hết hạn và đã đến lúc gọi renewđiểm cuối, mã này sẽ trả về mã 200 (ok).
  2. Trả về 401 để báo hiệu rằng phiên không hợp lệ hoặc mã thông báo đã hết hạn. Trong trường hợp này, máy khách sẽ gọi ngay renewđiểm cuối, nếu nó trả về 200 thì mã thông báo được làm mới, nhưng nếu renewcũng trả về 401 thì có nghĩa là máy khách đã ra khỏi hệ thống.

Bạn muốn giới thiệu phương án nào trong hai phương án trên? Cái nào sẽ chuẩn hơn, đơn giản hơn để hiểu và / hoặc nhiều RESTful hơn? Hoặc bạn muốn đề xuất một cách tiếp cận khác nhau hoàn toàn? Bạn có thấy bất kỳ vấn đề rõ ràng hoặc rủi ro bảo mật với một trong hai tùy chọn không? Thêm điểm nếu câu trả lời của bạn bao gồm các tài liệu tham khảo bên ngoài hỗ trợ ý kiến ​​của bạn.

CẬP NHẬT

Các bạn, xin vui lòng tập trung vào câu hỏi thực tế - trong số hai lựa chọn thay thế mã http để báo hiệu sự vô hiệu hóa gia hạn / phiên là tốt nhất? Đừng bận tâm rằng hệ thống của tôi sử dụng các phiên JWT phía máy chủ, đó là một đặc thù của API của tôi đối với các quy tắc kinh doanh rất cụ thể và không phải là phần tôi đang tìm kiếm trợ giúp;)


Làm thế nào một phiên của người dùng trở nên không hợp lệ trước khi mã thông báo hết hạn, giả sử thời gian hết hạn ngắn (khoảng 5 phút)?
Jack

Do quy tắc kinh doanh, một phần khác của hệ thống có thể làm mất hiệu lực phiên.
Óscar López

1
JWT là để chứng minh danh tính, vì trong "yêu cầu này được chứng minh là từ người dùng X". Nếu quy tắc kinh doanh của bạn là một cái gì đó như "người dùng X không còn được phép tương tác với tài nguyên Y", thì đó là thứ cần được kiểm tra riêng với JWT.
Jack

@Jack chính xác! đó chính xác là quan điểm của tôi và lý do tại sao tôi phải sử dụng một lớp bổ sung, có trạng thái để lưu thông tin phiên. Plain JWT, tốt đẹp như nó có thể, chỉ là không cắt giảm cho công việc.
Óscar López

1
Bạn có thể quan tâm đến câu trả lời của tôi sau đó :)
Jack

Câu trả lời:


22

Điều này nghe có vẻ như một trường hợp xác thực so với ủy quyền .

JWT là các khiếu nại được ký bằng mật mã về người khởi tạo yêu cầu. JWT có thể chứa các khiếu nại như "Yêu cầu này dành cho người dùng X" và "Người dùng X có vai trò quản trị viên". Lấy và cung cấp bằng chứng này thông qua mật khẩu, chữ ký và TLS là miền xác thực - chứng minh bạn là người bạn nói bạn là ai.

Những khiếu nại đó có ý nghĩa gì với máy chủ của bạn - những gì người dùng và vai trò cụ thể được phép làm - là vấn đề ủy quyền . Sự khác biệt giữa hai có thể được mô tả với hai kịch bản. Giả sử Bob muốn vào phần lưu trữ bị hạn chế trong kho của công ty anh ta, nhưng trước tiên anh ta phải đối phó với một người bảo vệ tên Jim.

Kịch bản A - Xác thực

  • Bob: "Xin chào Jim, tôi muốn vào bộ nhớ bị hạn chế."
  • Jim: "Bạn đã có huy hiệu của bạn?"
  • Bob: "Không, quên nó đi."
  • Jim: "Xin lỗi bạn thân, không có mục nào mà không có huy hiệu."

Kịch bản B - Ủy quyền

  • Bob: "Xin chào Jim, tôi muốn vào bộ nhớ bị hạn chế. Đây là huy hiệu của tôi."
  • Jim: "Này Bob, bạn cần giải phóng mặt bằng cấp 2 để vào đây. Xin lỗi."

Thời gian hết hạn của JWT là một thiết bị xác thực được sử dụng để ngăn người khác ăn cắp chúng. Nếu tất cả JWT của bạn có thời gian hết hạn năm phút, thì đó không phải là vấn đề lớn nếu chúng bị đánh cắp vì chúng sẽ nhanh chóng trở nên vô dụng. Tuy nhiên, quy tắc "hết hạn phiên" mà bạn thảo luận có vẻ như là một vấn đề ủy quyền. Một số thay đổi về trạng thái có nghĩa là người dùng X không còn được phép làm điều gì đó họ từng có thể làm. Chẳng hạn, người dùng Bob có thể đã bị sa thải - không quan trọng là huy hiệu của anh ta nói anh ta là Bob nữa, vì đơn giản là Bob không còn trao cho anh ta bất kỳ quyền hạn nào với công ty.

Hai trường hợp này có mã phản hồi HTTP riêng biệt: 401 Unauthorized403 Forbidden. Mã không may có tên 401 là dành cho các vấn đề xác thực như thông tin đăng nhập bị thiếu, hết hạn hoặc bị thu hồi. 403 là để ủy quyền, nơi máy chủ biết chính xác bạn là ai nhưng bạn không được phép làm điều bạn đang cố gắng làm. Trong trường hợp tài khoản của người dùng bị xóa, cố gắng làm điều gì đó với JWT ở điểm cuối sẽ dẫn đến phản hồi 403 Bị cấm. Tuy nhiên, nếu JWT hết hạn, kết quả chính xác sẽ là 401 trái phép.

Một mô hình JWT phổ biến là có các mã thông báo "tồn tại lâu" và "tồn tại ngắn". Mã thông báo tồn tại lâu được lưu trữ trên máy khách như mã thông báo tồn tại trong thời gian ngắn, nhưng chúng bị giới hạn phạm vi và chỉ được sử dụng với hệ thống ủy quyền của bạn để có được mã thông báo tồn tại ngắn. Các mã thông báo tồn tại lâu dài, như tên gọi của nó, có thời gian hết hạn rất dài - bạn có thể sử dụng chúng để yêu cầu mã thông báo mới trong nhiều ngày hoặc nhiều tuần. Mã thông báo tồn tại ngắn là mã thông báo bạn mô tả, được sử dụng với thời gian hết hạn rất ngắn để tương tác với hệ thống của bạn. Mã thông báo tồn tại lâu rất hữu ích để triển khai chức năng Ghi nhớ, vì vậy bạn không cần cung cấp mật khẩu của mình sau mỗi năm phút để nhận được mã thông báo ngắn mới.

Vấn đề "vô hiệu hóa phiên" mà bạn mô tả âm thanh tương tự như cố gắng vô hiệu hóa JWT tồn tại lâu, vì những người sống ngắn hiếm khi được lưu trữ phía máy chủ trong khi những người sống lâu được theo dõi trong trường hợp họ cần phải thu hồi. Trong một hệ thống như vậy, việc cố gắng có được thông tin đăng nhập với mã thông báo đã bị thu hồi lâu sẽ dẫn đến 401 Không được phép, vì về mặt kỹ thuật, người dùng có thể có được thông tin đăng nhập nhưng mã thông báo họ đang sử dụng không phù hợp với nhiệm vụ. Sau đó, khi người dùng cố gắng lấy mã thông báo tồn tại lâu dài bằng tên người dùng và mật khẩu của họ, hệ thống có thể phản hồi với 403 Bị cấm nếu họ bị loại khỏi hệ thống.


3
Đây là hướng dẫn mà tôi đang tìm kiếm và bạn đã mang đến một cái nhìn sâu sắc rất phù hợp cho cuộc thảo luận - rằng đây là trường hợp xác thực so với ủy quyền và mỗi trường hợp nên được xử lý khác nhau. Cảm ơn!
Óscar López

16

Phiên API của bạn là một thứ hoàn toàn không tồn tại trong thế giới RESTful. Các hoạt động RESTful được coi là không trạng thái, phiên chứa trạng thái và do đó không có chỗ trong thế giới RESTful.

JWT nên là cách duy nhất của bạn để xác định xem người dùng có còn đủ điều kiện để truy cập điểm cuối hay không. Một phiên nên hoàn toàn không có vai trò trong đó. Nếu vậy, bạn không có API RESTful.

Khi bạn loại bỏ hoàn toàn phiên, điều mà nếu bạn đang nhắm đến API RESTful bạn nên làm và chỉ sử dụng JWT làm yếu tố xác thực, người dùng có được phép sử dụng điểm cuối của bạn hay không - trong trường hợp đó, 401 Unauthorizedmã phản hồi là phù hợp - và nên gọi renewđiểm cuối với grant_type=refresh_tokenhoặc bất kỳ nhận dạng nào về gia hạn mà bạn đang sử dụng.

Cập nhật:

Từ nhận xét có vẻ như luồng xác thực của JWT bạn hiện đang sử dụng là không chính xác. Việc xác nhận được cho là như thế này:

  Client        RESTful API      JWT Issuer
     |              |                |
     |----- 1. ---->|                | 
     |              |------ 2. ----->|-----
     |              |                | 3. |
     |              |<----- 4. ------|<----
-----|<---- 5. -----|                |
| 6. |              |                |
---->|----- 7. ---->|                |
     |              |------ 8. ----->|-----
     |              |                | 9. |
     |              |<----- 10. -----|<----
     |              |                |
     |              |------          |
     |              | 11. |          |
     |<---- 12. ----|<-----          |
     |              |                |
     .              .                .

1. Ask RESTful API for a JWT using login endpoint.
2. Ask Issuer to create a new JWT.
3. Create JWT.
4. Return JWT to the RESTful API.
5. Return JWT to Client.
6. Store JWT to append it to all future API requests.
7. Ask for data from API providing JWT as authorization.
8. Send JWT to Issuer for verification.
9. Issuer verifies JWT.
10. Issuer returns 200 OK, verification successful.
11. Retrieve and format data for Client.
12. Return data to Client.

Máy chủ, RESTful APIphải kiểm tra tính hợp lệ của mã thông báo đang được gửi dưới dạng Ủy quyền. Đó không phải là trách nhiệm của Client. Có vẻ như bạn hiện không làm điều này. Thực hiện xác minh JWT theo cách này và bạn hoàn toàn không cần phiên.


Cảm ơn câu trả lời của bạn. Đồng ý, sử dụng phiên sẽ không phải là cách tiếp cận RESTful 100%, nhưng như tôi đã đề cập ở trên, tôi cần từ chối quyền truy cập vào một số người dùng trước khi mã thông báo hết hạn.
Óscar López

2
@ ÓscarLópez Sau đó, chỉ cần vô hiệu hóa các mã thông báo mà người dùng đang sử dụng. Họ sẽ không còn có thể truy cập API bằng mã thông báo được cung cấp (hiện tại sẽ không còn hiệu lực) và bạn không cần phiên.
Andy

1
Các mã thông báo được lưu trữ trên máy khách, làm thế nào tôi có thể làm mất hiệu lực chúng ở đó? Tôi sẽ phải theo dõi xem cái nào là hợp lệ ... và đó là nơi nhà nước xé cái đầu xấu xí của nó. Đôi khi điều đó là không thể tránh khỏi.
Óscar López

Một khách hàng độc hại có thể tiếp tục gửi mã thông báo hợp lệ trước đó miễn là thời gian hết hạn của nó cho phép, nhưng tôi cần đuổi anh ta ra khỏi hệ thống ngay lập tức - do đó, đặt thời gian gia hạn ngắn cũng không phải là một tùy chọn.
Óscar López

4
@Laiv Tôi đã tạo sơ đồ trình tự trong notepad.
Andy

1

Vì vậy, tôi sẽ thú nhận rằng tôi không có ý nghĩa gì khi lo lắng về cách tiếp cận nào là RESTful nhất khi bạn đã phá vỡ các quy ước REST với phiên, nhưng tôi hiểu việc đáp ứng các yêu cầu kinh doanh của bạn.

Từ quan điểm REST, ứng dụng khách được xác thực hoặc không. Kiến trúc không quan tâm nhiều tại sao (đó là trạng thái không cần thiết), vì vậy để trả lời câu hỏi chính của bạn, tôi hoàn toàn không có điểm cuối đổi mới. Một khách hàng đã đăng nhập sẽ luôn gửi JWT của họ và máy chủ luôn xác nhận nó và chấp nhận bằng cách gửi mã Thành công phù hợp dựa trên hành động 200, 201, v.v.) hoặc từ chối với 401 hoặc 403 nếu phù hợp.

Bây giờ, JWT sẽ được liên kết với một tài khoản nào đó. Tài khoản đó có thể bị khóa hoặc điều chỉnh hoặc bất cứ điều gì, và do đó, chính mã thông báo có thể hợp lệ nhưng hành động vẫn bị từ chối ở nơi khác. Nếu trường hợp tài khoản người dùng bị khóa vì các quy tắc kinh doanh, thì đó vẫn là 401 hoặc 403 tùy thuộc vào lượng thông tin bạn muốn cung cấp cho khách hàng (các doanh nghiệp khác nhau có ý kiến ​​khác nhau về điều đó).

Cuối cùng, nếu bạn khẳng định rằng tài khoản có thể được mở khóa và hợp lệ nhưng JWT chỉ cần bị thu hồi, thì tôi sẽ VẪN gắn bó với 401 hoặc 403 và duy trì một cái gì đó như Danh sách hủy bỏ chứng chỉ của JWT không hợp lệ mà bạn có thể đặt , miễn là nó tự dọn sạch khi JWT hết hạn (hầu hết các cơ sở dữ liệu đều có cách để làm điều đó hoặc bạn có thể có các sự kiện trong mã ứng dụng).


jwt có nghĩa là không quốc tịch. thời điểm bạn đặt câu hỏi về nội dung của nó và xác thực nó với db, nó không còn là trạng thái không còn tồn tại do đó trở nên dư thừa vì có các giải pháp tốt hơn cho các phiên chính thức
Stavm
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.