Search code examples
c#winformslive-sdk

Permission screen appears every time


I want to make my WinForms-App to use the SingleSign-On (SSO) feature with Microsoft Accounts.
I created a LiveApp and I'm able to Login to my App with the LiveSDK 5.4.
But everytime I click on my Login-Button the permissions list appears and I need to accept it again.

This is my code:

private const string ClientID = "{MY_CLIENT_ID}";
private LiveAuthClient liveAuthClient;
private LiveConnectClient liveConnectClient;
string[] scopes = new string[] { "wl.offline_access", "wl.emails", "wl.signin" };

private void buttonLogin_Click(object sender, EventArgs e)
{
    liveAuthClient = new LiveAuthClient(ClientID);
    webBrowser1.Navigate(liveAuthClient.GetLoginUrl(scopes));
}

private async void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
    if (this.webBrowser1.Url.AbsoluteUri.StartsWith("https://login.live.com/oauth20_desktop.srf"))
    {
        AuthResult authResult = new AuthResult(this.webBrowser1.Url);
        if (authResult.AuthorizeCode != null)
        {
            try
            {
                LiveConnectSession session = await liveAuthClient.ExchangeAuthCodeAsync(authResult.AuthorizeCode);
                this.liveConnectClient = new LiveConnectClient(session);
                LiveOperationResult meRs = await this.liveConnectClient.GetAsync("me");
                dynamic meData = meRs.Result;
                if(string.Equals(meData.emails.account, MyAppUser.EmailAddress))
                    MessageBox.Show("Successful login: " + meData.name);
            }
            catch (LiveAuthException aex)
            {
                MessageBox.Show("Failed to retrieve access token. Error: " + aex.Message);
            }
            catch (LiveConnectException cex)
            {
                MessageBox.Show("Failed to retrieve the user's data. Error: " + cex.Message);
            }
        }
        else
        {
            MessageBox.Show(string.Format("Error received. Error: {0} Detail: {1}", authResult.ErrorCode, authResult.ErrorDescription));
        }
    }
}

What I need to change? I don't want the User to accept the permissions on each login.


Solution

  • You can use IRefreshTokenHandler to save token as following example:

    public class RefreshTokenHandler : IRefreshTokenHandler
    {
        private string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\oneDrive\\RefreshTokenHandler\\RefreshTokenInfo.RefreshToken-me";
        public Task<RefreshTokenInfo> RetrieveRefreshTokenAsync()
        {
            return Task.Factory.StartNew<RefreshTokenInfo>(() =>
            {
                if (File.Exists(path))
                {
                    return new RefreshTokenInfo(File.ReadAllText(path));
                }
                return null;
            });
        }
    
        public Task SaveRefreshTokenAsync(RefreshTokenInfo tokenInfo)
        {
            // Note: 
            // 1) In order to receive refresh token, wl.offline_access scope is needed.
            // 2) Alternatively, we can persist the refresh token.
            return Task.Factory.StartNew(() =>
            {
                if (File.Exists(path)) File.Delete(path);
                if (!Directory.Exists(Path.GetDirectoryName(path))) Directory.CreateDirectory(Path.GetDirectoryName(path));
                File.AppendAllText(path, tokenInfo.RefreshToken);
            });
        }
    }
    

    after that you get session as following:

    RefreshTokenHandler handler = new RefreshTokenHandler();
    liveAuthClient = new LiveAuthClient(ClientID, handler);
    var Session = liveAuthClient.InitializeAsync(scopes).Result.Session;
    if (Session == null)
    {
        webBrowser1.Navigate(liveAuthClient.GetLoginUrl(scopes));
    }
    else
    {
        try
        {
            this.liveConnectClient = new LiveConnectClient(Session);
            LiveOperationResult meRs = await this.liveConnectClient.GetAsync("me");
            dynamic meData = meRs.Result;
            if (string.Equals(meData.emails.account, MyAppUser.EmailAddress))
                MessageBox.Show("Successful login: " + meData.name);
        }
        catch (LiveAuthException aex)
        {
            MessageBox.Show("Failed to retrieve access token. Error: " + aex.Message);
        }
        catch (LiveConnectException cex)
        {
            MessageBox.Show("Failed to retrieve the user's data. Error: " + cex.Message);
        }
    }