使用 ADAL 从 UWP 中的 ADFS 获取 UserInfo

Posted

技术标签:

【中文标题】使用 ADAL 从 UWP 中的 ADFS 获取 UserInfo【英文标题】:Get UserInfo from ADFS in UWP with ADAL 【发布时间】:2017-10-12 17:23:43 【问题描述】:

我正在尝试使用 ADFS 对用户进行身份验证,并且我正在使用 ADAL。身份验证似乎有效,因为我可以获得 AccessToken。问题是查看代码authResult 包含一个UserInfo,其中所有属性(例如GivenNameFamilyName)都是null

AuthenticationContext authContext = null;
AuthenticationResult authResult;
try

    authContext = new AuthenticationContext(authority, false);
    authResult = await authContext.AcquireTokenAsync(resource, clientId, new Uri(returnUri),
                    new PlatformParameters(PromptBehavior.Auto, false));

由于 ADFS 配置,这些值为空?我注意到解码返回的 AccessToken 我可以读取用户信息。但我不认为解码 JWT Token 是获取这些信息的正确方法。你有更好的建议吗?

我也看到人们通过使用声明来获取信息,但我不知道如何在 UWP 上使用它,因为我发现的所有示例都使用过

ClaimsPrincipal claimsPrincipal = System.Threading.Thread.CurrentPrincipal as ClaimsPrincipal;

System.Threading.Thread 在 UWP 上不可用。

【问题讨论】:

【参考方案1】:

通常,access_token 用于 Oauth 和 OpenID 连接方案,并打算由资源使用。为了识别用户,我们应该使用id_token(验证令牌并通过解码令牌来提取与用户相关的声明)。代币的使用请参考以下:

id_token:用于表示用户身份的 JWT 令牌。这 id_token 的“aud”或受众声明与 本机或服务器应用程序。 access_token:用于 Oauth 和 OpenID 连接场景的 JWT 令牌 并打算被资源消耗。 “听众”或观众 此令牌的声明必须与资源或 Web 的标识符匹配 API。 refresh_token:提交此令牌代替收集用户 凭据以提供单点登录体验。这个令牌是 由 AD FS 发布和使用,客户端不可读 或资源。

关于 ADFS 的本地客户端到 Web API 场景,您可以参考以下链接:

AD FS Scenarios for Developers - Native client to Web API

【讨论】:

您能否帮助了解我如何获取 id_token 并提取声明? id_token 应该可以通过authResult 对象(authResult.IdToken) 作为您共享的代码获取。要从令牌中提取声明,您可以使用System.IdentityModel.Tokens.Jwt。这是一个similar thread 供您参考。 idtoken 仅在 ADFS 2016 中可用。请检查版本。【参考方案2】:

取决于您的服务器的 ADFS 版本。如果您的公司使用的是 Windows Server 2012 R2,那么它是 ADFS 3.0。我确实成功地与我工作的公司的管理员创建的 SSO 登录集成。你应该在冒险之前参考这篇文章:https://docs.microsoft.com/en-us/previous-versions/adfs-windows-server-2012r2/dn660968(v=msdn.10)。注意:你甚至不需要制作 ToDoList 的 web api。

仅使用 GetAuthorizationHeader() 和 authenticationContext.AcquireTokenAsync(),您可以通过要求用户授权其凭据并解密接收令牌来获取令牌。

这是我做的代码示例:

authority = https://contoso.com/adfs/ls(来自 ADFS 元数据的端点)

resourceURI = https://localhost:44300/(依赖方,请您的 ADFS 管理员注册)

clientID = 建议使用 Package.appmanifest 在 Packaging 标签中的包名。只要是唯一的 ID。

clientReturnURI = 使用以下代码获取clientReturnURI(也可以在文章中的链接中找到):

string clientReturnURI = string.Format("ms-appx-web://Microsoft.AAD.BrokerPlugIn/0",WebAuthenticationBroker.GetCurrentApplicationCallbackUri().Host.ToUpper());

AuthenticationContext ac = new AuthenticationContext(Authority_Uri, false); AuthenticationResult ar = await ac.AcquireTokenAsync(resourceURI, GlobalVar.clientID, new Uri(clientReturnURI), new PlatformParameters(PromptBehavior.Always, true));

            var jwt = new JwtSecurityToken(ar.AccessToken);
            string unique_name = jwt.Claims.First(c => c.Type == JwtRegisteredClaimNames.UniqueName).Value;

您可以将 JwtRegisteredClaimNames.UniqueName 替换为其他任何内容。这取决于访问令牌中可用的信息/声明。您应该通过在 var jwt 处放置断点来检查 jwt 中的可用信息。或者您可以在本网站的 AuthenticationResult.AccessToken 中解密访问令牌: https://jwt.ms/

最后,您需要从 ADFS 管理员处安装证书,并在您的 Web 和 UWP 服务器上安装该证书,以允许应用程序能够信任地执行操作。

【讨论】:

以上是关于使用 ADAL 从 UWP 中的 ADFS 获取 UserInfo的主要内容,如果未能解决你的问题,请参考以下文章