1 回答
TA贡献1877条经验 获得超1个赞
我终于破解了!我最终扔掉了所有库,发现使用普通的旧 REST API 最简单。对于那些好奇的人来说,下面的代码示例:
用户的浏览器获取以下内容并重定向到 Google 以获取身份验证令牌:
public IActionResult OnGet([FromQuery]int id, [FromQuery]string returnAction)
{
var org = context.Organizations.Include(o => o.UserOrgs).First(o => o.Id == id);
var user = GetUser();
if (!IsUserMemberOfOrg(user, org)) return BadRequest("User is not a member of this organization!");
var redirectUri = Uri.EscapeUriString(GetBaseUri()+"dash/auth/google?handler=ReturnCode");
var uri = $"https://accounts.google.com/o/oauth2/v2/auth?"+
$"scope={Uri.EscapeUriString("https://www.googleapis.com/auth/analytics.readonly")}"+
$"&prompt=consent"+
$"&access_type=offline"+
//$"&include_granted_scopes=true"+
$"&state={Uri.EscapeUriString(JsonConvert.SerializeObject(new AuthState() { OrgId = id, ReturnAction = returnAction }))}"+
$"&redirect_uri={redirectUri}"+
$"&response_type=code"+
$"&client_id={_configuration["Authentication:Google:ClientId"]}";
return Redirect(uri);
}
Google 重定向回以下内容,此时我从网络服务器到 Google API 执行 POST,以将身份验证令牌交换为刷新令牌并将其存储以供以后使用:
public async Task<IActionResult> OnGetReturnCode([FromQuery]string state, [FromQuery]string code, [FromQuery]string scope)
{
var authState = JsonConvert.DeserializeObject<AuthState>(state);
var id = authState.OrgId;
var returnAction = authState.ReturnAction;
var org = await context.Organizations.Include(o => o.UserOrgs).SingleOrDefaultAsync(o => o.Id == id);
if (org == null) return BadRequest("This Org doesn't exist!");
using (var httpClient = new HttpClient())
{
var redirectUri = Uri.EscapeUriString(GetBaseUri()+"dash/auth/google?handler=ReturnCode");
var dict = new Dictionary<string, string>
{
{ "code", code },
{ "client_id", _configuration["Authentication:Google:ClientId"] },
{ "client_secret", _configuration["Authentication:Google:ClientSecret"] },
{ "redirect_uri", redirectUri },
{ "grant_type", "authorization_code" }
};
var content = new FormUrlEncodedContent(dict);
var response = await httpClient.PostAsync("https://www.googleapis.com/oauth2/v4/token", content);
var resultContent = JsonConvert.DeserializeObject<GoogleRefreshTokenPostResponse>(await response.Content.ReadAsStringAsync());
org.GoogleAuthRefreshToken = resultContent.refresh_token;
await context.SaveChangesAsync();
return Redirect($"{authState.ReturnAction}/{authState.OrgId}");
}
}
最后,我们可以稍后使用刷新令牌获取新的访问令牌,而无需用户干预:
public async Task<string> GetGoogleAccessToken(Organization org)
{
if(string.IsNullOrEmpty(org.GoogleAuthRefreshToken))
{
throw new Exception("No refresh token found. " +
"Please visit the organization settings page" +
" to setup your Google account.");
}
using (var httpClient = new HttpClient())
{
var dict = new Dictionary<string, string>
{
{ "client_id", _configuration["Authentication:Google:ClientId"] },
{ "client_secret", _configuration["Authentication:Google:ClientSecret"] },
{ "refresh_token", org.GoogleAuthRefreshToken },
{ "grant_type", "refresh_token" }
};
var resp = await httpClient.PostAsync("https://www.googleapis.com/oauth2/v4/token",
new FormUrlEncodedContent(dict));
if (resp.IsSuccessStatusCode)
{
dynamic returnContent = JObject.Parse(await resp.Content.ReadAsStringAsync());
return returnContent.access_token;
} else
{
throw new Exception(resp.ReasonPhrase);
}
}
}
- 1 回答
- 0 关注
- 64 浏览
添加回答
举报