问题描述
我正在尝试使用Owin在Google.Apis请求中提供的AccessToken,但收到异常System.InvalidOperationException(附加信息:访问令牌已过期,但我们无法刷新).
I'm trying to use the AccessToken provided by Owin in Google.Apis requests but I'm receiveing the exception System.InvalidOperationException (Additional information: The access token has expired but we can't refresh it).
我对Google身份验证的配置可以,并且可以成功登录到我的应用程序中.我将context.AccessToken作为Claim存储在身份验证回调(GoogleOAuth2AuthenticationProvider的OnAuthenticated事件")中.
My configuration of Google Authentication is OK and I can successfully login into my application with it. I store the context.AccessToken as a Claim in the authentication callback (OnAuthenticated "event" of GoogleOAuth2AuthenticationProvider).
我的Startup.Auth.cs配置(app.UseGoogleAuthentication(ConfigureGooglePlus()))
My Startup.Auth.cs configuration (app.UseGoogleAuthentication(ConfigureGooglePlus()))
private GoogleOAuth2AuthenticationOptions ConfigureGooglePlus()
{
var goolePlusOptions = new GoogleOAuth2AuthenticationOptions()
{
ClientId = "Xxxxxxx.apps.googleusercontent.com",
ClientSecret = "YYYYYYzzzzzz",
Provider = new GoogleOAuth2AuthenticationProvider()
{
OnAuthenticated = context =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("Google_AccessToken", context.AccessToken));
return Task.FromResult(0);
}
},
SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie
};
goolePlusOptions.Scope.Add("https://www.googleapis.com/auth/plus.login");
goolePlusOptions.Scope.Add("https://www.googleapis.com/auth/userinfo.email");
return goolePlusOptions;
}
引发异常的代码(Execute()方法)
var externalIdentity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
var accessTokenClaim = externalIdentity.FindAll(loginProvider + "_AccessToken").First();
var secrets = new ClientSecrets()
{
ClientId = "Xxxxxxx.apps.googleusercontent.com",
ClientSecret = "YYYYYYzzzzzz"
};
IAuthorizationCodeFlow flow =
new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = secrets,
Scopes = new[] { PlusService.Scope.PlusLogin, PlusService.Scope.UserinfoEmail }
});
UserCredential credential = new UserCredential(flow, "me", new TokenResponse() { AccessToken = accessTokenClaim.Value });
var ps = new PlusService(
new BaseClientService.Initializer()
{
ApplicationName = "My App Name",
HttpClientInitializer = credential
});
var k = ps.People.List("me", PeopleResource.ListRequest.CollectionEnum.Visible).Execute();
是否有另一种方法来获取原始AccessToken或刷新它而不通过整个认证过程(用户已经通过认证)?
Is there another way to get the original AccessToken or refresh it without pass thru the entire authentication process (the user is already authenticated)?
我需要查询一些GooglePlus个人资料数据,例如GivenName,familyName,性别,个人资料图片和个人资料网址.
I need to query some GooglePlus profile data such as GivenName, familyName, gender, profile picture and profile url.
推荐答案
琳达为我提供了一个URL指向新的asp.net mvc示例( https://codereview.appspot.com/194980043/ ).
Linda helped me with an URL pointing to a new asp.net mvc sample (https://codereview.appspot.com/194980043/).
我只需要向GoogleOAuth2AuthenticationOptions添加 AccessType ="offline" 并保存一些额外的信息,以在需要时创建TokenResponse的新实例.
I just had to add AccessType = "offline" to GoogleOAuth2AuthenticationOptions and save some extra info to create a new instance of TokenResponse when I need.
Google身份验证选项
private GoogleOAuth2AuthenticationOptions ConfigureGooglePlus()
{
var goolePlusOptions = new GoogleOAuth2AuthenticationOptions()
{
AccessType = "offline",
ClientId = "Xxxxxxx.apps.googleusercontent.com",
ClientSecret = "Yyyyyyyyyy",
Provider = new GoogleOAuth2AuthenticationProvider()
{
OnAuthenticated = context =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("Google_AccessToken", context.AccessToken));
if (context.RefreshToken != null)
{
context.Identity.AddClaim(new Claim("GoogleRefreshToken", context.RefreshToken));
}
context.Identity.AddClaim(new Claim("GoogleUserId", context.Id));
context.Identity.AddClaim(new Claim("GoogleTokenIssuedAt", DateTime.Now.ToBinary().ToString()));
var expiresInSec = (long)(context.ExpiresIn.Value.TotalSeconds);
context.Identity.AddClaim(new Claim("GoogleTokenExpiresIn", expiresInSec.ToString()));
return Task.FromResult(0);
}
},
SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie
};
goolePlusOptions.Scope.Add("https://www.googleapis.com/auth/plus.login");
goolePlusOptions.Scope.Add("https://www.googleapis.com/auth/plus.me");
goolePlusOptions.Scope.Add("https://www.googleapis.com/auth/userinfo.email");
return goolePlusOptions;
}
如何检索凭据(使用已存储"的令牌信息作为声明)
How to retrieve the credentials (using token info "stored" as claim)
private async Task<UserCredential> GetCredentialForApiAsync()
{
var initializer = new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets
{
ClientId = "Xxxxxxxxx.apps.googleusercontent.com",
ClientSecret = "YYyyyyyyyyy",
},
Scopes = new[] {
"https://www.googleapis.com/auth/plus.login",
"https://www.googleapis.com/auth/plus.me",
"https://www.googleapis.com/auth/userinfo.email" }
};
var flow = new GoogleAuthorizationCodeFlow(initializer);
var identity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ApplicationCookie);
var userId = identity.FindFirstValue("GoogleUserId");
var token = new TokenResponse()
{
AccessToken = identity.FindFirstValue("Google_AccessToken"),
RefreshToken = identity.FindFirstValue("GoogleRefreshToken"),
Issued = DateTime.FromBinary(long.Parse(identity.FindFirstValue("GoogleTokenIssuedAt"))),
ExpiresInSeconds = long.Parse(identity.FindFirstValue("GoogleTokenExpiresIn")),
};
return new UserCredential(flow, userId, token);
}
这篇关于如何在Google.Apis调用中使用ASP.NET MVC Owin AccessToken?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!