diff --git a/ADAL.podspec b/ADAL.podspec
index 52efc1a0d..4e4fc6306 100644
--- a/ADAL.podspec
+++ b/ADAL.podspec
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "ADAL"
s.module_name = "ADAL"
- s.version = "4.0.5"
+ s.version = "4.0.6"
s.summary = "The ADAL SDK for iOS gives you the ability to add Azure Identity authentication to your application"
s.description = <<-DESC
diff --git a/ADAL/resources/ios/Framework/Info.plist b/ADAL/resources/ios/Framework/Info.plist
index 5d7e8c41e..6271f566e 100644
--- a/ADAL/resources/ios/Framework/Info.plist
+++ b/ADAL/resources/ios/Framework/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 4.0.5
+ 4.0.6
CFBundleSignature
????
CFBundleVersion
diff --git a/ADAL/resources/mac/Info.plist b/ADAL/resources/mac/Info.plist
index 72975e4ae..1230c6e2c 100644
--- a/ADAL/resources/mac/Info.plist
+++ b/ADAL/resources/mac/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 4.0.5
+ 4.0.6
CFBundleSignature
????
CFBundleVersion
diff --git a/ADAL/src/ADAL_Internal.h b/ADAL/src/ADAL_Internal.h
index 4a4467728..d05217e40 100644
--- a/ADAL/src/ADAL_Internal.h
+++ b/ADAL/src/ADAL_Internal.h
@@ -28,7 +28,7 @@
#define ADAL_VER_HIGH 4
#define ADAL_VER_LOW 0
-#define ADAL_VER_PATCH 5
+#define ADAL_VER_PATCH 6
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
diff --git a/ADAL/src/ADAuthenticationContext.m b/ADAL/src/ADAuthenticationContext.m
index ce000d297..2dbc3b515 100755
--- a/ADAL/src/ADAuthenticationContext.m
+++ b/ADAL/src/ADAuthenticationContext.m
@@ -513,6 +513,33 @@ - (void)acquireTokenWithRefreshToken:(NSString *)refreshToken
[request acquireToken:@"137" completionBlock:completionBlock];
}
+- (void)acquireTokenInteractiveWithResource:(NSString *)resource
+ clientId:(NSString *)clientId
+ redirectUri:(NSURL *)redirectUri
+ promptBehavior:(ADPromptBehavior)promptBehavior
+ userIdentifier:(ADUserIdentifier *)userId
+ extraQueryParameters:(NSString *)queryParams
+ claims:(NSString *)claims
+ completionBlock:(ADAuthenticationCallback)completionBlock
+{
+ API_ENTRY;
+ REQUEST_WITH_REDIRECT_URL(redirectUri, clientId, resource);
+
+ [request setPromptBehavior:promptBehavior];
+ [request setUserIdentifier:userId];
+ [request setExtraQueryParameters:queryParams];
+ [request setSkipCache:YES];
+
+ ADAuthenticationError *claimsError;
+ if (![request setClaims:claims error:&claimsError])
+ {
+ completionBlock([ADAuthenticationResult resultFromError:claimsError correlationId:_correlationId]);
+ return;
+ }
+
+ [request acquireToken:@"138" completionBlock:completionBlock];
+}
+
#pragma mark - Private
#if TARGET_OS_IPHONE
diff --git a/ADAL/src/cache/ADResponseCacheHandler.m b/ADAL/src/cache/ADResponseCacheHandler.m
index 585dc78ac..2d54b2ae5 100644
--- a/ADAL/src/cache/ADResponseCacheHandler.m
+++ b/ADAL/src/cache/ADResponseCacheHandler.m
@@ -88,7 +88,8 @@ + (ADAuthenticationResult *)handleError:(NSError *)msidError
cache:(MSIDLegacyTokenCacheAccessor *)cache
params:(ADRequestParameters *)requestParams
{
- if (response.oauthErrorCode == MSIDErrorServerInvalidGrant && refreshToken)
+ NSString *subError = [[msidError userInfo] objectForKey:MSIDOAuthSubErrorKey];
+ if (response.oauthErrorCode == MSIDErrorServerInvalidGrant && refreshToken && (subError == nil || [subError caseInsensitiveCompare:@"consent_required"] != NSOrderedSame))
{
NSError *removeError = nil;
diff --git a/ADAL/src/public/ADAuthenticationContext.h b/ADAL/src/public/ADAuthenticationContext.h
index b5e78eaba..faa08dccf 100644
--- a/ADAL/src/public/ADAuthenticationContext.h
+++ b/ADAL/src/public/ADAuthenticationContext.h
@@ -293,6 +293,9 @@ typedef enum
/*! Enable to return access token with extended lifetime during server outage. */
@property BOOL extendedLifetimeEnabled;
+/*! Enables sending refresh token to the webview when consenting to new scopes without re-entering password.
+ This also causes the auth provider to ignore SSO cookies in the webview and instead use the cached refresh token. */
+@property BOOL useRefreshTokenForWebview;
/*!
List of additional ESTS features that client handles.
*/
@@ -530,6 +533,26 @@ typedef enum
userId:(nonnull NSString *)userId
completionBlock:(nonnull ADAuthenticationCallback)completionBlock;
+/*! Follows the OAuth2 protocol (RFC 6749). The function accepts claims challenge returned from middle tier service, which will be sent to authorization endpoint. ADAL will ignore cache and will not attempt
+ to silently acquire token or return access token from cache. It will get the token through webview.
+ @param resource The resource for whom token is needed.
+ @param clientId The client identifier
+ @param redirectUri The redirect URI according to OAuth2 protocol
+ @param promptBehavior Controls if any credentials UI will be shown.
+ @param userId An ADUserIdentifier object describing the user being authenticated
+ @param queryParams The extra query parameters will be appended to the HTTP request to the authorization endpoint. This parameter can be nil. It should be URL-encoded.
+ @param claims The claims parameter that needs to be sent to authorization endpoint. It should be URL-encoded.
+ @param completionBlock the block to execute upon completion. You can use embedded block, e.g. "^(ADAuthenticationResult res){ }"
+ */
+- (void)acquireTokenInteractiveWithResource:(nonnull NSString *)resource
+ clientId:(nonnull NSString *)clientId
+ redirectUri:(nonnull NSURL *)redirectUri
+ promptBehavior:(ADPromptBehavior)promptBehavior
+ userIdentifier:(nullable ADUserIdentifier *)userId
+ extraQueryParameters:(nullable NSString *)queryParams
+ claims:(nullable NSString *)claims
+ completionBlock:(nonnull ADAuthenticationCallback)completionBlock;
+
@end
diff --git a/ADAL/src/request/ADAuthenticationRequest+WebRequest.m b/ADAL/src/request/ADAuthenticationRequest+WebRequest.m
index d5b1649f1..da8cd25e7 100755
--- a/ADAL/src/request/ADAuthenticationRequest+WebRequest.m
+++ b/ADAL/src/request/ADAuthenticationRequest+WebRequest.m
@@ -36,6 +36,8 @@
#import "NSString+ADURLExtensions.h"
#import "MSIDDeviceId.h"
#import "MSIDAADV1Oauth2Factory.h"
+#import "MSIDLegacyTokenCacheAccessor.h"
+#import "MSIDRefreshToken.h"
#import "ADAuthenticationErrorConverter.h"
#import "MSIDClientCapabilitiesUtil.h"
@@ -80,6 +82,45 @@ - (void)executeRequest:(NSDictionary *)request_data
}];
}
+- (NSString *)getRefreshTokenForRequest
+{
+ if (![NSString msidIsStringNilOrBlank:_refreshToken])
+ {
+ return _refreshToken;
+ }
+ else
+ {
+ NSError *refreshTokenError = nil;
+ MSIDRefreshToken *refreshTokenItem = [self.tokenCache getRefreshTokenWithAccount:_requestParams.account
+ familyId:nil
+ configuration:_requestParams.msidConfig
+ context:_requestParams
+ error:&refreshTokenError];
+
+ // FRT is more likely to be valid as it gets refreshed if any app in the family uses it, so try to use the FRT instead
+ if (!refreshTokenItem || ![NSString msidIsStringNilOrBlank:[refreshTokenItem familyId]])
+ {
+ NSError *msidFRTError = nil;
+ NSString *familyId = [NSString msidIsStringNilOrBlank:[refreshTokenItem familyId]] ? @"1" : [refreshTokenItem familyId];
+ MSIDRefreshToken *frtItem = [self.tokenCache getRefreshTokenWithAccount:_requestParams.account
+ familyId:familyId
+ configuration:_requestParams.msidConfig
+ context:_requestParams
+ error:&msidFRTError];
+ if (frtItem && !msidFRTError)
+ {
+ refreshTokenItem = frtItem;
+ refreshTokenError = nil;
+ }
+ }
+
+ MSID_LOG_VERBOSE(_requestParams, @"Retrieve refresh token from cache for web view: %@, error code: %ld", _PII_NULLIFY(refreshTokenItem), refreshTokenError.code);
+ return [refreshTokenItem refreshToken];
+ }
+
+ return nil;
+}
+
//Requests an OAuth2 code to be used for obtaining a token:
- (void)requestCode:(MSIDAuthorizationCodeCallback)completionBlock
{
@@ -89,7 +130,13 @@ - (void)requestCode:(MSIDAuthorizationCodeCallback)completionBlock
MSID_LOG_VERBOSE(_requestParams, @"Requesting authorization code");
MSID_LOG_VERBOSE_PII(_requestParams, @"Requesting authorization code for resource: %@", _requestParams.resource);
- [ADWebAuthController startWithRequest:_requestParams promptBehavior:_promptBehavior context:_context completion:^(MSIDWebviewResponse *response, NSError *error) {
+ NSString *refreshToken = nil;
+ if (_promptBehavior == AD_PROMPT_AUTO && [_context useRefreshTokenForWebview])
+ {
+ refreshToken = [self getRefreshTokenForRequest];
+ }
+
+ [ADWebAuthController startWithRequest:_requestParams promptBehavior:_promptBehavior refreshToken:refreshToken context:_context completion:^(MSIDWebviewResponse *response, NSError *error) {
if (error)
{
diff --git a/ADAL/src/ui/ADWebAuthController+Internal.h b/ADAL/src/ui/ADWebAuthController+Internal.h
index db7bffbf2..1d17530c6 100644
--- a/ADAL/src/ui/ADWebAuthController+Internal.h
+++ b/ADAL/src/ui/ADWebAuthController+Internal.h
@@ -35,6 +35,7 @@
// the authentication process.
+ (void)startWithRequest:(ADRequestParameters *)requestParams
promptBehavior:(ADPromptBehavior)promptBehavior
+ refreshToken:(NSString*)refreshToken
context:(ADAuthenticationContext *)context
completion:(MSIDWebviewAuthCompletionHandler)completionHandler;
diff --git a/ADAL/src/ui/ADWebAuthController.m b/ADAL/src/ui/ADWebAuthController.m
index 37c3288c8..d1aae563e 100755
--- a/ADAL/src/ui/ADWebAuthController.m
+++ b/ADAL/src/ui/ADWebAuthController.m
@@ -54,6 +54,10 @@
NSString* ADWebAuthWillSwitchToBrokerApp = @"ADWebAuthWillSwitchToBrokerApp";
+NSString* ADWebAuthIgnoreSSOHeader = @"x-ms-sso-Ignore-SSO";
+
+NSString* ADWebAuthRefreshTokenHeader = @"x-ms-sso-RefreshToken";
+
// Private interface declaration
@interface ADWebAuthController ()
@end
@@ -94,6 +98,7 @@ + (void)registerWebAuthNotifications
+ (void)startWithRequest:(ADRequestParameters *)requestParams
promptBehavior:(ADPromptBehavior)promptBehavior
+ refreshToken:(NSString*)refreshToken
context:(ADAuthenticationContext *)context
completion:(MSIDWebviewAuthCompletionHandler)completionHandler
{
@@ -139,6 +144,15 @@ + (void)startWithRequest:(ADRequestParameters *)requestParams
webviewConfig.presentationType = ADAuthenticationSettings.sharedInstance.webviewPresentationStyle;
#endif
+ if ([context useRefreshTokenForWebview])
+ {
+ [[webviewConfig customHeaders] setObject:@"1" forKey:ADWebAuthIgnoreSSOHeader];
+ if (![NSString msidIsStringNilOrBlank:refreshToken])
+ {
+ [[webviewConfig customHeaders] setObject:refreshToken forKey:ADWebAuthRefreshTokenHeader];
+ }
+ }
+
[MSIDWebviewAuthorization startEmbeddedWebviewAuthWithConfiguration:webviewConfig
oauth2Factory:context.oauthFactory
webview:context.webView
diff --git a/ADAL/tests/app/resources/ios/Info.plist b/ADAL/tests/app/resources/ios/Info.plist
index 40dcfbe19..c193ecfe2 100644
--- a/ADAL/tests/app/resources/ios/Info.plist
+++ b/ADAL/tests/app/resources/ios/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 4.0.5
+ 4.0.6
CFBundleSignature
????
CFBundleURLTypes
diff --git a/ADAL/tests/util/ADTestWebAuthController.m b/ADAL/tests/util/ADTestWebAuthController.m
index 03083bc15..6ee535d3b 100644
--- a/ADAL/tests/util/ADTestWebAuthController.m
+++ b/ADAL/tests/util/ADTestWebAuthController.m
@@ -30,6 +30,7 @@ @implementation ADWebAuthController (TestWebviewOverride)
+ (void)startWithRequest:(ADRequestParameters *)requestParams
promptBehavior:(ADPromptBehavior)promptBehavior
+ refreshToken:(NSString*)refreshToken
context:(ADAuthenticationContext *)context
completion:(MSIDWebviewAuthCompletionHandler)completionHandler
{
diff --git a/README.md b/README.md
index c526825bb..f32dcbc21 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,23 @@
+---
+This library, ADAL for iOS and macOS, will no longer receive new feature improvements. Instead, use the new library
+[MSAL for iOS and macOS](https://github.com/AzureAD/microsoft-authentication-library-for-objc).
+
+* If you are starting a new project, you can get started with the
+ [MSAL for iOS and macOS docs](https://github.com/AzureAD/microsoft-authentication-library-for-objc/wiki)
+ for details about the scenarios, usage, and relevant concepts.
+* If your application is using the previous ADAL for iOS and macOS library, you can follow this
+ [migration guide](https://docs.microsoft.com/azure/active-directory/develop/migrate-objc-adal-msal)
+ to update to MSAL for iOS and macOS.
+* Existing applications relying on ADAL for iOS and macOS will continue to work.
+
+---
# Microsoft Azure Active Directory Authentication Library (ADAL) for iOS and macOS
=====================================
| [Code Samples](https://github.com/azure-samples?utf8=✓&q=active-directory-ios) | [Reference Docs](http://cocoadocs.org/docsets/ADAL/) | [Developer Guide](https://aka.ms/aaddev)
| --- | --- | --- |
-## Note
-
-In the near future, ADAL will be deprecated in favor of MSAL. At the current point, we are only adding new features to MSAL library, and only providing security fixes for ADAL.
-
-- If you're building a new app, we strongly recommend to adopt MSAL directly.
-- If you have an existing app, please plan to migrate to MSAL shortly.
-
-Please open an issue and/or feature request in MSAL, if there's anything that would block you from migrating to MSAL.
-MSAL library repository: [https://github.com/AzureAD/microsoft-authentication-library-for-objc](https://github.com/AzureAD/microsoft-authentication-library-for-objc)
-
## Release Versions
We recommend remaining up-to-date with the latest version of ADAL. The best place to check what the most recent version is is the [releases page](https://github.com/AzureAD/azure-activedirectory-library-for-objc/releases) on GitHub, you can also subscribe the the [Atom Feed](https://github.com/AzureAD/azure-activedirectory-library-for-objc/releases.atom) from GitHub, or use a 3rd party tool like [Sibbell](https://sibbell.com/about/) to receive emails when a new version is released.
diff --git a/changelog.txt b/changelog.txt
index 1e1f33739..2510c30b4 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,8 @@
+Version 4.0.6 (02.21.2020)
+------
+* Support passing refresh token in the header to avoid extra prompts (#1495)
+* Added ADAL migration info to readme (#1518)
+
Version 4.0.5 (01.20.2020)
------
* Verify broker schemes are correctly registered (#1497)