Microsoft Graph / OneDrive请求多个身份验证

时间:2018-08-06 14:54:27

标签: vb.net microsoft-graph onedrive

我正在尝试编写代码以读取我的OneDrive文件夹中的文件,并在将来创建,移动和删除它们。

下面的代码片段可以使用,但是它为For Each ... Next中的每次迭代请求一个新的身份验证(显示Microsoft的OAuth窗口)。

我在这里做什么错了?

Imports Microsoft.Graph

Public Class FormGraphClient
    Private Shared client As GraphServiceClient

    Private Async Sub FormGraphClient_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        client = AuthenticationHelper.GetAuthenticatedClient

        Dim formsmonitor_items = Await client.Me.Drive.Root.ItemWithPath("FormsMonitor").Children.Request.GetAsync

        Dim forms As New Dictionary(Of String, String)

        For Each form In formsmonitor_items
            If form.Name Like "*.json" Then
                Using formstream = Await client.Me.Drive.Items.Item(form.Id).Content.Request.GetAsync
                    Using reader = New IO.StreamReader(formstream)
                        forms(form.Name) = reader.ReadToEnd
                    End Using
                End Using
            End If
        Next

    End Sub
End Class

我也在使用此帮助程序类:

Imports System.Net.Http.Headers
Imports Microsoft.Graph
Imports Microsoft.Identity.Client

Public Class AuthenticationHelper
    Shared clientId As String = "my-client-id"
    Public Shared Scopes As String() = {"User.Read", "Files.ReadWrite.All"}
    Public Shared IdentityClientApp As PublicClientApplication = New PublicClientApplication(clientId)
    Public Shared TokenForUser As String = Nothing
    Public Shared Expiration As DateTimeOffset
    Private Shared graphClient As GraphServiceClient = Nothing

    Public Shared Function GetAuthenticatedClient() As GraphServiceClient
        If graphClient Is Nothing Then

            Try
                graphClient = New GraphServiceClient(
                    "https://graph.microsoft.com/v1.0",
                    New DelegateAuthenticationProvider(
                        Async Function(requestMessage)
                            Dim token = Await GetTokenForUserAsync()
                            requestMessage.Headers.Authorization = New AuthenticationHeaderValue("bearer", token)
                            requestMessage.Headers.Add("SampleID", "uwp-csharp-apibrowser-sample")
                        End Function))
                Return graphClient
            Catch ex As Exception
                Debug.WriteLine("Could not create a graph client: " & ex.Message)
            End Try
        End If

        Return graphClient
    End Function

    Public Shared Async Function GetTokenForUserAsync() As Task(Of String)
        Dim authResult As AuthenticationResult

        Dim ex As Exception = Nothing

        Try
            authResult = Await IdentityClientApp.AcquireTokenSilentAsync(Scopes, IdentityClientApp.GetUser("antonio.patricio@agu.gov.br"))
            TokenForUser = authResult.AccessToken
        Catch ex
            If TokenForUser Is Nothing OrElse Expiration <= DateTimeOffset.UtcNow.AddMinutes(5) Then
            End If
        End Try
        If ex IsNot Nothing Then
            Try
                authResult = Await IdentityClientApp.AcquireTokenAsync(Scopes)
                TokenForUser = authResult.AccessToken
                Expiration = authResult.ExpiresOn
            Catch ex
            End Try
        End If

        Return TokenForUser
    End Function

End Class

1 个答案:

答案 0 :(得分:0)

我在这里和那里检查了样本,并提出了这个包装器类。我想我会做更多的工作,但是目前,它解决了本文中提到的问题:

Imports System.Net.Http
Imports System.Net.Http.Headers
Imports Microsoft.Graph
Imports Microsoft.Identity.Client

Public Class MsGraph
    Private Const baseUrl As String = "https://graph.microsoft.com/v1.0"
    Private ReadOnly client_id As String
    Private ReadOnly scopes As String()
    Private authSuccess As Boolean
    Private clientApp As PublicClientApplication

    Public Sub New(app_client_id As String, ParamArray app_scopes As String())
        client_id = app_client_id
        If Not app_scopes.Contains("User.Read", StringComparer.InvariantCultureIgnoreCase) Then
            app_scopes = {"User.Read"}.Concat(app_scopes).ToArray
        End If
        scopes = app_scopes
        clientApp = New PublicClientApplication(client_id)
        Dim authProvider = New DelegateAuthenticationProvider(AddressOf AuthenticateRequestAsync)
        Try
            Client = New GraphServiceClient(baseUrl, authProvider)
        Catch ex As Exception
            Stop
        End Try
    End Sub

    Public ReadOnly Property Client As GraphServiceClient

    Public Async Function AuthenticateRequestAsync(request As HttpRequestMessage) As Task
        request.Headers.Authorization = New AuthenticationHeaderValue("bearer", Await GetTokenForUserAsync())
    End Function

    Private Async Function GetTokenForUserAsync() As Task(Of String)
        Dim success As Boolean
        Dim authResult As AuthenticationResult = Nothing
        If clientApp.Users.Any Then
            Try
                authResult = Await clientApp.AcquireTokenSilentAsync(scopes, clientApp.Users.FirstOrDefault())
                success = True
            Catch ex As Exception
                Stop
            End Try
        Else
            Try
                authResult = Await clientApp.AcquireTokenAsync(scopes)
                success = True
            Catch ex As Exception
                Stop
            End Try
        End If
        authSuccess = success
        Return authResult?.AccessToken
    End Function
End Class