2014-12-29 1 views
3

Я разрабатываю приложение Asp.NET MVC5 following this Google sample code.OAuth 2 токен обновления API для Google - null

Я хочу, чтобы приложение было аутентифицировано и создало пользовательский интерфейс (Configure stage), а позже мне нужно иметь возможность называть Google APis (API каталога в моем случае) с использованием токена обновления (без вмешательства пользователя) , что-то вроде «offline»).

Контроллер:

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, так как нет предыдущего маркера доступа для пользователя, он создает новую после знака пользователя в учетную запись Google ,
Это образец маркер доступа,

{"access_token":"ya29.5gBOszGO-oYJJt4YZfF6FeaZth1f69_.....","token_type":"Bearer","expires_in":3600,"Issued":"2014-12-24T16:02:32.014+05:30"}

Question1: Почему там нет Refreshtoken хранится с этим? Как я могу получить refreshtoken? Вопрос 2: Если я получу refreshtoken, как мне изменить код для создания нового токена доступа и вызвать API (когда истекает срок действия accesstoken)? [Я ссылался на this question, но не было правильного ответа на недостающий токен обновления.

ответ

7

Найдено решение для доступа к API Google в автономном режиме, чтобы получить обновления маркер и использовать токен обновления, чтобы создать новый маркер доступа,

Question1: Почему там нет 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" 
      }; 
     } 
    }; 

question2: ..ow я должен изменить код, чтобы создать новый маркер доступа и вызова 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); 
    } 

Это сработало для меня! Надеюсь, это поможет другим ...

+1

Как это не входит в документацию Google? Также кажется, что автономный доступ и обновляющие токены в других библиотеках тривиальны по сравнению с циклами, которые мы должны перескакивать с помощью библиотеки .NET. Потеряли столько времени, когда искали решение, рад, что вы его разместили! – DavGarcia