How to enable SSO app for mobile app for UWP

I am creating a Universal Windows Platform (UWP) application that uses the backend of the Mobile App Service for Azure applications, as well as the OneDrive user account. I have 2 requirements for authentication:

  • If a user logs on to their UWP device with a Microsoft account (for example, Windows 10), then I do not want them to have a login prompt (for example, Single Sign On, reusing Microsoft credentials).
  • I want to have one authentication event through Azure and OneDrive, that is, the user allows once, and I reuse this token for both services.

I did this on Windows Phone 8 with the Azure Mobile Service by logging into the Live SDK and passing the returned token to the MobileServiceClient.LoginAsync() method, however I cannot get this to work in UWP with the Azure Mobile Application. When I call the same method, I get a 401 Unauthorised response.

  • I linked my UWP application to the store and installed the applications in the Microsoft Account Developer Center, including adding the redirect URI from the Azure Mobile application.
  • I installed the Azure App mobile app, including adding Client ID and secret key from Microsoft Account Development Center.
  • I tried many ways to get the token, including OnlineIdAuthenticator , WebAuthenticationCoreManager and WebAuthenticationBroker . So far no one has worked.

I am currently using the following code in the LiveAuthenticationService class to get an access token:

 public async Task<bool> LoginAsync() { AccessToken = null; bool success = false; OnlineIdAuthenticator onlineIdAuthenticator = new OnlineIdAuthenticator(); EventWaitHandle waithandle = new ManualResetEvent(false); OnlineIdServiceTicketRequest serviceTicketRequest = new OnlineIdServiceTicketRequest(scopes, "DELEGATION"); UserIdentity result = await onlineIdAuthenticator.AuthenticateUserAsync(serviceTicketRequest); if (!string.IsNullOrWhiteSpace(result?.Tickets[0]?.Value)) { currentUserId = result.SafeCustomerId; AccessToken = result.Tickets[0].Value; success = true; waithandle.Set(); } else { await logger.LogErrorAsync("Error signing in to Microsoft Live", new Dictionary<string, string> { { "errorCode", result?.Tickets[0]?.ErrorCode.ToString() } }); } waithandle.WaitOne(10000); //10 second timeout return success; } 

And then, to try to enter my Azure Mobile app with this token that uses the LiveAuthenticationService from above:

 private async Task RefreshUserIdAndAccessToken() { try { var tcs = new TaskCompletionSource<MobileServiceUser>(); var authService = new LiveAuthenticationService(); await UiDispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => { try { await authService.LoginAsync(); var jsonAuthenticationToken = JObject.Parse(@"{""authenticationToken"": """ + authService.AccessToken + @"""}"); tcs.SetResult(await mobileService.LoginAsync(MobileServiceAuthenticationProvider.MicrosoftAccount, jsonAuthenticationToken)); } catch (Exception ex) { tcs.SetException(ex); } }); var user = await tcs.Task; currentUserId = user.UserId; AccessToken = user.MobileServiceAuthenticationToken; } catch (Exception ex) { await logger.LogExceptionAsync(ex, Constants.LOGGING_DATAKEY_REFRESHACCESSTOKENFAILURE, currentUserId); currentUserId = null; AccessToken = null; } } 

As indicated, this results in a 401 Unauthorized Response from Azure. I ran Fiddler and the request seems correct, the expected authentication token is included in the JSON payload with the request.

UPDATE The only thing I see is that the token issued by the code above is almost 900 characters, all in the form of YnElFkAAcK8bRSQab/FK+PT5n/wA4CPU... , and the token issued if I allow Azure Mobile App to process authentication, those. Calling MobileServiceClient.LoginAsync() without passing the token is only about 350 characters in the form hbGciOi.eyJmdWWxsIiwiRGJn... (note the period at the beginning).

This problem really causes me problems. I cannot release the application without authentication, and I cannot figure out how to fix it. Any help would be appreciated.

+5
source share
1 answer

It was difficult for me to solve, because I ran into this problem too.

The most important part is the OnlineIdServiceTicketRequest request should look like this:

 var mobileServicesTicket = new OnlineIdServiceTicketRequest("https://yourmobileservice.azure-mobile.net/", "JWT"); 

Please note that we indicate your endpoint, and also request a JWT token instead of delegation. This will get the iconic character you were looking for.

Here is the complete code example that I am doing:

 public async Task<bool> LoginAsync() { var authenticator = new Windows.Security.Authentication.OnlineId.OnlineIdAuthenticator(); var mobileServicesTicket = new Windows.Security.Authentication.OnlineId.OnlineIdServiceTicketRequest("https://yourendpoint.azure-mobile.net/", "JWT"); var ticketRequests = new List<OnlineIdServiceTicketRequest>() { mobileServicesTicket }; var authResult = await authenticator.AuthenticateUserAsync(ticketRequests, CredentialPromptType.PromptIfNeeded); if ((authResult.Tickets.Count == 1) && (authResult.Tickets[0].ErrorCode == 0)) { var accessToken = authResult.Tickets[0]; var res = await _mobileServiceClient.LoginWithMicrosoftAccountAsync(accessToken.Value); return true; } else { return false; } } 

_mobileServiceClient is introduced into the class and is a reference to the Microsoft.WindowsAzure.MobileServices.MobileServiceClient object in the WindowsAzure.MobileServices library.

Actually I wrote a blog article about this problem here http://jshapland.com/single-sign-on-with-azure-mobile-services-in-a-uwp-app/

+4
source

Source: https://habr.com/ru/post/1232587/