54

Tôi muốn người dùng có thể xác thực ứng dụng Firebase của mình bằng nhiều nhà cung cấp xác thực khác nhau, chẳng hạn như Facebook, Twitter hoặc Github. Khi đã được xác thực, tôi muốn người dùng có quyền truy cập vào cùng một tài khoản bất kể họ đã sử dụng phương thức xác thực nào.Tôi làm cách nào để đăng nhập bằng nhiều dịch vụ xã hội với Firebase?

Nói cách khác, tôi muốn hợp nhất nhiều phương thức xác thực vào một tài khoản trong ứng dụng của mình. Tôi làm cách nào để thực hiện điều này trong ứng dụng Firebase?

Trả lời

55

Cập nhật (20.160.521): căn cứ hỏa lực vừa phát hành một bản cập nhật lớn đến sản phẩm Firebase Authentication của nó, mà bây giờ cho phép một người sử dụng duy nhất để liên kết tài khoản từ các nhà cung cấp hỗ trợ khác nhau. Để tìm hiểu thêm về tính năng này, hãy đọc tài liệu cho iOS, WebAndroid. Câu trả lời dưới đây được để lại vì lý do lịch sử. dịch vụ căn cứ hỏa lực


Cốt lõi cung cấp một số phương pháp để xác thực: https://www.firebase.com/docs/security/authentication.html

Tại cốt lõi của nó, căn cứ hỏa lực sử dụng thẻ JWT an toàn để xác thực. Bất kỳ thứ gì dẫn đến việc tạo mã thông báo JWT (chẳng hạn như sử dụng thư viện JWT trên máy chủ của riêng bạn) sẽ hoạt động để xác thực người dùng của bạn với Firebase, vì vậy bạn có toàn quyền kiểm soát quy trình xác thực.

Firebase cung cấp dịch vụ được gọi là Đăng nhập đơn giản Firebase, là một cách để tạo các mã thông báo này (điều này cung cấp cho Facebook, Twitter, vv auth của chúng tôi). Nó dành cho các kịch bản auth phổ biến để bạn có thể bắt đầu và chạy nhanh chóng mà không có máy chủ, nhưng nó không phải là cách duy nhất để xác thực và không phải là giải pháp toàn diện.

Dưới đây là một cách tiếp cận để cho phép đăng nhập với nhiều nhà cung cấp sử dụng căn cứ hỏa lực đơn giản Login:

  1. Cất giữ một định danh người dùng kinh điển cho mỗi người dùng, và một bản đồ cho mỗi nhà cung cấp cụ thể định danh với một id kinh điển.
  2. Cập nhật các quy tắc bảo mật của bạn để khớp với bất kỳ thông tin đăng nhập nào trên tài khoản người dùng được cấp thay vì chỉ một tài khoản.

Trong thực tế, các quy tắc an ninh có thể trông như thế này, giả sử bạn muốn kích hoạt cả Twitter và Facebook xác thực (hoặc cho phép người dùng tạo một tài khoản với một và sau đó thêm cái khác):

