OneDrive / onedrive-sdk-csharp

OneDrive SDK for C#! https://dev.onedrive.com
Other
294 stars 145 forks source link

GetSilentlyAuthenticatedMicrosoftAccountClient missing from new OneDrive SDK? #188

Open ericberman opened 7 years ago

ericberman commented 7 years ago

I have a website that allows its users to save their data to a file on OneDrive, updating it nightly (i.e., unattended). Since I work with a variety of oAuth services, I have centralized oAuth functionality to get an accesstoken/refreshtoken, and that all works totally fine.

In 1.1.47 of the SDK, I would call await OneDriveClient.GetSilentlyAuthenticatedMicrosoftAccountClient(AppKey, string.Empty, Scopes, AppSecret, AuthState.RefreshToken); to get my onedriveclient object, which I could use without problem to save the user's data. Note that I'm passing in a RefreshToken that I already received from an earlier authentication. (This is because the user authenticates once, and then every night I run a process to update their file using the cached token)

This works great in 1.1.47. I just upgraded to 2.0.4 and GetSilentlyAuthenticatedMicrosoftAccountClient is gone, and I can't find a replacement for it. It looks like I'm supposed to create an MsaAuthenticationProvider, but even there I don't see where I can use a cached refreshtoken (it looks like they want to do the user redirect, i.e., disallowing unattended use).

Is there a code sample for how I am supposed to do this?

cdmayer commented 7 years ago

Authentication was factored out of this library and into this library. The intent of that library is to give some examples of how to authenticate an app, but not be exhaustive. Your scenario definitely is less-than-ordinary, so the sample code doesn't cover it.

However, your scenario is far from impossible. It is possible to cache sessions using the ICredentialVault interface. There is currently a default implementation for UWP apps and local Win32 apps, but no such implementation for a server-side app. Basically, you need to implement ICredentialVault for your app. It needs to be able to talk to you storage layer (to store & retrieve sessions). Then, when you create your client object, you'll just call:

var msaAuthProvider = new MsaAuthenticationProvider(
    clientId,
    returnUrl,
    scopes,
    /*CredentialCache*/ null,
    new MyAwesomeCredentialVault(clientId));
authTask = msaAuthProvider.RestoreMostRecentFromCacheOrAuthenticateUserAsync();
app.OneDriveClient = new OneDriveClient(this.oneDriveConsumerBaseUrl, msaAuthProvider);

Of course, you may want to pass other parameters into the CredentialVault constructor depending on your implementation. After that, the auth library will automatically read from/write to the credential vault whenever a refresh token is needed.

I hope that helps. Please let me know if that leaves you with any questions.

ericberman commented 7 years ago

Thanks, I’ll definitely give that a try.

chadwackerman commented 7 years ago

@cdmayer This does not work. @ericberman did you come up with an alternate solution?

ericberman commented 7 years ago

No. I went back to go do this and realized that I can't use the ICredentialVault solution (at least not given the documentation I have) because I do my oAuth authentication using DotNetOpenAuth (i.e., I don't use the OneDrive SDK to do the authentication, since I am a client for several oAuth services) and I couldn't see in the documentation how to insert the resulting authtoken into an ICredentialVault on my own. OneDrive SDK 1.1.47 is still working perfectly for me, so I haven't spent a ton of time diving in on this; far easier to simply not upgrade. (Why backwards compatibility wasn't maintained in the API escapes me, I confess...).

@cdmayer - would love any advice you have on these issues. I have an authtoken that, in JSON form, I can represent as {"Callback":(my callback URL)","RefreshToken":"(refresh token)","AccessToken":"(access token)","AccessTokenExpirationUtc":"...","AccessTokenIssueDateUtc":"...","Scope":["onedrive.appfolder","wl.basic","onedrive.readwrite","wl.offline_access","wl.signin"],"IsDeleted":false}.

How would I put this into an ICredentialVault?

Secondary issue: what replaces OneDriveException which I am catching now?

chadwackerman commented 7 years ago

I believe Microsoft.Graph.ServiceException is the replacement for OneDriveException.