Security > Authentication and user identity

UWP支持若干种用户验证方法,囊括简单的单点登录(SSO),以及安全性更高的两步验证(two factor)。

连接第三方服务,可以使用Web authentication broker。可以搭配Credential Lock来帮助记忆用户口令。

对于企业用户,可以考虑Microsoft Passport and Windows Hello,或者Smart cards或者Figerprint biometrics

Web authentication broker

通过AuthenticateAsync API,可以方便地从第三方OpenID或者OAuth服务获得验证信息。

一个示例: https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/WebAuthenticationBroker

使用OpenID或者OAuth之前,你地App必须在第三方服务中注册并获得一个ID以及密令。这些是要作为参数添加在请求验证的uri中的。同时要提供一个redirect_uri,作为验证成功后的回调。

Windows.Security.Authentication.Web命名空间中还有一个AuthenticateAndContinue,这是给Windows Phone 8.1用的遗留API,已经废弃了。

默认情况下,AuthenticateBroker不会保留cookie,也就不支持SSO。为了使用SSO,首先目标服务必须支持(允许redirect_uri为ms-app://<appSID>格式,然后在调用AuthenticateAsync的时候需要使用不带redirect_uri的那个版本。这种情况下redirect_uri会自动填充,通过GetCurrentApplicationCallbackUri可以获取填充的redirect_uri:

string result;

try
{
    var webAuthenticationResult = 
        await Windows.Security.Authentication.Web.WebAuthenticationBroker.AuthenticateAsync( 
        Windows.Security.Authentication.Web.WebAuthenticationOptions.None, 
        startURI);

    switch (webAuthenticationResult.ResponseStatus)
    {
        case Windows.Security.Authentication.Web.WebAuthenticationStatus.Success:
            // Successful authentication. 
            result = webAuthenticationResult.ResponseData.ToString(); 
            break;
        case Windows.Security.Authentication.Web.WebAuthenticationStatus.ErrorHttp:
            // HTTP error. 
            result = webAuthenticationResult.ResponseErrorDetail.ToString(); 
            break;
        default:
            // Other error.
            result = webAuthenticationResult.ResponseData.ToString(); 
            break;
    } 
}
catch (Exception ex)
{
    // Authentication failed. Handle parameter, SSL/TLS, and Network Unavailable errors here. 
    result = ex.Message;
}

调试的话可以查看事件日志或者通过Fiddler查看web请求和答复。

事件日志需要打开everntvwr.exe,然后开启Application and Services\Microsoft\Windows\WebAuth\Operational 通道。

Authenticate Broker会在User-Agent字段中添加MSAuthHost/1.0字样。

使用Fildder web调试器的话,需要开启AuthHost的PrivateNetwork权限:

REG ADD "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\authhost.exe" /v EnablePrivateNetwork /t REG_DWORD /d 1 /f

接着设置:

CheckNetIsolation.exe LoopbackExempt -a -n=microsoft.windows.authhost.a.p_8wekyb3d8bbwe
CheckNetIsolation.exe LoopbackExempt -a -n=microsoft.windows.authhost.sso.p_8wekyb3d8bbwe
CheckNetIsolation.exe LoopbackExempt -a -n=microsoft.windows.authhost.sso.c_8wekyb3d8bbwe
D:\Windows\System32>CheckNetIsolation.exe LoopbackExempt -s
List Loopback Exempted AppContainers
[1] -----------------------------------------------------------------
    Name: microsoft.windows.authhost.sso.c_8wekyb3d8bbwe
    SID:  S-1-15-2-1973105767-3975693666-32999980-3747492175-1074076486-3102532000-500629349
[2] -----------------------------------------------------------------
    Name: microsoft.windows.authhost.sso.p_8wekyb3d8bbwe
    SID:  S-1-15-2-166260-4150837609-3669066492-3071230600-3743290616-3683681078-2492089544
[3] -----------------------------------------------------------------
    Name: microsoft.windows.authhost.a.p_8wekyb3d8bbwe
    SID:  S-1-15-2-3506084497-1208594716-3384433646-2514033508-1838198150-1980605558-3480344935

然后在防火墙开启一个规则,将流入的数据导入Fiddler

实际经验

对于OneDrive,request_uri中要指定redirect_uri否则会出现:

We're unable to complete your request

invalid_request: The provided value for the input parameter 'redirect_uri' is not valid. The expected value is a URI which matches a redirect URI registered for this client application.

WebAuthenticationBroker的意义在于通过AuthHost提供一个安全的Webview,让用户可以放心输入密码。

AuthenticateAsync的第三个参数endUri是让AuthHost得以匹配服务器返回的数据,知道何时结束并关闭弹出的Webview。SSO的情况下,endUri不需要指定,因为默认为App的SID,比如:“ms-app://S-1-15-2-3506084497-1208594716-3384433646-2514033508-1838198150-1980605558-3480344935”。 这个SID需要在第三方服务商那边指定,并且能够返回给AuthHost,这样才能让AuthHost知道何时该结束进程。

参考

(未完待续)

2020-04-27更新

从Fiddler中看,最新的Authhost的应用包名字变成了

  • microsoft.windows.authhost.a_8wekyb3d8bbwe
  • microsoft.windows.authhost.sso_8wekyb3d8bbwe

(更新完)