{ 
    "users": { 
    "$userid": { 
     // Require the user to be logged in, and make sure their current credentials 
     // match at least one of the credentials listed below, unless we're creating 
     // a new account from scratch. 
     ".write": "auth != null && 
     (data.val() === null || 
     (auth.provider === 'facebook' && auth.id === data.child('facebook/id').val() || 
     (auth.provider === 'twitter' && auth.id === data.child('twitter/id').val()))" 
    } 
    }, 
    "user-mappings": { 
    // Only allow users to read the user id mapping for their own account. 
    "facebook": { 
     "$fbuid": { 
     ".read": "auth != null && auth.provider === 'facebook' && auth.id === $fbuid", 
     ".write": "auth != null && 
      (data.val() == null || 
      root.child('users').child(data.val()).child('facebook-id').val() == auth.id)" 
     } 
    }, 
    "twitter": { 
     "$twuid": { 
     ".read": "auth != null && auth.provider === 'twitter' && auth.id === $twuid", 
     ".write": "auth != null && 
      (data.val() == null || 
      root.child('users').child(data.val()).child('twitter-id').val() == auth.id)" 
     } 
    } 
    } 
} 

Trong ví dụ này, bạn lưu trữ một id người dùng toàn cầu (có thể là bất kỳ thứ gì bạn chọn) và duy trì ánh xạ giữa Facebook, Twitter, vv cơ chế xác thực cho bản ghi người dùng chính. Sau khi đăng nhập cho từng người dùng, bạn sẽ tìm nạp bản ghi người dùng chính từ ánh xạ người dùng và sử dụng id đó làm cửa hàng chính của dữ liệu người dùng và hành động. Ở trên cũng hạn chế và xác nhận dữ liệu trong ánh xạ người dùng sao cho nó chỉ có thể được viết bởi người dùng thích hợp đã có cùng tên người dùng Facebook, Twitter, v.v. dưới/users/$ userid/(facebook-id | twitter -id | etc-id).

Phương pháp này sẽ cho phép bạn bắt đầu và chạy nhanh. Tuy nhiên, nếu bạn có một trường hợp sử dụng phức tạp và muốn kiểm soát hoàn toàn trải nghiệm auth, bạn có thể chạy mã auth của riêng bạn trên các máy chủ của riêng bạn.Có nhiều thư viện nguồn mở hữu ích mà bạn có thể sử dụng để thực hiện việc này, chẳng hạn như everyauthpassport.

Bạn cũng có thể xác thực bằng cách sử dụng nhà cung cấp xác thực bên thứ 3. Ví dụ, bạn có thể sử dụng Singly, trong đó có một loạt các tích hợp out-of-the-box mà không cần phải viết bất kỳ mã phía máy chủ nào.

+1

Tôi có một vài câu hỏi cho bạn về chiến lược này tìm thấy ở đây: http://stackoverflow.com/questions/22886053/can-the-firebase-auth-object -handle-synchronaneous-authentication-types –

+0

Tôi không thể thấy sự khác biệt giữa '.child ('twitter/id'). val()' và '.child ('twitter-id'). val()'. Cả hai tham chiếu khác nhau? Tôi đã không bắt được nó. – Jobsamuel

+0

Cảm ơn rất nhiều về ví dụ lập bản đồ. Có thể theo dõi một số mã về cách thực hiện điều này trên iOS không? –

16

Tôi biết bài đăng này tồn tại trong nhiều tháng nhưng khi tôi gặp vấn đề này, phải mất rất nhiều thời gian để làm cho mã linh hoạt hơn. Dựa trên mã Andrew ở trên, tôi đã chỉnh sửa mã một chút.

mẫu lưu trữ dữ liệu:

userMappings 
|---facebook:777 
| |---user:"123" 
|---twitter:888 
    |---user:"123" 
users 
|---123 
    |---userMappings 
     |---facebook: "facebook:777" 
     |---twitter: "twitter:888" 

quy tắc bảo mật:

"userMappings": { 
    "$login_id": { 
    ".read": "$login_id === auth.uid", 
    ".write": "auth!== null && (data.val() === null || $login_id === auth.uid)" 
    } 
}, 

"users": { 
    "$user_id": { 
    ".read": "data.child('userMappings/'+auth.provider).val()===auth.uid", 
    ".write": "auth!= null && (data.val() === null || data.child('userMappings/'+auth.provider).val()===auth.uid)" 
    } 
} 

Vì vậy userMappings vẫn là thông tin đầu tiên chúng ta nhìn lên khi đăng nhập bằng Facebook, Twitter ... . userMappings ' người dùng sẽ trỏ đến tài khoản chính trong người dùng. Vì vậy, sau khi đăng nhập bằng Facebook hoặc Twitter, chúng tôi có thể tra cứu tài khoản người dùng chính. Trong người dùng, chúng tôi lưu danh sách userMapping có thể truy cập vào dữ liệu của nó.

Khi tạo người dùng mới, trước tiên chúng tôi phải tạo một tài khoản ở số người dùng. Id cho người dùng trong người dùng có thể là bất cứ điều gì chúng tôi muốn. Điều này là linh hoạt vì chúng tôi có thể cung cấp thêm phương thức đăng nhập như Google, Github mà không cần thêm quy tắc bảo mật khác.

+1

Điều này có vẻ như một giải pháp tuyệt vời, nhưng nó khiến tôi tự hỏi/bị chặn trong một khía cạnh: yêu cầu với auth.uid chính xác sẽ có thể truy cập vào "userMapping" cần, tự nhiên (kiểm tra!), Và cũng sẽ có thể truy cập vào "người dùng" nó cần bằng cách tra cứu trên "userMappings" của con (hơi clunky, nhưng kiểm tra!). Nhưng khi chúng ta có dữ liệu/trường khác, hãy nói "userActivity" hoặc "userPosts", làm cách nào để một trường chỉ có thể ghi được bởi người dùng đã tạo chúng? Có vẻ như họ cũng sẽ phải có con "userMappings" với tất cả các khóa đăng nhập cho người dùng đó .. – tydbwjiiofj23iof2jiojf2ifj3i2

+0

@MathewHuuskoV: Tôi nghĩ trong "userActivity" hoặc "userPosts", ... chúng tôi có thể kiểm tra quy tắc bảo mật bằng cách sử dụng biến cố định "root" để tìm kiếm ID người dùng trong userMappings. Ví dụ. ".write": "root.child ('userMappings /' + auth.uid) .child ('người dùng'). val() === data.child ('tác giả'). val()". 'Tác giả' nào chứa ID người dùng của tác giả bài đăng. – Kuma

+1

Có ai đó đã triển khai một cái gì đó như thế này chưa? Có bất kỳ ví dụ mã nào cho loại giải pháp này không? Tôi muốn thêm đăng nhập Firebase - vào cùng một tài khoản - sử dụng email/mật khẩu hoặc Facebook vào ứng dụng iOS của tôi. Tôi thấy một vài tình huống khiến toàn bộ nội dung trở nên phức tạp, tùy thuộc vào cách người dùng đăng nhập và nếu trước đó người dùng đã tạo tài khoản bằng email hoặc Facebook. Ví dụ: nếu người dùng đăng nhập bằng Facebook, nhưng trước đây chỉ sử dụng email/mật khẩu để đăng nhập, tôi phải tìm người dùng phù hợp trong cơ sở dữ liệu Firebase của mình như thế nào? Hoặc ngược lại. – andlin

2

Tôi vừa mới tạo ra một nhà thiết angularfire để xử lý này cho chúng ta: angularfire-multi-auth

0

Tôi đã dành khá nhiều thời gian suy nghĩ trong một giải pháp tốt, và IMHO để có thể đăng ký từ bất kỳ nhà cung cấp chỉ là khó hiểu. Trong giao diện người dùng của tôi, tôi luôn yêu cầu đăng ký email, do đó, người dùng đăng nhập bằng facebook và google +, chẳng hạn, sẽ được ghi lại là người dùng giống nhau khi anh ấy thông báo email của mình.

Bằng cách này, Dữ liệu mẫu do Kuma đề xuất không cần phải sao chép userMappings.

mẫu Store Data:

userMappings 
|---facebook:777 
| |---user:"123" 
|---twitter:888 
    |---user:"123" 
users 
|---123 
    |---user data 
Các vấn đề liên quan