Azure活动目录注销或清除本机应用程序

时间:2016-08-31 00:38:30

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

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

问题是它为该令牌生成一小时缓存,如果用户注销并仅使用用户或用户+错误密码再次进入,则身份验证只会查找该用户的缓存并忽略或不#& 39; t验证密码。在一小时的窗口中,任何人都可以使用用户名进入。

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

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

1 个答案:

答案 0 :(得分:8)

强烈建议您遵循对抗的策略。对于您的应用程序来说,收集用户名和密码通常是不好的做法。此流(Resource Owner Password Credentials (ROPC) Grant流)仅适用于其他机制不可用的情况。从OAuth 2.0规范(重点补充):

  

1.3.3。资源所有者密码凭证

     

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

     

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

对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值的构造函数签名并传入null TokenCache值:
 

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

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

(真的,不要这样做,你也可以跳到下一节......)

  

如果您发现自己的本机客户端应用程序绝对必须使用用户名/密码流,并且您接受风险并且愿意与它们一起生活以及所有其他缺点,那么您的Angular应用程序应该正在制作{{ 3}}直接到Azure AD,通过您的API后端。然后,可以使用收到的访问令牌对您的API(或Azure AD保护的其他API)进行经过身份验证的请求,具体取决于您在令牌请求中指定的resource

正确的方法

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

用户通过身份验证后,您的应用将拥有访问令牌,刷新令牌和ID令牌。您可以直接在应用程序后端使用这些令牌。如果您的应用程序的后端需要在用户的上下文中调用其他API,则可以通过将其从本机客户端应用程序获取的访问令牌作为访问令牌交换到另一个资源,代表最初授予访问令牌的用户(实际上,有一个样本正是这样做的:the token request)。

对于Angular2应用程序,我建议您查看active-directory-dotnet-webapi-onbehalfof库,并结合一些似乎添加对Angular2的支持的包装库(例如ADAL for JavaScript)。