如何在不看到权限屏幕的情况下登录到 OneDrive(初始时间之后)

本文关键字:OneDrive 登录 之后 时间 情况下 不看 权限 屏幕 | 更新日期: 2024-10-29 18:23:23

我刚刚开始使用OneDrive API及其附带的示例程序(OneDriveApiBrowser)。

正如预期的那样,当我第一次登录(使用"登录到 MSA...")时,系统要求我输入凭据、我的 2 因素代码,最后是一个权限屏幕,询问我是否批准应用想要对我的 OneDrive 帐户进行访问。

但是,在我退出程序并重新启动它后,我没有登录。我重复"登录到 MSA..."并且不再提示我输入凭据(如我预期的那样),但再次提示我使用权限屏幕。

有没有办法让应用程序重新登录而不总是提示用户权限?

为了学习如何使用 OneDrive API,我只是使用Microsoft作为位于 https://github.com/OneDrive/onedrive-sdk-csharp/tree/master/samples/OneDriveApiBrowser 的 API 的一部分提供的示例代码。代码不能直接从那里下载,但在这个项目的根目录下,https://github.com/OneDrive/onedrive-sdk-csharp。这将下载 API 的源代码以及示例代码和单元测试。

如何在不看到权限屏幕的情况下登录到 OneDrive(初始时间之后)

在做了更多的探索之后,我终于找到了如何做到这一点。 我在这里的解释将在上面原始问题中提到的示例程序的上下文中进行。

在程序中,在SignIn方法中,正在完成一些设置,其中包括调用OneDriveClient.GetMicrosoftAccountClient(...),然后调用以下内容:

if (!this.oneDriveClient.IsAuthenticated)
{
    await this.oneDriveClient.AuthenticateAsync();
}

因此,需要做两件事。我们需要从上面的代码中保存结果,然后将 RefreshToken 值保存在安全的地方......(这只是一个很长的字符串)。

if (!this.oneDriveClient.IsAuthenticated)
{
    AccountSession accountSession = await this.oneDriveClient.AuthenticateAsync();
    // Save accountSession.RefreshToken somewhere safe...
}

最后,我需要在OneDriveClient.GetMicrosoftAccountClient(...)调用周围放置一个if,并且仅在保存的刷新令牌尚未保存(或由于添加到注销调用的代码而被删除)时才调用它......如果我们有一个保存的刷新令牌,我们调用'OneDriveClient.GetSilentlyAuthenticatedMicrosoftAccountClient(...)。 完成后,整个登录方法如下所示。

private async Task SignIn(ClientType clientType)
{
    string refreshToken = null;
    AccountSession accountSession;
    // NOT the best place to save this, but will do for an example...
    refreshToken = Properties.Settings.Default.RefreshToken;
    if (this.oneDriveClient == null)
    {
        if (string.IsNullOrEmpty(refreshToken))
        {
            this.oneDriveClient = clientType == ClientType.Consumer
                        ? OneDriveClient.GetMicrosoftAccountClient(
                            FormBrowser.MsaClientId,
                            FormBrowser.MsaReturnUrl,
                            FormBrowser.Scopes,
                            webAuthenticationUi: new FormsWebAuthenticationUi())
                        : BusinessClientExtensions.GetActiveDirectoryClient(FormBrowser.AadClientId, FormBrowser.AadReturnUrl);
        }
        else
        {
            this.oneDriveClient = await OneDriveClient.GetSilentlyAuthenticatedMicrosoftAccountClient(FormBrowser.MsaClientId,
                    FormBrowser.MsaReturnUrl,
                    FormBrowser.Scopes, 
                    refreshToken);
        }
    }
    try
    {
        if (!this.oneDriveClient.IsAuthenticated)
        {
            accountSession = await this.oneDriveClient.AuthenticateAsync();
            // NOT the best place to save this, but will do for an example...
            Properties.Settings.Default.RefreshToken = accountSession.RefreshToken;
            Properties.Settings.Default.Save();
        }
        await LoadFolderFromPath();
        UpdateConnectedStateUx(true);
    }
    catch (OneDriveException exception)
    {
        // Swallow authentication cancelled exceptions
        if (!exception.IsMatch(OneDriveErrorCode.AuthenticationCancelled.ToString()))
        {
            if (exception.IsMatch(OneDriveErrorCode.AuthenticationFailure.ToString()))
            {
                MessageBox.Show(
                    "Authentication failed",
                    "Authentication failed",
                    MessageBoxButtons.OK);
                var httpProvider = this.oneDriveClient.HttpProvider as HttpProvider;
                httpProvider.Dispose();
                this.oneDriveClient = null;
            }
            else
            {
                PresentOneDriveException(exception);
            }
        }
    }
}

为了完整起见,我更新了注销代码

private async void signOutToolStripMenuItem_Click(object sender, EventArgs e)
{
    if (this.oneDriveClient != null)
    {
        await this.oneDriveClient.SignOutAsync();
        ((OneDriveClient)this.oneDriveClient).Dispose();
        this.oneDriveClient = null;
        // NOT the best place to save this, but will do for an example...
        Properties.Settings.Default.RefreshToken = null;
        Properties.Settings.Default.Save();
    }
    UpdateConnectedStateUx(false);
}

应用程序需要wl.offline_access范围来保存用户同意信息并在没有 UI 提示的情况下刷新访问令牌。

有关可在应用程序中使用的作用域的更多详细信息,请参阅 https://dev.onedrive.com/auth/msa_oauth.htm#authentication-scopes