如何为 UWP 启用 App Service Mobile App SSO
How to enable App Service Mobile App SSO for UWP
我正在构建一个通用 Windows 平台 (UWP) 应用程序,它使用 Azure 应用服务移动应用程序后端以及用户的 OneDrive 帐户。我有 2 个身份验证要求:
- 如果用户使用 Microsoft 帐户登录到他们的 UWP 设备(例如 Windows 10),那么我不希望他们看到登录提示(即单点登录,重新登录)使用他们的 Microsoft 帐户凭据)。
- 我想在 Azure 和 OneDrive 中进行单一身份验证事件,即用户授权一次,我为这两项服务重新使用该令牌。
我在 Windows Phone 8 中使用 Azure 移动服务通过使用 Live SDK 登录然后将返回的令牌传递给 MobileServiceClient.LoginAsync()
方法来完成此操作,但是我可以' 使用 Azure 移动应用让它在 UWP 中工作。当我调用相同的方法时,我收到 401 Unauthorised
响应。
- 我已将我的 UWP 应用程序与商店相关联并设置了
在 Microsoft 帐户开发人员中心申请,包括
从 Azure 移动应用添加重定向 URI。
- 我已经设置了 Azure App Service 移动应用程序,包括添加
来自 Microsoft 帐户开发人员中心的客户端 ID 和密码。
- 我尝试了多种方法来检索令牌,包括
OnlineIdAuthenticator
、WebAuthenticationCoreManager
和
WebAuthenticationBroker
。 None 目前有效。
我目前在 class LiveAuthenticationService
中使用以下代码来检索访问令牌:
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;
}
然后尝试使用该令牌登录我的 Azure 移动应用程序,该令牌使用上面的 LiveAuthenticationService
:
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;
}
}
如前所述,这会导致 Azure 发出 401 未经授权的响应。我有 运行 Fiddler,请求似乎是正确的,预期的身份验证令牌包含在请求的 JSON 负载中。
更新
我可以看到的一件事是上面的代码发出的令牌有将近 900 个字符长,都是 YnElFkAAcK8bRSQab/FK+PT5n/wA4CPU...
的形式,而如果我让 Azure 移动应用程序处理身份验证,即调用 MobileServiceClient.LoginAsync()
发出的令牌] 不传递标记,只有大约 350 个字符长,格式为 hbGciOi.eyJmdWWxsIiwiRGJn...
(注意开头的句点)。
这个问题现在真的让我很头疼。没有身份验证工作,我无法发布该应用程序,我无法弄清楚如何修复它。任何帮助将不胜感激。
这对我来说很难解决,因为我也遇到了这个问题。
最重要的部分是 OnlineIdServiceTicketRequest
请求应如下所示:
var mobileServicesTicket = new OnlineIdServiceTicketRequest("https://yourmobileservice.azure-mobile.net/", "JWT");
请注意,我们正在指定您的端点并且还请求 JWT 令牌而不是委托。这将获得您正在寻找的 350ish 字符令牌。
这是我正在做的事情的完整代码示例:
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
被注入 class 并且是对 WindowsAzure.MobileServices
库中 Microsoft.WindowsAzure.MobileServices.MobileServiceClient
对象的引用。
我实际上在这里写了一篇关于这个问题的博客文章http://jshapland.com/single-sign-on-with-azure-mobile-services-in-a-uwp-app/
我正在构建一个通用 Windows 平台 (UWP) 应用程序,它使用 Azure 应用服务移动应用程序后端以及用户的 OneDrive 帐户。我有 2 个身份验证要求:
- 如果用户使用 Microsoft 帐户登录到他们的 UWP 设备(例如 Windows 10),那么我不希望他们看到登录提示(即单点登录,重新登录)使用他们的 Microsoft 帐户凭据)。
- 我想在 Azure 和 OneDrive 中进行单一身份验证事件,即用户授权一次,我为这两项服务重新使用该令牌。
我在 Windows Phone 8 中使用 Azure 移动服务通过使用 Live SDK 登录然后将返回的令牌传递给 MobileServiceClient.LoginAsync()
方法来完成此操作,但是我可以' 使用 Azure 移动应用让它在 UWP 中工作。当我调用相同的方法时,我收到 401 Unauthorised
响应。
- 我已将我的 UWP 应用程序与商店相关联并设置了 在 Microsoft 帐户开发人员中心申请,包括 从 Azure 移动应用添加重定向 URI。
- 我已经设置了 Azure App Service 移动应用程序,包括添加 来自 Microsoft 帐户开发人员中心的客户端 ID 和密码。
- 我尝试了多种方法来检索令牌,包括
OnlineIdAuthenticator
、WebAuthenticationCoreManager
和WebAuthenticationBroker
。 None 目前有效。
我目前在 class LiveAuthenticationService
中使用以下代码来检索访问令牌:
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;
}
然后尝试使用该令牌登录我的 Azure 移动应用程序,该令牌使用上面的 LiveAuthenticationService
:
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;
}
}
如前所述,这会导致 Azure 发出 401 未经授权的响应。我有 运行 Fiddler,请求似乎是正确的,预期的身份验证令牌包含在请求的 JSON 负载中。
更新
我可以看到的一件事是上面的代码发出的令牌有将近 900 个字符长,都是 YnElFkAAcK8bRSQab/FK+PT5n/wA4CPU...
的形式,而如果我让 Azure 移动应用程序处理身份验证,即调用 MobileServiceClient.LoginAsync()
发出的令牌] 不传递标记,只有大约 350 个字符长,格式为 hbGciOi.eyJmdWWxsIiwiRGJn...
(注意开头的句点)。
这个问题现在真的让我很头疼。没有身份验证工作,我无法发布该应用程序,我无法弄清楚如何修复它。任何帮助将不胜感激。
这对我来说很难解决,因为我也遇到了这个问题。
最重要的部分是 OnlineIdServiceTicketRequest
请求应如下所示:
var mobileServicesTicket = new OnlineIdServiceTicketRequest("https://yourmobileservice.azure-mobile.net/", "JWT");
请注意,我们正在指定您的端点并且还请求 JWT 令牌而不是委托。这将获得您正在寻找的 350ish 字符令牌。
这是我正在做的事情的完整代码示例:
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
被注入 class 并且是对 WindowsAzure.MobileServices
库中 Microsoft.WindowsAzure.MobileServices.MobileServiceClient
对象的引用。
我实际上在这里写了一篇关于这个问题的博客文章http://jshapland.com/single-sign-on-with-azure-mobile-services-in-a-uwp-app/