我正在使用ADALiOS访问OneDrive以获取商业服务,我使用以下代码段在帐户消除歧义后对用户进行身份验证,
ADAuthenticationContext *context = ....
[context acquireTokenWithResource:resource
clientId:clientId
redirectUri:redirectUri
promptBehavior:AD_PROMPT_ALWAYS
userId:@"userA@mydomain.com"
extraQueryParameters:@""
completionBlock:^(ADAuthenticationResult *result) {
...
}
Web身份验证UI将提示,并允许用户输入凭据以继续。这里的问题是,在此页面中,用户还可以将用户ID更改为" userB@mydomain.com" ;,并且将调用完成块,其中包含错误,例如"不同的用户已通过身份验证。预计userA@mydomain.com,实际userB@mydomain.com"。我使用ADALiOS错了吗?
答案 0 :(得分:3)
当您指定userId时,ADAL会假定它已被指定,因为它确实是您想要的用户。如果生成的用户不是被要求的用户,则会收到您看到的错误。如果您不关心哪个用户经过身份验证,那么您可以将nil作为userId参数传递,但您不会收到错误。
ADAL库出于过分谨慎的考虑。尽管userId参数意味着什么,但当您调用ADAL时,ADAL无法保证您将获得您要求的用户的令牌。它会做到最好。如果它可以在缓存中找到该用户的令牌,那么它将返回它。但是,正如您所见,如果调用交互式流程,则不会阻止用户输入与请求的用户名不同的用户名。在这种情况下,将返回不同用户的令牌。如果应用程序已将某些UI元素或私有资源与特定userId相关联,会发生什么?如果它获得的用户名不同于其他用户,那么它可能会以对应用用户不明显的方式混合用户。如果用户最初以低权限用户身份登录,但随后以管理员身份登录,并且应用程序没有注意到这一点,那么可能会发生不好的事情。因此,该库假定如果您要求特定用户,那么这是唯一可接受的用户。
以下内容可能比您需要的更详细,但为了完整,我会继续。遗憾的是,userId参数因三种不同的目的而被重载。
作为缓存查找键。如果ADAL先前已对传递的用户进行了身份验证,并且在缓存中具有该用户的令牌或刷新令牌,则它可以直接查找该令牌并避免任何需要AAD请求。如果您一次只验证一个用户,那么这不会添加任何值,因为ADAL将尝试查找对传递的资源有效的令牌。
作为服务器的登录提示。 userId用于预填充用户名字段以方便用户。但是,用户可以自由删除该用户名并提供不同的用户名。
作为家庭领域发现的暗示。如果用户是联合用户,意味着AAD需要引用ADFS(或某些其他联合服务器)进行身份验证,则需要用户名来确定它应该引用的服务器的地址。通常这是通过两步过程完成的。用户首先登陆AAD页面并键入其用户名。只要用户名字段失去焦点,服务器就会查找用户名,如果是联合用户,则会开始将其重定向到其ADFS服务器。最后,用户登陆ADFS登录页面,他们发现用户名已经填写。他们输入密码并完成身份验证。但是,如果传递userId参数,则将其值传递给AAD。因此,AAD不再需要等待用户键入其用户名,并可以将其直接发送到联合服务器,从而消除一个页面,并允许用户直接登录。
如果你需要2或3,但是你不在乎1有一个解决方法。您可以为userId指定nil,但添加" login_hint =" username"作为extraQueryParameters参数。替换"用户名"使用您在userId参数中传递的用户名。如果您这样做,那么ADAL将无视您要求的用户,但AAD会将用户名解释为登录提示以预填充用户名字段,并作为家庭领域发现提示。确保用户要求的检查是绕过的用户。您需要非常清楚,您可能无法获得作为login_hint提供的用户的令牌。在对用户或他们可能访问的内容做出任何假设之前,您应该确保验证用户。
答案 1 :(得分:0)
@Ryan Pangrle是对的。
如果安装了Microsoft身份验证器,上述解决方法可能无法正常工作。
自ADAL 2.1+以来,ADAL一直提供以下API来解决此问题:
- (void)acquireTokenWithResource:(NSString*)resource
clientId:(NSString*)clientId
redirectUri:(NSURL*)redirectUri
promptBehavior:(ADPromptBehavior)promptBehavior
userIdentifier:(ADUserIdentifier*)userId
extraQueryParameters:(NSString*)queryParams
completionBlock:(ADAuthenticationCallback)completionBlock;
开发人员可以在(ADUserIdentifier *)userId参数中将UPN匹配设置为可选。