2016-08-21 19 views
11

Tôi đang sử dụng ASP.NET Core để phục vụ API cho ứng dụng khách Android. Android đăng nhập dưới dạng tài khoản Google và chuyển JWT, Mã thông báo ID tới API dưới dạng mã thông báo mang. Tôi có ứng dụng hoạt động, nó vượt qua kiểm tra auth, nhưng tôi không nghĩ rằng nó xác nhận chữ ký token.Xác thực Mã số Thẻ Google

Mỗi tài liệu của Google, tôi có thể gọi url này để làm điều đó: https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123, nhưng tôi không thể tìm thấy móc thích hợp ở phía máy chủ để thực hiện. Cũng theo các tài liệu của Google, tôi bằng cách nào đó có thể sử dụng API Client Access để làm điều đó mà không cần gọi đến máy chủ mỗi lần.

mã cấu hình của tôi:

app.UseJwtBearerAuthentication(new JwtBearerOptions() 
{ 

    Authority = "https://accounts.google.com", 
    Audience = "hiddenfromyou.apps.googleusercontent.com", 
    TokenValidationParameters = new TokenValidationParameters() 
    { 
     ValidateAudience = true, 
     ValidIssuer = "accounts.google.com" 
    }, 
    RequireHttpsMetadata = false, 
    AutomaticAuthenticate = true, 
    AutomaticChallenge = false, 
}); 

Làm thế nào để tôi có được middleware JWTBearer để xác nhận chữ ký? Tôi gần như từ bỏ việc sử dụng phần mềm trung gian MS và cuộn của riêng tôi.

Trả lời

17

Có một vài khác nhau ways trong đó bạn có thể xác nhận tính toàn vẹn của thẻ ID ở phía máy chủ:

  1. "Manually" - liên tục tải khóa công khai của Google, xác minh chữ ký và sau đó mỗi trường, bao gồm cả iss; lợi thế chính (mặc dù một lợi ích nhỏ trong quan điểm của tôi) tôi thấy ở đây là bạn có thể giảm thiểu số lượng yêu cầu được gửi tới Google.
  2. "Tự động" - làm một GET trên thiết bị đầu cuối của Google để xác minh thẻ https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={0}
  3. này Sử dụng một thư viện của Google API Client - như official one.

Sau đây là cách thứ hai có thể nhìn:

private const string GoogleApiTokenInfoUrl = "https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={0}"; 

public ProviderUserDetails GetUserDetails(string providerToken) 
{ 
    var httpClient = new MonitoredHttpClient(); 
    var requestUri = new Uri(string.Format(GoogleApiTokenInfoUrl, providerToken)); 

    HttpResponseMessage httpResponseMessage; 
    try 
    { 
     httpResponseMessage = httpClient.GetAsync(requestUri).Result; 
    } 
    catch (Exception ex) 
    { 
     return null; 
    } 

    if (httpResponseMessage.StatusCode != HttpStatusCode.OK) 
    { 
     return null; 
    } 

    var response = httpResponseMessage.Content.ReadAsStringAsync().Result; 
    var googleApiTokenInfo = JsonConvert.DeserializeObject<GoogleApiTokenInfo>(response); 

    if (!SupportedClientsIds.Contains(googleApiTokenInfo.aud)) 
    { 
     Log.WarnFormat("Google API Token Info aud field ({0}) not containing the required client id", googleApiTokenInfo.aud); 
     return null; 
    } 

    return new ProviderUserDetails 
    { 
     Email = googleApiTokenInfo.email, 
     FirstName = googleApiTokenInfo.given_name, 
     LastName = googleApiTokenInfo.family_name, 
     Locale = googleApiTokenInfo.locale, 
     Name = googleApiTokenInfo.name, 
     ProviderUserId = googleApiTokenInfo.sub 
    }; 
} 

GoogleApiTokenInfo lớp:

