Asp.NET Core集成谷歌登录

开篇

要集成谷歌登录,首先得会科学上网,毕竟所有操作都是在墙外。
开发者中心 : https://console.developers.google.com 注册APP,获取client_id,client_secret等
基础集成教程 : https://developers.google.com/identity/sign-in/web/sign-in#before_you_begin
比较全面的教程 :https://developers.google.com/identity/choose-auth

Asp.Net Core官方集成

关于.net core集成谷歌登录,微软官方有一篇文章 https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/google-logins?view=aspnetcore-2.2 看上去也挺简单,去谷歌官方注册账号,创建应用,获取client_id,client_secrent。在startup.cs里添加类似代码即可

services.AddAuthentication()
    .AddGoogle(googleOptions => { ... })

这种方法没有试过,不知道会不会配合ef+codefirst等手段,而且集成太深,受制于人的感觉总是不太好,所以放弃。

JS集成

教程 https://developers.google.com/identity/sign-in/web/ 集成比较简单,这种方式是在前端就可以获取到id_token ,然后在传回后端,后端使用类似GoogleIdToken idToken = verifier.verify(idTokenString); 后去具体token信息(包括email,uid,姓名等)

尝试谷歌官方sdk

惯性思维觉得,这种登录授权,官方一定有相应的SDK,也会有教程,按照教程撸代码就可以了。google登录授权的sdk

Install-Package Google.Apis.Auth -Version 1.38.0

这个sdk是支持.net core的,
github网址 https://github.com/googleapis/google-api-dotnet-client
开发文档 https://developers.google.com/api-client-library/dotnet/get_started

1. 集成跳转代码

获取授权信息,如果未获取到,跳转到谷歌官方(此步不需要VPN等)

var flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
    ClientSecrets = new ClientSecrets
    {
        ClientId = "你的client_id",
        ClientSecret = "你的client_secret"
    },
    Scopes = new []{"openid"},
    DataStore = null
});
var auth = new AuthorizationCodeWebApp(flow, "http://localhost:5000/auth/google", "");
var result = auth.AuthorizeAsync("[谷歌给的userid]", CancellationToken.None).GetAwaiter().GetResult();
if (result.Credential != null)
{
    //获取授权信息
}
else
{
    return Redirect(result.RedirectUri);
}

2. 回调

(当用户在谷歌官网同意授权后,将跳回你的网站),url大概如下

http://localhost:5000/auth/google?
code=&
scope=openid&
authuser=0&
session_state=f3d5712ae1881ee4d1d1e3409819ce4bb309467f..99d2
&prompt=consent 

通过url里的code,再去换取access_token,代码如下

flow.ExchangeCodeForTokenAsync()

问题就出在回调页上,在与谷歌换取access_token的时候,一直超时最后报错,因为googleapis.com在天朝是打不开的,那就上VPN吧,但即便在开启vpn的情况下,也超时出错,谷歌一圈,有人说是httpclient的问题,感觉也不好修复。

HTTP/REST集成

教程 https://developers.google.com/identity/protocols/OpenIDConnect#userinfocall
其实为什么集成登录这件事,喜欢用SDK,因为SDK封装了请求、加密、序列化等一系列操作,但我看了下谷歌的http/rest,感觉尤其简单。

1. 拼接跳转的url

https://accounts.google.com/o/oauth2/v2/auth?
scope=openid&
access_type=offline&
include_granted_scopes=true&
state=1&
redirect_uri=http%3A%2F%2Flocalhost:5000%2Fauth%2Fgoogle&
response_type=code&
client_id=[你的clientid]

所有scope : https://developers.google.com/identity/protocols/googlescopes

2.通过回调的code换取id_token

换取id_token时,注意把googleapis.com 换成googleapis.cn

var url = $"https://www.googleapis.cn/oauth2/v4/token";
var formDataDictionary = new Dictionary<string, string>()
 {
         {"code", code.Trim() },
         {"client_id", "你的client-id" },
         {"client_secret", "你的client-secret" },
         {"redirect_uri","http://localhost:5000/auth/google"},
         {"grant_type","authorization_code"}
};
var formData = new FormUrlEncodedContent(formDataDictionary);
var responseMessage = await _httpClient.PostAsync(url, formData);
var resp = await responseMessage.Content.ReadAsStringAsync();

在resp里可以获取到id_token, id_token实际上是jwt,可以decode成一个json字符串,然后获取email,头像等信息