【问题标题】:Azure active directory Logout or clear token cache for native appAzure 活动目录注销或清除本机应用程序的令牌缓存
【发布时间】:2016-08-31 21:20:36
【问题描述】:

我有一个 C# Web API REST 服务后端,我为 CMS、网页和 Angular2 应用程序提供服务(这是相关的这里)。 Angular 应用程序需要通过后端发送用户名和密码(原始凭据)进行身份验证,后端使用这些向 Azure Active Directory 请求 access_token(使用UserCredentials),并将 access_token 发送回 Angular 应用程序,以便用于在其请求中进行授权 (Authorization: Bearer)。这是我验证的方式:

UserCredential uc = new UserPasswordCredential(user, password);
AuthenticationContext authContext = new AuthenticationContext(Constants.authority, false);
AuthenticationResult result = authContext.AcquireTokenAsync(Constants.audience, Constants.clientIdNative, uc).Result;

问题是它会为该令牌生成一小时的缓存,如果用户注销并再次输入用户或用户 + 错误的密码,身份验证只是查找该用户的缓存并忽略或不t 验证密码。在一小时内,任何人都可以通过用户名进入。

我在这里和许多其他网站上找到了注销或清除令牌的方法,但这些不适用于我的后端,因为它是无状态的。我不管理它们之间的会话或 HTTP 上下文。如果有人可以指导解决这个问题,我正在使用 Microsoft.IdentityModel.Clients.ActiveDirectory 的最后一个程序集,版本 3.13.1.846,我知道 AcquireTokenByAuthorizationCodeAsync 方法不会查找缓存,但没有与原始凭据一起使用的实现。

谢谢大家,希望你们能帮助我。

【问题讨论】:

  • 当我输入答案时,您介意分享一下为什么您使用AuthenticationContext(string authority, bool validateAuthority) 构造函数并将validateAuthority 设置为false
  • 嗨@PhilippeSignoret,因为我真的不明白它会进行什么样的地址验证?我应该将其设置为 true 吗?我是 Azure 东西和 azure Active Directory 身份验证的新手。
  • 是的,最好使用不更改默认值的默认构造函数(true),除非您确定知道权限验证的含义以及禁用它的安全隐患。此构造函数的文档在这里(此特定构造函数自 v2 以来没有,这是引用的版本):msdn.microsoft.com/en-us/library/dn528729.aspx

标签: c# azure azure-active-directory adal


【解决方案1】:

强烈建议反对您所遵循的策略。对于您的应用程序来说,收集用户名和密码通常是一种不好的做法。此流程(Resource Owner Password Credentials (ROPC) Grant 流程)仅适用于其他机制不可用的场景。来自 OAuth 2.0 规范(已添加重点):

1.3.3。资源所有者密码凭证

资源所有者密码凭据(即用户名和密码) 可以直接用作授权授予来获得访问权限 令牌。凭证仅应在存在高 资源所有者和客户之间的信任程度(例如, 客户端是设备操作系统的一部分或具有高度特权的 应用程序),以及当其他授权授予类型不是 可用(例如授权码)

即使这种授权类型需要客户端直接访问 资源所有者凭据,使用资源所有者凭据 单个请求并交换访问令牌。这个 授权类型可以消除客户端存储 资源所有者凭据以供将来使用,通过交换 具有长期访问令牌或刷新令牌的凭据。

在针对 Azure AD 使用此流程时,您会发现此流程通常会失败,因为有时用户需要提供的不仅仅是用户名和密码。这不起作用的一些示例:

  • 用户需要同意应用程序请求的权限
  • 用户密码已过期,需要更改
  • 用户的凭据are suspected of being compromised
  • 用户的登录 is otherwise considered suspicious(在您的场景中更有可能,因为登录似乎来自网络服务器,而该服务器可能不在用户所在的位置)
  • 用户启用了多重身份验证
  • 用户是联合域名的一部分(其中权威身份提供者不是 Azure AD)

基本上,通过使用这种方法,您绕过了 OAuth 2.0 和 Azure AD 提供的大部分安全改进,并且通过使用用户名/密码流的方式使您自己、您的应用程序和您的用户处于危险之中它不打算被使用。

此外,虽然 Azure AD 服务 当前确实支持 ROPC 流,但您会发现在某些情况下实际上已从库中删除了对该流的支持(例如问题 #320 删除非来自 iOS/Android/WinRT 和 Issue #462 PCL UserCredential no longer supports password) 的交互式身份验证。

回答您的具体问题

(悬停以查看在您的情况下您不应该做什么,但回答您关于令牌缓存的问题。)

跳过令牌缓存的一种方法是简单地使用构造函数签名,该签名接受TokenCache 值并传入空TokenCache 值:

AuthenticationContext authContext =
    new AuthenticationContext(Constants.authority, false, null);

更好(但仍然非常糟糕)的方法

(真的,别这样,你还不如跳到下一节……)

如果您发现自己的本地客户端应用程序绝对必须使用用户名/密码流程,并且您接受风险并愿意忍受它们以及所有其他缺点,那么您的 Angular 应用程序应该是 @987654325 @ 直接发送给 Azure AD, 通过您的 API 后端。接收到的访问令牌随后可用于针对您的 API(或受 Azure AD 保护的其他 API,具体取决于您在令牌请求中指定为 resource 的内容)发出经过身份验证的请求。

正确的方法

正确的方法是让您的本机客户端应用程序使用任何受支持的流,这些流涉及将用户(通过 Web 浏览器或 Web 视图)发送到 Azure AD 进行身份验证。这样可以确保正确处理上述所有场景中的用户体验(同意提示、更改密码提示、多因素身份验证提示等)。它还允许您使用令牌缓存(改善整体体验,因为您不会为每次调用后端添加令牌请求)。

用户通过身份验证后,您的应用将拥有一个访问令牌、一个刷新令牌和一个 ID 令牌。您可以将这些令牌直接用于您的应用程序后端。如果您的应用程序的后端需要在用户的上下文中调用其他 API,它可以通过将其从本机客户端应用程序获得的访问令牌交换到另一个资源的访问令牌来执行此操作,代表用户访问令牌最初是被授予的(事实上,有一个示例就是这样做的:active-directory-dotnet-webapi-onbehalfof)。

对于 Angular2 应用程序,我建议查看 ADAL for JavaScript 库,并结合一些似乎增加了对 Angular2 支持的包装库(例如 angular2-adal)。

【讨论】:

  • 是的@PhilippeSignoret,我看到了 ADAL js 方法,但是有了这些方法,它首先将我重定向到微软登录页面,这是角度应用程序使用它自己的登录页面的要求(没有重定向到第三方登录或注销),但我没有找到不使用微软登录页面进行身份验证的方法。请你指导我好吗?
  • 是什么推动了这一要求?是否希望控制登录体验的外观?
  • 是的@PhilippeSignore,客户公司希望如此。
  • 此应用程序是否适用于一个组织中使用其工作或学校身份的用户?对于许多组织中使用工作或学校身份的用户?还是供所有用户使用的通用应用程序(即使他们没有 Azure Ad 工作或学校身份)?
  • 它适用于一个组织中使用其工作身份的用户
猜你喜欢
  • 1970-01-01
  • 2016-12-23
  • 1970-01-01
  • 1970-01-01
  • 2019-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-02
相关资源
最近更新 更多