使用 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的主要内容,如果未能解决你的问题,请参考以下文章

如何从本地 SharePoint 2013 和 ADFS 获取 FedAuth Cookie

未从 ADFS 3.0 获取用于 OAuth2 访问令牌的 JWT 中的用户身份

共享点身份验证。如何从 ADFS 获取 SharePoint cookie

如何从 UWP(又名 .NET Core)中的 Type 对象获取程序集

如果在 UWP 中调用 authContext.AcquireTokenAsync,则出现 Null 异常

当前应用程序的 Adal.NET 获取令牌