如何在 Google.Apis 调用中使用 ASP.NET MVC Owin AccessToken?

How can I use ASP.NET MVC Owin AccessToken in Google.Apis call?

我试图在 Google.Apis 请求中使用 Owin 提供的 AccessToken,但我收到异常 System.InvalidOperationException(附加信息:访问令牌已过期,但我们无法刷新它)。

我的 Google 身份验证配置正常,我可以使用它成功登录我的应用程序。我将 context.AccessToken 作为声明存储在身份验证回调中(GoogleOAuth2AuthenticationProvider 的 OnAuthenticated "event")。

我的 Startup.Auth.cs 配置 (app.UseGoogleAuthentication(配置GooglePlus()))

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 或刷新它而不通过整个身份验证过程(用户已经通过身份验证)?

我需要查询一些 GooglePlus 个人资料数据,例如 GivenName、familyName、性别、个人资料照片和个人资料 url。

Linda helped me with an URL pointing to a new asp.net mvc sample (https://codereview.appspot.com/194980043/).

我只需要将 AccessType = "offline" 添加到 GoogleOAuth2AuthenticationOptions 并保存一些额外信息以在需要时创建新的 TokenResponse 实例。

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;
}

如何检索凭据(使用令牌信息 "stored" 作为声明)

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);
}