ADAL iOS - Different user was authenticated. Expected userA@mydomain.com, actual userB@mydomain.com

半世苍凉 提交于 2019-12-11 07:09:24

问题


I am using ADALiOS to access OneDrive for business service, and I use below snippet to authenticate a user after account disambiguation,

    ADAuthenticationContext *context = ....

   [context acquireTokenWithResource:resource
                             clientId:clientId
                          redirectUri:redirectUri
                       promptBehavior:AD_PROMPT_ALWAYS
                               userId:@"userA@mydomain.com"
                 extraQueryParameters:@""
                      completionBlock:^(ADAuthenticationResult *result) {
                      ...
                      }

The web authentication UI will prompt, and allow user to input credential to continue. The issue here is, in this page, user can also change the user id to "userB@mydomain.com", and completion block will be invoked with a error like "Different user was authenticated. Expected userA@mydomain.com, actual userB@mydomain.com". Am I using ADALiOS wrong?


回答1:


When you specify a userId, ADAL assumes that it was specified because that was truly the user that you wanted. If the resulting user is not the one that was asked for, then you get the error you are seeing. If you don't care which user is authenticated then you can pass nil as the userId parameter and you won't get the error.

The ADAL library does this out of an over abundance of caution. Despite what the userId parameter implies, when you call ADAL there is no way for ADAL to guarantee that you will get a token for the user that you asked for. It will do it's best. If it can find a token for that user in the cache then it will return it. However, as you've seen, if the interactive flow is invoked, nothing prevents the user from entering a different username than the one that was asked for. In that case, a token for a different user will be returned. What happens if the app has associated some UI elements or private resources with a particular userId? If it get's a token for a different user than was asked for, then it might be mixing users in a way that is not obvious to the user of the app. If the user originally signed in as a low privilege user, but subsequently signed in as an admin, and the app doesn't notice this, then bad things may happen. So, the library assumes that if you asked for a specific user, then that is the only user that is acceptable.

What follows is probably more detail than you need but just to be complete I will continue. The userId parameter is unfortunately overloaded for three different purposes.

  1. As a cache lookup key. If ADAL has previously authenticated the passed user, and has a token or refresh token for that user in the cache, then it can look up that token directly and avoid any need for an AAD request. If you only ever authenticate a single user at a time, then this doesn't add any value as ADAL will attempt to find a token valid for the resource that was passed.

  2. As a login hint to the server. The userId is used to prefill the username field as a convenience to the user. However, the user is free to erase that username and provide a different one.

  3. As a hint for home realm discovery. If the user is a federated user, meaning that AAD needs to refer to ADFS (or some other federation server) for authentication, it needs a username to determine the address of the server to which it should refer. Normally this is done via a two step process. The user first lands on an AAD page and types their username. As soon as the username field loses focus the server looks up the username, and if it is a federated user, it starts redirecting them to their ADFS server. Finally, the user lands on the ADFS login page and they find their username already filled in. They enter their password and authentication completes. However, if you pass a userId parameter its value is passed to AAD. As a result, AAD no longer needs to wait for the user to type their username and can send them directly to their federation server, eliminating one page, and allowing the user to go directly to signing in.

If you need 2 or 3, but you don't care about 1 there is a workaround. You can specify nil for the userId but add "login_hint="username" as the extraQueryParameters parameter. Replace "username" with the username you would have passed in the userId parameter. If you do this, then ADAL will be oblivious to the user you have asked for, but AAD will interpret the username as a login hint to prefill the username field, and as a home realm discovery hint. The check to ensure that the user asked for is the user returned will be bypassed. You need to be very aware that you may not get a token for the user you provided as the login_hint. You should ensure that you verify the user before making any assumptions about who they are or what they might have access to.




回答2:


@Ryan Pangrle is right.

The above work around may not work properly anymore if Microsoft Authenticator is installed.

ADAL has been providing the following API to solve this issue since ADAL 2.1+ :

- (void)acquireTokenWithResource:(NSString*)resource
clientId:(NSString*)clientId
redirectUri:(NSURL*)redirectUri
promptBehavior:(ADPromptBehavior)promptBehavior
userIdentifier:(ADUserIdentifier*)userId
extraQueryParameters:(NSString*)queryParams
completionBlock:(ADAuthenticationCallback)completionBlock;

where developers can set the UPN match to be optional in the (ADUserIdentifier*)userId parameter.



来源:https://stackoverflow.com/questions/26694432/adal-ios-different-user-was-authenticated-expected-useramydomain-com-actual

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!