如何将Microsoft.OneDriveSDK v1迁移到v2?

时间:2016-10-01 15:54:46

标签: c# xamarin onedrive

我有一个基于Xamarin的应用程序,它使用带有版本1.x的Microsoft.OneDriveSDK nuget Package在此应用程序中,我使用Xamarin.Auth管理OAuth内容,从而从该框架获取access_token。

使用OneDriveSDK 1.x,我可以通过重新定义几个类来提供此访问令牌,然后从未让API尝试获取令牌。

现在我想迁移到版本2,并注意到之前的类已被替换,API现在使用Microsoft.Graph nuget包。所以我必须实现接口IAuthenticationProvider并且这样做:

    public async Task AuthenticateRequestAsync(HttpRequestMessage request)
    {
        if (!string.IsNullOrEmpty(MicrosoftLiveOAuthProvider.Instance.AccessToken))
        {
            request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", MicrosoftLiveOAuthProvider.Instance.AccessToken);
        }
    }

调用代码并正确地向请求标头提供身份验证令牌。但是一旦SDK尝试使用令牌,我就会得到一个例外:

  

类型' Microsoft.Graph.ServiceException'的异常被扔了。

     

代码:InvalidAuthenticationToken

     

消息:CompactToken解析失败,错误代码:-2147184118

现在使用谷歌此消息总是说令牌不符合JWT,然后SDK会将其用作微软真实账户令牌。但如果是这种情况,我想知道为什么它失败了V2但与V1合作。

身份验证是针对:

完成的
  

https://login.live.com/oauth20_authorize.srf

任何帮助都非常感谢!

1 个答案:

答案 0 :(得分:3)

我使用带有WebRedirectAuthenticator v2.0.0的子类Xamarin.Auth Microsoft.OneDriveSDK

我使用通过以下构建的access_token通过Xamarin.Auth子类获得初始authorizeUrl:

string GetAuthorizeUrl()
{
    var requestUriStringBuilder = new StringBuilder();
    requestUriStringBuilder.Append(Consts.MicrosoftAccountAuthenticationServiceUrl);
    requestUriStringBuilder.AppendFormat("?{0}={1}", Consts.RedirectUriKeyName, Consts.Redirect_URI);
    requestUriStringBuilder.AppendFormat("&{0}={1}", Consts.ClientIdKeyName, Consts.Client_ID);
    requestUriStringBuilder.AppendFormat("&{0}={1}", Consts.ResponseTypeKeyName, Consts.TokenKeyName);
    requestUriStringBuilder.AppendFormat("&{0}={1}", Consts.ScopeKeyName, Consts.Drive_Scopes);
    return Uri.EscapeUriString(requestUriStringBuilder.ToString());
}

获得访问权限并刷新令牌后,我可以实现需要传递给IHttpProvider构造函数的OneDriveClient,以便在http标头中设置访问令牌:

public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
{
    SetupHttpClient();
    return _httpClient.SendAsync(request);
}

public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
{
    SetupHttpClient();
    return _httpClient.SendAsync(request, completionOption, cancellationToken);
}

HttpClient _httpClient;
void SetupHttpClient()
{
    if (_httpClient == null)
    {
        _httpClient = new HttpClient();
        var accessToken = _account.Properties["access_token"];
        _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    }
}

使用您的OneDriveClientIAuthenticationProvider对象创建IHttpProvider客户端(我只是在构建所有OneDrive API调用的同一个类中实现它们),每个OnDrive请求都将使用使用已保存的Account中的访问令牌。

注意:IAuthenticationProvider AuthenticateRequestAsync的{​​{1}}实施目前无效,但您可以在此处进行Account设置,以获得更清晰的代码流。

var oneDriveClient = new OneDriveClient("https://api.onedrive.com/v1.0", this, this);
var pictureFolderItem = await oneDriveClient.Drive.Root.ItemWithPath("Pictures").Request().GetAsync();
Console.WriteLine(pictureFolderItem.Folder);

刷新几乎一样容易,我在访问令牌到期时存储(减去5分钟)并设置一个计时器来刷新它并将其重新保存到Account。在应用启动时执行相同的操作,如果用户有Account可用且之前已登录,请检查它是否已过期,刷新它,设置后台计时器......

async Task<bool> GetRefreshToken(Account account)
{
    // https://github.com/OneDrive/onedrive-api-docs/blob/master/auth/msa_oauth.md#step-3-get-a-new-access-token-or-refresh-token
    OneDriveOAuth2Authenticator auth = OAuth2Authenticator();
    var token = account.Properties["refresh_token"];
    var expiresIn = await auth.RequestRefreshTokenAsync(token);
    ResetRefreshTokenTimer(expiresIn);
    return true;
}