Skip to content

Instantly share code, notes, and snippets.

@rgregg
Last active February 25, 2022 23:19
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rgregg/0f45cebbfbde4b7e4157 to your computer and use it in GitHub Desktop.
Save rgregg/0f45cebbfbde4b7e4157 to your computer and use it in GitHub Desktop.
Windows Store App Sign-in for OneDrive SDK
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Windows.Security.Authentication.OnlineId;
namespace OneDrive
{
public class MsaForStoreApps
{
private const string OnlineIdTicketPolicyForLiveServices = "DELEGATION";
private const int UserNotFoundLoginExceptionHResult = -2147023579;
private const int ConsentNotGrantedExceptionHResult = -2138701812;
private const int InvalidClientExceptionHResult = -2138701821;
private const int InvalidAuthTargetExceptionHResult = -2138701823;
private OnlineIdAuthenticator Authenticator { get; set; }
public MsaForStoreApps()
{
Authenticator = new OnlineIdAuthenticator();
}
public async Task<AuthToken> SignInAsync(string[] requestedScopes, bool silent = false)
{
try
{
string accessToken = await GetAccessTokenAsync(requestedScopes, silent);
AuthToken results = new AuthToken(AuthStatus.Successful, this, accessToken, requestedScopes);
return results;
}
catch (TaskCanceledException)
{
return null;
}
catch (Exception comExp)
{
switch (comExp.HResult)
{
case UserNotFoundLoginExceptionHResult:
return new AuthToken(AuthStatus.Unknown, this);
case ConsentNotGrantedExceptionHResult:
return new AuthToken(AuthStatus.Failure, this);
case InvalidClientExceptionHResult:
case InvalidAuthTargetExceptionHResult:
// This usually means you haven't assoicated your app with the store app yet.
return new AuthToken(AuthStatus.InvalidRequest, this);
default:
return new AuthToken(AuthStatus.ServerError, this);
}
}
}
private async Task<string> GetAccessTokenAsync(string[] requestedScopes, bool silent)
{
string accessToken = null;
string scopes = BuildScopeString(requestedScopes);
CredentialPromptType promptType = silent ? CredentialPromptType.DoNotPrompt : CredentialPromptType.PromptIfNeeded;
var ticketRequests = new List<OnlineIdServiceTicketRequest>();
ticketRequests.Add(new OnlineIdServiceTicketRequest(scopes, OnlineIdTicketPolicyForLiveServices));
UserIdentity identity = await Authenticator.AuthenticateUserAsync(ticketRequests, promptType);
if (identity.Tickets != null && identity.Tickets.Count > 0)
{
accessToken = identity.Tickets[0].Value;
}
return accessToken;
}
public bool CanSignOut
{
get { return Authenticator.CanSignOut; }
}
private static string BuildScopeString(string[] requestedScopes)
{
StringBuilder sb = new StringBuilder();
foreach (string scope in requestedScopes)
{
if (sb.Length > 0)
sb.Append(' ');
sb.Append(scope);
}
return sb.ToString();
}
}
public class AuthToken : OneDrive.IAuthenticationInfo
{
public AuthToken(AuthStatus result, MsaForStoreApps client, string accessToken = null, string[] scopes = null)
{
AuthClient = client;
AccessToken = accessToken;
Scopes = scopes;
Status = result;
}
public MsaForStoreApps AuthClient { get; private set; }
public string AccessToken { get; private set; }
public string[] Scopes { get; private set; }
public AuthStatus Status { get; private set; }
public string RefreshToken
{
get { throw new NotImplementedException(); }
}
public string TokenType
{
get { return "Bearer"; }
}
public DateTimeOffset TokenExpiration
{
get { return DateTimeOffset.MaxValue; }
}
public Task<bool> RefreshAccessTokenAsync()
{
throw new NotImplementedException();
}
public string AuthorizationHeaderValue
{
get { return "Bearer " + AccessToken; }
}
}
public enum AuthStatus
{
Unknown,
Successful,
Failure,
InvalidRequest,
ServerError
}
}
private async void SignInButton_Click(object sender, RoutedEventArgs e)
{
OneDrive.MsaForStoreApps authClient = new OneDrive.MsaForStoreApps();
ODConnection oneDriveConnection = null;
var token = await authClient.SignInAsync(new string[] { "wl.signin", "onedrive.readwrite" });
if (token.Status == OneDrive.AuthStatus.Successful)
{
oneDriveConnection = new OneDrive.ODConnection("https://api.onedrive.com/v1.0", token);
var rootItem = await oneDriveConnection.GetRootItemAsync(OneDrive.ItemRetrievalOptions.Default);
}
else
{
textBlockStatus.Text = string.Format("Error signing into OneDrive: " + token.Status.ToString());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment