Azure Mobile Services LoginAsync method not working with Microsoft Auth Token

偶尔善良 提交于 2021-02-08 07:57:25

问题


I have successfully been able to get an access_token (or authenticationToken for Microsoft tokens) using the client side authentication in my Xamarin forms App. I am able to get further user information (email, name, etc.) using the same access token. Now, when I try to pass that token to my Azure Mobile Service backend, I get a 401 error.

Here is my code:

        private async System.Threading.Tasks.Task<string> MSGetUserInfo(Account account)
    {
        // Reference: http://graph.microsoft.io/en-us/docs/overview/call_api
        // Note that Microsoft don't recognize the access_token header entry, but rely instead on an Authorization header entry

        var client = new HttpClient();
        var userInfoRequest = new HttpRequestMessage()
        {
            RequestUri = new Uri("https://graph.microsoft.com/v1.0/me"),
            Method = HttpMethod.Get,
        };
        // Add acccess Bearer
        userInfoRequest.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", account.Properties["access_token"]);
        using (var response = await client.SendAsync(userInfoRequest).ConfigureAwait(false))
        {
            if (response.IsSuccessStatusCode)
            {
                Models.User user = new Models.User();
                var responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                var jobject = JObject.Parse(responseString);
                var userName = (string)jobject["userPrincipalName"];
                // Check username is valid
                if (String.IsNullOrEmpty(userName))
                {
                    throw new Exception("Username was not set for authenticated user");
                }
                else
                    user.ProviderLoginId = userName;

                var userDisplayName = (string)jobject["displayName"];
                // Replace display name if invalid
                if (String.IsNullOrWhiteSpace(userDisplayName))
                {
                    userDisplayName = userName;
                }
                else
                    user.Name = userDisplayName;
                var userEmail = (string)jobject["mail"];
                // Replace email if invalid
                if (String.IsNullOrWhiteSpace(userEmail))
                {
                    userEmail = userName;
                }
                else
                    user.Email = userEmail;

                Valufy.App.currentUser = user;
            }
            else
            {
                throw new Exception("OAuth2 request failed: " + await response.Content.ReadAsStringAsync().ConfigureAwait(false));
            }
        }
        return "success";
    }

The above code snippet works in getting my user details. Now when I try to use the same token in the subsequent call, I get a 404:

        public async Task<bool> Authenticate(string token)
    {
        string message = string.Empty;
        var success = false;
        JObject objToken = new JObject();
        //objToken.Add("access_token", token);  //for facebook and google
        objToken.Add("authenticationToken", token); //for microsoft

        try
        {
            // Sign in with Facebook login using a server-managed flow.
            if (user == null)
            {
                //ProviderAuth("MICROSOFT");
                user = await syncMgr.CurrentClient
                    .LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount, objToken);
                if (user != null)
                {
                    success = true;
                    message = string.Format("You are now signed-in as {0}.", user.UserId);
                }
            }

        }
        catch (Exception ex)
        {
            message = string.Format("Authentication Failed: {0}", ex.Message);
        }

        // Display the success or failure message.
   //     await new MessageDialog(message, "Sign-in result").ShowAsync();

        return success;
    }

Is there something that I am doing wrong? Any and all assistance is appreciated.


回答1:


According to your description, I followed this Git sample about Microsoft Graph Connect Sample for UWP (REST). I could get the access_token and it could work as expected with Microsoft Graph API (e.g. Get a user). But when I use this access_token as the authenticationToken token object for MobileServiceClient.LoginAsync, I could also get 401 Unauthorized.

Then I checked the managed client for Azure Mobile Apps about Authenticate users. For Client-managed authentication flow, I found that the official code sample about using Microsoft Account is working with Live SDK as follows:

// Request the authentication token from the Live authentication service.
// The wl.basic scope should always be requested.  Other scopes can be added
LiveLoginResult result = await liveIdClient.LoginAsync(new string[] { "wl.basic" });
if (result.Status == LiveConnectSessionStatus.Connected)
{
    session = result.Session;

    // Get information about the logged-in user.
    LiveConnectClient client = new LiveConnectClient(session);
    LiveOperationResult meResult = await client.GetAsync("me");

    // Use the Microsoft account auth token to sign in to App Service.
    MobileServiceUser loginResult = await App.MobileService
        .LoginWithMicrosoftAccountAsync(result.Session.AuthenticationToken);
}

Note: As LiveConnectSession states about AuthenticationToken:

The authentication token for a signed-in and connected user.

While check the authentication with Microsoft Graph, I could only find the access_token instead of AuthenticationToken.

UPDATE:

I have checked LiveLogin for WP8 and Microsoft Account Authentication for Mobile Apps via Fiddler to capture the authorize requests. I found that MS account authentication has the similar authorize request as Live SDK.

I assumed that you need to leverage Live SDK to authenticate the user when using client side authentication with Microsoft account. I found the Live SDK download page is not exist, you could follow the Live SDK for WP8 to get started with Live SDK.

UPDATE2:

For the client-flow authentication (Microsoft Account), you could leverage MobileServiceClient.LoginWithMicrosoftAccountAsync("{Live-SDK-session-authentication-token}"), also you could use LoginAsync with the token parameter of the value {"access_token":"{the_access_token}"} or {"authenticationToken":"{Live-SDK-session-authentication-token}"}. I have tested LoginAsync with the access_token from MSA and retrieve the logged info as follows:



来源:https://stackoverflow.com/questions/43105903/azure-mobile-services-loginasync-method-not-working-with-microsoft-auth-token

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!