AzureAD / azure-activedirectory-library-for-objc

The ADAL SDK for Objective C gives you the ability to add support for Work Accounts to your iOS and macOS applications with just a few lines of additional code. This SDK gives your application the full functionality of Microsoft Azure AD, including industry standard protocol support for OAuth2, Web API integration with user level consent, and two factor authentication support.
MIT License
177 stars 113 forks source link

ADAL fix for ADFS PkeyAuth issue #1560

Closed NerevarineRule closed 3 years ago

NerevarineRule commented 3 years ago

When PKeyAuth is enabled through UA string, Client-side PKeyAuth handler creates a PkeyAuth header and then responds to the server-side challenge.

There was a bug in the client-side code, specifically in the msidEncodeStringFromDictionary API in the MSID category method for the NSString object.

This API constructs a URL string from the key-value pairs contained in the input dictionary. ex: https://fs.msidlab4.com/adfs/ls/?&key1=value1&key2=value2&......&keyn=valuen.

This input dictionary is constructed from the submitURL parameter contained within the PKeyAuth request URL returned by the server. this submitURL field contains the information about the endpoint to which the PKeyAuth response must be submitted.

This is how the flow goes:

Client submits PKeyAuth request through the UA string Server sees the request, and returns the challenge request URL, upon which the client must respond with a valid PKeyAuth header to the endpoint stored in the challenge request URL's submitURL parameter. Client first converts the submitURL field into a dictionary with different key value pairs, where each key-value is generated from the components separated by & field, and each component takes the following format: &key1=value1&key2=value2....&keyn=valuen. Then, client adds the "x-client-Ver" key-value pair to the dictionary in the step 3. Client converts the dictionary back into the URL format using msidEncodeStringFromDictionary API. During the transition from liveID endpoint to OrgID endpoint, namely, between AAD and ADFS transition point, AAD's JS logic appends three additional parameters: cbctx, lc, and mkt to the ADFS endpoint URL string, and this also propagates to the SubmitURL field in the PKeyAuth request URL string. However, they do not contain any additional information, so the SubmitURL would have the following structure: &cbctx=&lc=&mkt=

When they are converted into key-value pairs & stored in a dictionary, this dictionary is then fed into msidEncodeStringFromDictionary API after "x-client-Ver" key-value pair is added.

However, this API does not add "=" after the key, if the value a non-null empty string. So, the end result is a URL that will have &cbctx&lc&mkt in the string. This breaks ADFS's input parser logic, since it also delimits the URL string based on '=' character, when not having that character would throw an exception.

The fix is to add "=" in the WWWFormURLEncode API, even if the value is an empty string, and this complies with the URL query string spec as well, and both AAD and ADFS also comply with this convention.

Additionally, ADAL first extracts certificate issuer from the WPJ keychain, and then tries to look for it in the list of certificate authorities embedded in the challenge data returned by the server using regex matching. That list of certificate authorities is stored in the string format, but it was not decoded properly in ADAL's latest release branch/master, while MSAL does.