Azure 活动目录注销或清除本机应用程序的令牌缓存

Azure active directory Logout or clear token cache for native app

我有一个 C# web API REST 服务后端,我为 CMS、网页和 Angular2 应用程序提供服务(这是相关的)。 Angular 应用程序需要通过后端发送用户名和密码(原始凭据)进行身份验证,后端使用这些向 Azure Active Directory(使用 UserCredentials)请求 access_token,并发送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;

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

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

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

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

1.3.3. Resource Owner Password Credentials

The resource owner password credentials (i.e., username and password) can be used directly as an authorization grant to obtain an access token. The credentials should only be used when there is a high degree of trust between the resource owner and the client (e.g., the client is part of the device operating system or a highly privileged application), and when other authorization grant types are not available (such as an authorization code).

Even though this grant type requires direct client access to the resource owner credentials, the resource owner credentials are used for a single request and are exchanged for an access token. This grant type can eliminate the need for the client to store the resource owner credentials for future use, by exchanging the credentials with a long-lived access token or refresh token.

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

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

基本上,通过使用这种方法,您将绕过 OAuth 2.0 和 Azure AD 提供的大部分安全改进,并且使用 username/password 流程将您自己、您的应用程序和您的用户置于风险之中以一种不打算使用的方式。

此外,虽然 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);

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

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

如果您发现自己的本地客户端应用程序绝对必须使用 username/password 流程,并且您接受风险并愿意忍受这些风险以及所有其他缺点,那么您的 Angular 应用程序应该 the token request 直接连接到 Azure AD, 而不是 通过您的 API 后端。然后,可以使用收到的访问令牌针对您的 API(或受 Azure AD 保护的其他 API 发出经过身份验证的请求,具体取决于您在令牌中指定的 resource请求)。

正确的做法

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

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

对于 Angular2 应用程序,我建议查看 ADAL for JavaScript library, in combination with some of the wrapper libraries that have appeared to add support for Angular2 (e.g. angular2-adal)。