Skip to content

SSO between ADAL and MSAL based apps

Olga Dalton edited this page Sep 24, 2018 · 2 revisions

MSAL for iOS starting with 0.2.0 is able to co-exist and share SSO state with ADAL Objective-C. Therefore, you can migrate your apps to MSAL Objective-C at your own pace, ensuring that your users will still benefit from cross-app SSO.

Note: if you're looking for guidance of setting up cross-app SSO between apps using MSAL SDK, you can find it here. This Wiki gives some additional hints of achieving SSO between ADAL and MSAL.

The specifics of SSO setup will depend on ADAL version that you're using.

ADAL 2.7.x

ADAL 2.7.x is able to read MSAL cache format. Therefore, you don't need to do anything special for cross-app SSO with that version.

However, MSAL and ADAL use different account identifiers. ADAL uses UPN as its primary account identifier and MSAL Home Account Identifier, which contains account's object ID and tenant ID.

When you get MSALAccount object in the result, it will contain both of those identifiers. username translates to userId in ADAL. Whereas, MSAL supports cache queries by both username and homeAccountIdentifier.

@interface MSALAccount : NSObject <NSCopying>

/*!
 The displayable value in UserPrincipleName(UPN) format. Can be nil if not returned from the service.
 This is the primary ADAL identifier for acquireTokenSilent calls.
 */
@property (readonly) NSString *username;

/*!
 Unique identifier of the account in the home directory.
 This is the primary MSAL identifier for acquireTokenSilent calls.
 */
@property (readonly) MSALAccountId *homeAccountId;

/*!
 Host part of the authority string used for authentication.
 */
@property (readonly) NSString *environment;

@end

In ADAL, you can call acquireTokenSilentWithResource:clientId:redirectUri:userId:completionBlock: API

If another app has previously signed into MSAL, you can save the username from MSALAccount object and pass it to your ADAL based app. ADAL will be able to find the account information silently.

ADAL 2.7.x will also return homeAccountId in the ADUserInformation object in the result. The app can save the identifier to use it in MSAL.

/*! Unique AAD account identifier across tenants based on user's home OID/home tenantId. */
@property (readonly) NSString *homeAccountId;

In MSAL, first lookup an account by username or homeAccountIdentifier:

/*!
 Returns account for for the given home identifier (received from an account object returned in a previous acquireToken call)

 @param  error      The error that occured trying to get the accounts, if any, if you're
                    not interested in the specific error pass in nil.
 */
- (MSALAccount *)accountForHomeAccountId:(NSString *)homeAccountId
                                   error:(NSError * __autoreleasing *)error;

/*!
 Returns account for for the given username (received from an account object returned in a previous acquireToken call or ADAL)

 @param  username    The displayable value in UserPrincipleName(UPN) format
 @param  error       The error that occured trying to get the accounts, if any, if you're
                     not interested in the specific error pass in nil.
 */
- (MSALAccount *)accountForUsername:(NSString *)username
                              error:(NSError * __autoreleasing *)error;

Then use the account in the acquireTokenSilent calls.

/*!
    Acquire a token silently for an existing account.
 
    @param  scopes          Permissions you want included in the access token received
                            in the result in the completionBlock. Not all scopes are
                            gauranteed to be included in the access token returned.
    @param  account         An account object retrieved from the application object that the
                            interactive authentication flow will be locked down to.
    @param  completionBlock The completion block that will be called when the authentication
                            flow completes, or encounters an error.
 */
- (void)acquireTokenSilentForScopes:(NSArray<NSString *> *)scopes
                            account:(MSALAccount *)account
                    completionBlock:(MSALCompletionBlock)completionBlock;

ADAL 2.x-2.6.6

Older ADAL versions didn't natively support MSAL cache format. However, MSAL is still able to read older ADAL cache format to ensure smooth migration from ADAL to MSAL without asking for user credentials again.

However, since homeAccountId wasn't available in older ADAL, you should lookup account by username instead.

/*!
 Returns account for for the given username (received from an account object returned in a previous acquireToken call or ADAL)

 @param  username    The displayable value in UserPrincipleName(UPN) format
 @param  error       The error that occured trying to get the accounts, if any, if you're
                     not interested in the specific error pass in nil.
 */
- (MSALAccount *)accountForUsername:(NSString *)username
                              error:(NSError * __autoreleasing *)error;

Alternatively, you can just read all accounts, which will also read account information from ADAL:

/*!
 Returns an array of all accounts visible to this application.

 @param  error      The error that occured trying to retrieve accounts, if any, if you're
                    not interested in the specific error pass in nil.
 */

- (NSArray <MSALAccount *> *)allAccounts:(NSError * __autoreleasing *)error;

Getting started with MSAL SDK

Configure, Build, Test, Deploy

Advanced Topics

Getting Help, Common Issues, and FAQ

Migrating

News

Clone this wiki locally