public class GoogleApiTokenInfo 
{ 
/// <summary> 
/// The Issuer Identifier for the Issuer of the response. Always https://accounts.google.com or accounts.google.com for Google ID tokens. 
/// </summary> 
public string iss { get; set; } 

/// <summary> 
/// Access token hash. Provides validation that the access token is tied to the identity token. If the ID token is issued with an access token in the server flow, this is always 
/// included. This can be used as an alternate mechanism to protect against cross-site request forgery attacks, but if you follow Step 1 and Step 3 it is not necessary to verify the 
/// access token. 
/// </summary> 
public string at_hash { get; set; } 

/// <summary> 
/// Identifies the audience that this ID token is intended for. It must be one of the OAuth 2.0 client IDs of your application. 
/// </summary> 
public string aud { get; set; } 

/// <summary> 
/// An identifier for the user, unique among all Google accounts and never reused. A Google account can have multiple emails at different points in time, but the sub value is never 
/// changed. Use sub within your application as the unique-identifier key for the user. 
/// </summary> 
public string sub { get; set; } 

/// <summary> 
/// True if the user's e-mail address has been verified; otherwise false. 
/// </summary> 
public string email_verified { get; set; } 

/// <summary> 
/// The client_id of the authorized presenter. This claim is only needed when the party requesting the ID token is not the same as the audience of the ID token. This may be the 
/// case at Google for hybrid apps where a web application and Android app have a different client_id but share the same project. 
/// </summary> 
public string azp { get; set; } 

/// <summary> 
/// The user's email address. This may not be unique and is not suitable for use as a primary key. Provided only if your scope included the string "email". 
/// </summary> 
public string email { get; set; } 

/// <summary> 
/// The time the ID token was issued, represented in Unix time (integer seconds). 
/// </summary> 
public string iat { get; set; } 

/// <summary> 
/// The time the ID token expires, represented in Unix time (integer seconds). 
/// </summary> 
public string exp { get; set; } 

/// <summary> 
/// The user's full name, in a displayable form. Might be provided when: 
/// The request scope included the string "profile" 
/// The ID token is returned from a token refresh 
/// When name claims are present, you can use them to update your app's user records. Note that this claim is never guaranteed to be present. 
/// </summary> 
public string name { get; set; } 

/// <summary> 
/// The URL of the user's profile picture. Might be provided when: 
/// The request scope included the string "profile" 
/// The ID token is returned from a token refresh 
/// When picture claims are present, you can use them to update your app's user records. Note that this claim is never guaranteed to be present. 
/// </summary> 
public string picture { get; set; } 

public string given_name { get; set; } 

public string family_name { get; set; } 

public string locale { get; set; } 

public string alg { get; set; } 

public string kid { get; set; } 
} 
+0

Wow Tôi đã là người đóng góp trên thư viện khách hàng chính thức của Google .Net từ năm 2012. Bạn có chắc chắn C# chưa có? Ngoài ra, gửi spam tokeninfo không được Google khuyên dùng, bạn nên xác thực Token_id cục bộ. https://github.com/google/google-api-dotnet-client – DaImTo

+0

lời xin lỗi @DalmTo, bạn nói đúng! Tôi đã chỉnh sửa câu trả lời của mình –

+0

GoogleApiTokenInfo được định nghĩa ở đâu? Đây có phải là lớp tùy chỉnh bạn đã tạo hoặc được xác định trong Google SDK không? –

2

Vì vậy, những gì tôi thấy là khi các thông số kỹ thuật OpenIDConnect có một /.well-known/ url chứa thông tin mà bạn cần để xác thực mã thông báo. Điều này bao gồm quyền truy cập vào các khóa công khai cho chữ ký. Phần mềm trung gian JWT tạo thành url được biết đến từ chính quyền, truy xuất thông tin và tiến hành xác thực nó trên chính nó.

Câu trả lời ngắn cho câu hỏi là xác thực đã xảy ra trong phần mềm trung gian, không còn gì để làm.

1

Google tiểu bang trong tài liệu cho openId connect

Đối với mục đích gỡ lỗi, bạn có thể sử dụng thiết bị đầu cuối tokeninfo của Google. Giả sử giá trị mã thông báo ID của bạn là XYZ123.

Bạn không nên sử dụng điểm cuối đó để xác thực JWT của mình.

Xác nhận của một thẻ ID đòi hỏi một số bước:

  1. Xác minh rằng các thẻ ID được ký chính xác bởi các tổ chức phát hành. Mã thông báo do Google cấp được ký bằng một trong các chứng chỉ được tìm thấy tại URI được chỉ định trong trường jwks_uri của discovery document.
  2. Xác minh rằng giá trị của iss trong mã thông báo ID bằng https://accounts.google.com hoặc accounts.google.com.
  3. Xác minh rằng giá trị của kiểm tra trong mã thông báo ID bằng với ID ứng dụng của ứng dụng của bạn.
  4. Xác minh rằng thời gian hết hạn (exp) của mã thông báo ID không được chuyển.
  5. Nếu bạn đã chuyển thông số hd trong yêu cầu, hãy xác minh rằng mã thông báo ID có xác nhận quyền sở hữu hd khớp với miền được lưu trữ trên G Suite của bạn.

Có một dự án mẫu chính thức về cách xác thực chúng here. Rất tiếc, chúng tôi chưa thêm thư này vào thư viện Google .Net Client. Nó đã được đăng nhập dưới dạng issue

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