2011-11-29 37 views
51

Tôi đã sử dụng đăng nhập Facebook để xác định người dùng. Khi một người dùng mới đến, tôi lưu trữ userID của họ trong cơ sở dữ liệu của tôi. Lần tới khi họ đến, tôi nhận ra ID Facebook của họ và tôi biết người dùng nào đang ở trong cơ sở dữ liệu của tôi.Cách xác định người dùng Google OAuth2?

Bây giờ tôi đang cố gắng làm tương tự với OAuth2 của Google, nhưng làm cách nào tôi có thể nhận ra người dùng?

Google gửi cho tôi nhiều mã và mã thông báo (access_token, id_token, refresh_token), tuy nhiên không có mã nào trong số đó là hằng số. Có nghĩa là nếu tôi đăng xuất và đăng nhập lại sau 2 phút, tất cả 3 giá trị đã thay đổi. Làm cách nào tôi có thể xác định duy nhất người dùng?

Tôi đang sử dụng thư viện khách PHP của họ: "Người nầy là ai" https://code.google.com/p/google-api-php-client/

Trả lời

26

tôi chèn phương pháp này vào google-api-php-client/src/apiClient.php:

public function getUserInfo() 
{ 
    $req = new apiHttpRequest('https://www.googleapis.com/oauth2/v1/userinfo'); 
    // XXX error handling missing, this is just a rough draft 
    $req = $this->auth->sign($req); 
    $resp = $this->io->makeRequest($req)->getResponseBody(); 
    return json_decode($resp, 1); 
} 

Bây giờ tôi có thể gọi:

$client->setAccessToken($_SESSION[ 'token' ]); 
$userinfo = $client->getUserInfo(); 

Nó trả về một mảng như thế này (cộng e-mail nếu phạm vi đó đã được yêu cầu):

Array 
(
    [id] => 1045636599999999999 
    [name] => Tim Strehle 
    [given_name] => Tim 
    [family_name] => Strehle 
    [locale] => de 
) 

Giải pháp có nguồn gốc từ chủ đề này: https://groups.google.com/forum/#!msg/google-api-php-client/o1BRsQ9NvUQ/xa532MxegFIJ

+4

Lưu ý rằng gần đây Google đã thay đổi phản hồi và 'id_token' hiện chứa mã định danh tĩnh trong khóa' sub' thay vì trong khóa 'id' như trước và trong ví dụ trên. AFAIK, thay đổi này là cách giải thích của họ về giao thức OpenID Connect. Thật không may, khi tôi viết câu trả lời này có vẻ hơi ngẫu nhiên: đôi khi nó là 'id' và đôi khi nó là' phụ' nên tôi cần hỗ trợ cả hai. –

1

về cơ bản là một dịch vụ; bạn phải yêu cầu quyền truy cập vào phạm vi và sau đó gửi yêu cầu tới tiểu sử trên Google máy chủ tài nguyên để nhận danh tính. Xem OAuth 2.0 for Login để biết chi tiết.

+0

Điều này có vẻ chính xác nhất về mặt kỹ thuật, nhưng thiếu chi tiết bổ sung mà câu trả lời hiện được chấp nhận. Kết hợp hai câu trả lời với nhau và bạn có vàng. –

76

Như những người khác đã đề cập, bạn có thể gửi một GET để https://www.googleapis.com/oauth2/v3/userinfo, sử dụng người mang OAuth2 mã thông báo bạn vừa nhận được, và bạn sẽ nhận được một phản ứng với một số thông tin về người dùng (id, tên, v.v.)

Điều đáng nói là Google triển khai OpenID Connect và điểm cuối của thông tin người dùng này chỉ là một phần của nó.

OpenID Connect là lớp xác thực ở trên cùng của OAuth2. Khi trao đổi ủy quyền code tại điểm cuối mã thông báo của Google, bạn sẽ nhận được mã thông báo truy cập (tham số access_token) cũng như mã thông báo ID OpenID Connect (tham số id_token).

Cả hai mã thông báo này là JWT (Mã thông báo web JSON, http://tools.ietf.org/html/draft-ietf-oauth-json-web-token).

Nếu bạn giải mã chúng, bạn sẽ nhận được một số xác nhận, bao gồm id của người dùng. Nếu bạn liên kết ID này với người dùng trong DB của mình, bạn có thể ngay lập tức nhận dạng chúng mà không phải thực hiện thêm userinfo GET (tiết kiệm thời gian).

Như đã đề cập trong các nhận xét, các mã thông báo này được ký bằng khóa riêng của Google và bạn có thể muốn xác minh chữ ký bằng khóa công khai của Google (https://www.googleapis.com/oauth2/v3/certs) để đảm bảo chúng là xác thực.

Bạn có thể xem những gì trong JWT bằng cách dán nó tại https://jwt.io/ (cuộn xuống cho trình gỡ lỗi JWT). Các khẳng định giống như thế:

{ 
    "iss":"accounts.google.com", 
    "id":"1625346125341653", 
    "cid":"8932346534566-hoaf42fgdfgie1lm5nnl5675g7f167ovk8.apps.googleusercontent.com", 
    "aud":"8932346534566-hoaf42fgdfgie1lm5nnl5675g7f167ovk8.apps.googleusercontent.com", 
    "token_hash":"WQfLjdG1mDJHgJutmkjhKDCdA", 
    "iat":1567923785, 
    "exp":1350926995 
} 

Ngoài ra còn có thư viện cho các ngôn ngữ lập trình khác nhau để programatically giải mã JWTs.

PS: để nhận danh sách URL và tính năng cập nhật được nhà cung cấp OpenID Connect của Google hỗ trợ, bạn có thể kiểm tra URL đó: https://accounts.google.com/.well-known/openid-configuration.

+1

Có, nhưng để sử dụng thông tin này một cách an toàn, bạn phải xác minh chữ ký của JWT, mà bạn cần khóa công khai. Bất kỳ ý tưởng nơi google làm cho khóa công khai của họ có sẵn? – jazmit

+7

OK, đã tìm thấy: https://www.googleapis.com/oauth2/v1/certs Tôi cũng nên chỉ ra rằng việc xác minh là hoàn toàn cần thiết, nếu không kẻ tấn công có thể dễ dàng đăng nhập vào ứng dụng của bạn bằng bất kỳ đăng ký nào đã được đăng ký tài khoản Google. – jazmit

+0

@jamesinchina Và làm thế nào để bạn nghĩ rằng cuộc tấn công này là có thể nếu thông tin chính nó đến trực tiếp từ Google, không phải từ kẻ tấn công? – stroncium

1

JWTs có thể được xác thực cục bộ bằng khóa công khai, (Google API Client Library tải xuống và lưu trữ khóa công khai tự động) kiểm tra mã thông báo bên phía Google thông qua điểm cuối https://www.googleapis.com/oauth2/v1/tokeninfo là cần thiết để kiểm tra xem truy cập cho ứng dụng đã được bị thu hồi kể từ khi tạo mã thông báo.

9

Cần lưu ý rằng API OpenID Connect không trả lại thuộc tính id nữa.

Hiện tại thuộc tính sub đóng vai trò là nhận dạng người dùng duy nhất.

Xem Google Dev OpenID Connect UserInfo

+1

Bạn không chắc chắn điều này là đúng. Mặc dù những gì các tài liệu nhà nước, nếu tôi khởi động lại máy chủ auth của tôi, xóa bộ nhớ cache và đăng nhập lại, 'phụ' là khác nhau. – HockeyJ

+0

Có ai khác có vấn đề của HockeyJ với 'phụ' thay đổi cho cùng một thông tin đăng nhập không? – dardawk

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