我正在开发一个Asp.NET MVC5应用程序following this Google sample code。
我希望应用程序经过身份验证并由用户创建一个accessstoken(配置阶段),之后我需要能够调用Google APis' (在我的情况下是目录API)使用刷新令牌(没有用户干预,类似"离线")。
控制器:
public async Task<ActionResult> IndexAsync(CancellationToken cancellationToken)
{
var result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).
AuthorizeAsync(cancellationToken);
if (result.Credential != null)
{
var service = new Google.Apis.Admin.Directory.directory_v1.DirectoryService(new BaseClientService.Initializer
{
HttpClientInitializer = result.Credential,
ApplicationName = "My Application"
});
return View();
}
else
{
return new RedirectResult(result.RedirectUri);
}
}
FlowMetadata实现。 (我使用的是FiledataStore稍加修改(GoogleFileDataStore))
public class AppFlowMetadata : FlowMetadata
{
//Move to settings
static readonly string clientId = "xxxccnvofsdfsfoj.apps.googleusercontent.com";
static readonly string clientsecret = "xxxxxxxxxxLvtC6Qbqpp4x_";
static readonly string datastore = "AdminSDK.Api.Auth.Store";
private static readonly IAuthorizationCodeFlow flow =
new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets
{
ClientId = clientId,
ClientSecret = clientsecret
},
Scopes = new[] { DirectoryService.Scope.AdminDirectoryUser, DirectoryService.Scope.AdminDirectoryUserAliasReadonly },
DataStore = new GoogleFileDataStore(datastore)
});
public override string GetUserId(Controller controller)
{
return ConfigHelper.UserID.ToString();
}
public override IAuthorizationCodeFlow Flow
{
get { return flow; }
}
}
当我调用IndexAsync控制器时,由于用户没有先前的accessstoken,因此在用户登录Google帐户后会创建一个新的。 这是一个示例accessstoken,
{"access_token":"ya29.5gBOszGO-oYJJt4YZfF6FeaZth1f69_.....","token_type":"Bearer","expires_in":3600,"Issued":"2014-12-24T16:02:32.014+05:30"}
问题1:为什么没有存储与此相关的Refreshtoken?如何检索refreshtoken? 问题2:如果我获得了refreshtoken,我应该如何修改代码以创建新的访问令牌并调用API(当accesstoken过期时)? [我提到this question,但缺少刷新令牌没有正确答案。
答案 0 :(得分:7)
找到Google API离线访问的解决方案以获取刷新令牌并使用刷新令牌创建新的accessstoken,
问题1:为什么没有存储与此相关的Refreshtoken?如何检索refreshtoken?
我必须在请求中将access_type设置为脱机(默认情况下是在线)。 as mentioned here
我必须为GoogleAuthorizationCodeFlow类编写自己的实现。感谢this post.
public class ForceOfflineGoogleAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
{
public ForceOfflineGoogleAuthorizationCodeFlow(GoogleAuthorizationCodeFlow.Initializer initializer) : base(initializer) { }
public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri)
{
return new GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl))
{
ClientId = ClientSecrets.ClientId,
Scope = string.Join(" ", Scopes),
RedirectUri = redirectUri,
AccessType = "offline",
ApprovalPrompt = "force"
};
}
};
问题2:我应该修改代码以创建新的访问令牌并调用API吗?
//try to get results
var result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).
AuthorizeAsync(cancellationToken);
//// This bit checks if the token is out of date,
//// and refreshes the access token using the refresh token.
if (result.Credential.Token.IsExpired(SystemClock.Default))
{
Google.Apis.Auth.OAuth2.Responses.TokenResponse token = new Google.Apis.Auth.OAuth2.Responses.TokenResponse();
//If the token is expired recreate the token
token = await result.Credential.Flow.RefreshTokenAsync(ConfigHelper.UserID.ToString(), result.Credential.Token.RefreshToken, CancellationToken.None);
//Get the authorization details back
result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).AuthorizeAsync(cancellationToken);
}
这对我有用!希望这会有助于其他人......