2015-05-14 16 views
9

Tôi đang cố gắng thiết kế các API REST để hỗ trợ các ứng dụng di động khác nhau (các ứng dụng iOS và Android). Các ứng dụng này sẽ cho phép người dùng đăng nhập bằng cách sử dụng đăng nhập facebook cùng với xác thực email của chính chúng tôi. Bạn có thể tham khảo sơ đồ dưới đây để hiểu thiết kế của tôiThiết kế Kiến trúc - REST API để hỗ trợ Đăng nhập Facebook được thực hiện bởi Ứng dụng di động

Design flow

Có hai cấp độ của nơi cấp phép mất:

Đầu tiên là "Khách hàng (hoặc App) Authorization" có sử dụng OAuth2. Vì vậy, khi người dùng cài đặt ứng dụng của chúng tôi trên thiết bị di động và bắt đầu ứng dụng, thì điều đầu tiên, ứng dụng tạo "Ủy quyền ứng dụng (Client)" như được hiển thị trong sơ đồ trên (hình ảnh thứ nhất). Và máy chủ gửi lại một thời gian dài access_token cho khách hàng để sử dụng cho tất cả các cuộc gọi tiếp theo. Đây là câu hỏi của tôi là:

Q1) Bạn có thể thấy khách hàng đang gửi client_keyclient_secret và tôi lưu trữ chúng trong bảng client_info. Bí mật này có nên ở dạng văn bản thuần túy hay phải ở định dạng có thể giải mã được không? Nếu tôi mã hóa nó, tôi vẫn cần giữ mã khóa ở đâu đó trong hệ thống của mình. Vậy làm thế nào nó sẽ làm cho nó an toàn? Cũng trong mọi cuộc gọi, giải mã sẽ là một chi phí.

Q2) Có được lưu vào bộ nhớ cache access_token cho ứng dụng khách ở định dạng văn bản thuần túy khi sử dụng lại và sử dụng bộ nhớ cache đó trước không?

Q3) Để an toàn hơn, tôi yêu cầu khách hàng gửi appsecret_proof để đảm bảo access_token, họ đang gửi chỉ thuộc về khách hàng này. Nó sử dụng cùng một khái niệm như Facebook https://developers.facebook.com/docs/graph-api/securing-requests#appsecret_proof. Và nó là hash_hmac('sha256', access_token, client_secret)

Q4) Chúng tôi sẽ chỉ có 2 ứng dụng dành cho thiết bị di động (mỗi cho iOS và Android) và không cung cấp cho bên thứ ba sử dụng API của chúng tôi để phát triển các ứng dụng khác. Điều đó có nghĩa, bảng client_info của chúng tôi sẽ chỉ có hai hàng một cho mỗi loại ứng dụng. Vì vậy, có ổn không, trong mã ứng dụng, chúng tôi giữ mã số client_keyclient_secret được mã hóa cứng? Nếu có, thì trong tương lai khi chúng ta phải làm mất hiệu lực và sử dụng bí mật mới thì làm thế nào chúng ta sẽ đạt được thay thế những thông tin đó?

Q5) Vì đây là ứng dụng của riêng chúng tôi trong vài năm nên sẽ có nhiều access_token sẽ được tạo trên cùng một số client_keyclient_secret. Để lưu tất cả chúng, bạn nên lưu client_key làm khóa và array of all access_tokens làm giá trị trong redis. Trong tương lai, khi chúng tôi sẽ mở API của chúng tôi cho bên thứ ba, thì thiết kế lưu trữ redis này vẫn có thể mở rộng?

=================

Sau đó, người dùng quyết định thực hiện một số thao tác trên ứng dụng của tôi, cho rằng chúng ta cần phải sử dụng để đăng nhập vào tài khoản của mình. Đối với người dùng đó, hãy nhấp vào "đăng nhập facebook". Ứng dụng của tôi nhận được facebook access_token và id người dùng fb từ facebook và chuyển các thông tin đó tới máy chủ API (như được hiển thị trong biểu đồ thứ 2). Máy chủ API nhận mã thông báo đó và gọi API facebook để xác thực access_token của nó. Khi mã thông báo được xác thực, máy chủ sử dụng một số siêu dữ liệu có liên quan đến người dùng đó cùng với mã thông báo truy cập FB để tạo user_access_token của riêng chúng tôi, cho phép nói utoken. Và vượt qua điều đó utoken quay lại khách hàng để trả lại trong mọi cuộc gọi API cụ thể của người dùng tiếp theo. Dưới đây là câu hỏi của tôi là:

Q1) Có ok để lưu rằng utoken trong cơ sở dữ liệu, user_token bảng. Nên utoken này ở dạng văn bản thuần túy hay phải ở định dạng có thể giải mã được? Nếu tôi mã hóa nó, tôi vẫn cần giữ mã khóa ở đâu đó trong hệ thống của mình. Vậy làm thế nào nó sẽ làm cho nó an toàn? Cũng trong mọi cuộc gọi, giải mã sẽ là một chi phí.

Q2) Trong mọi cuộc gọi API cụ thể của người dùng, tôi có nên gọi cho facebook mỗi lần kiểm tra facebook access_token vẫn hợp lệ không? Tôi tin rằng tôi không nên, vì điều đó sẽ không nhận được bất cứ điều gì với tôi. Xin lưu ý, Facebook CHỈ được sử dụng cho "đăng nhập facebook".

Q3) Thông tin tôi cần mã hóa để tạo ra utoken là gì? Tôi đang suy nghĩ để có một mảng băm hoặc liên kết của người dùng email, user id, rolefacebook token và sau đó tuần tự hóa cấu trúc dữ liệu đó và cuối cùng mã hóa cấu trúc đó. Bạn có nghĩ rằng đó là đủ tốt. Tôi hiểu nó theo yêu cầu của tôi, nhưng như là một ứng dụng tiêu chuẩn hoặc phổ biến, họ có đủ tốt không? Hoặc là có bất kỳ thực hành tốt nhất?

Q4) Khách hàng có nên lưu trữ utoken trong cookie/bộ nhớ cache của mình không? Điều đó không đáng sợ sao?

Q5) Xin lưu ý rằng người dùng có thể có nhiều thiết bị, đăng nhập bằng thông tin xác thực người dùng tương tự. Điều đó có nghĩa, trong bảng user_token, chúng tôi sẽ phải lưu trữ nhiều utokens cho những phiên đăng nhập đó, trong khi tất cả chúng sẽ thuộc về cùng một người dùng. Điều đó có đúng không?

Đề xuất thiết kế hơi quen thuộc với tôi REST API for website which uses Facebook for authentication

Trả lời

0

Q1.1: Không !. Thông tin đăng nhập của khách hàng không được sử dụng theo cách đó. Nếu ứng dụng của bạn là Ứng dụng đơn lẻ hoặc Ứng dụng dành cho thiết bị di động, bạn sẽ bị buộc lưu trữ thông tin đăng nhập ứng dụng khách của bạn trong môi trường không an toàn, máy của người dùng. Bạn nên sử dụng luồng ImLicit của OAuth

Q1.2: Giả sử mã thông báo ngắn ngủi, không có sự cố khi lưu trữ bộ nhớ cache. Chìa khóa của OAuth, ngoài việc đảm bảo rằng bạn có thể dựa vào ứng dụng khác để xác thực người dùng của mình, là bạn thay thế hiệu quả thông tin đăng nhập của người dùng hoặc ứng dụng, đã tồn tại lâu, với một mã thông báo ngắn. Vì vậy, nếu ai đó có quyền truy cập vào mã thông báo, ít nhất, quyền truy cập của họ vào hệ thống sẽ bị giới hạn về thời gian.

Q1.3: Kiểm tra ra rằng tài liệu hướng dẫn facebook: các cuộc gọi API

Graph có thể được thực hiện từ các khách hàng hoặc từ máy chủ của bạn thay mặt cho khách hàng. Cuộc gọi từ máy chủ có thể được bảo mật tốt hơn bằng cách thêm tham số có tên là appsecret_proof.

Điều này quy định rằng appsecret_proof sẽ được sử dụng cho các cuộc gọi từ máy chủ thay mặt người dùng. Vấn đề ở đây phải làm với Q1.1. Nếu bạn đang lưu trữ client_secret trong thiết bị của người dùng, họ có thể tạo ra appsecret_proof.

Q1.4: Một lần nữa, Không! Bạn nên đọc kỹ Thông số kỹ thuật OAuth và hiểu các loại luồng khác nhau và thời điểm sử dụng từng loại. Cũng xin lưu ý rằng nếu bạn cung cấp API cho Ứng dụng, API sẽ được công khai cho bất kỳ ai lạm dụng. Sự khác biệt duy nhất là nó không phải là tài liệu. Điều tương tự cũng sẽ xảy ra với một ứng dụng web. Khi nó ở trên internet, tôi có thể viết một scraper và lạm dụng các ứng dụng Web. Điều này là hoàn toàn bình thường, chỉ cần nhớ rằng bất cứ điều gì trên internet không phải là tư nhân, nó chỉ là không có giấy tờ.

Q1.5: Một lần nữa, mã thông báo phải ngắn gọn. Nếu tuổi thọ của họ giống với thông tin đăng nhập, cho đến khi người dùng thay đổi chúng, thì mã thông báo sẽ mất mục đích của họ.

Q2.1: Bạn nên lưu mã thông báo đó Một kiến ​​trúc ReST sử dụng ràng buộc bộ đệm máy khách.

Q2.2: Tôi không nghĩ vậy. Facebook chỉ cho bạn biết rằng người dùng đã nhận được mã thông báo đó có một số nhận dạng (ví dụ: email) mà bạn có thể liên kết với người dùng trong hệ thống của mình. Một khi bạn biết rằng liên kết, bạn không nên quan tâm nhiều đến mã thông báo Facebook, nhưng để thực hiện cuộc gọi đến Facebook API. Nhưng bạn nói, bạn đang sử dụng nó chỉ để đăng nhập.

Q2.3: Có vẻ không tệ nhưng hãy kiểm tra lại Đặc tả Oauth khi bạn có vẻ đang xây dựng luồng Implicit và sử dụng mã thông báo JWT. Theo những gì bạn muốn lưu trữ trong mã thông báo của bạn, có vẻ tốt.

Q2.4: Mã thông báo JWT phải được khách hàng lưu vào bộ nhớ cache. Không có gì đáng sợ, bởi vì chúng mờ đục đối với khách hàng khi chúng được mã hóa. Máy khách gửi mã thông báo JWT với mỗi yêu cầu và máy chủ API giải mã mã thông báo bằng khóa riêng (không bao giờ được tiếp xúc bên ngoài máy chủ) và có thể kiểm tra danh tính của người dùng.

Q2.5: Nhớ các mã thông báo ngắn. Mã thông báo phải hết hạn !.

Các vấn đề liên quan