Skip to content

Commit 36ff749

Browse files
authored
Merge pull request #1496 from AzureAD/sedemche/duna_resume_cherry_pick
Cherry pick DUNA "resume" action fix
2 parents bb1d57b + e2d237e commit 36ff749

12 files changed

+146
-16
lines changed

IdentityCore/IdentityCore.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,8 @@
484484
23D2049421D1C274009B5975 /* MSIDTokenResponseSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 23D2049221D1C274009B5975 /* MSIDTokenResponseSerializer.m */; };
485485
23D2049521D1C274009B5975 /* MSIDTokenResponseSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 23D2049221D1C274009B5975 /* MSIDTokenResponseSerializer.m */; };
486486
23D204A521D5A745009B5975 /* MSIDDefaultTokenResponseValidatorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 23D204A421D5A745009B5975 /* MSIDDefaultTokenResponseValidatorTests.m */; };
487+
23D4DEE72D92537D005A77E4 /* MSIDFlightManagerMockProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 23D4DEE52D92537D005A77E4 /* MSIDFlightManagerMockProvider.m */; };
488+
23D4DEE82D92537D005A77E4 /* MSIDFlightManagerMockProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 23D4DEE52D92537D005A77E4 /* MSIDFlightManagerMockProvider.m */; };
487489
23D744782097B2DA00210C51 /* MSIDAADV1AuthorizationCodeRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 23D744762097B2DA00210C51 /* MSIDAADV1AuthorizationCodeRequest.h */; };
488490
23D744792097B2DA00210C51 /* MSIDAADV1AuthorizationCodeRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 23D744772097B2DA00210C51 /* MSIDAADV1AuthorizationCodeRequest.m */; };
489491
23D7447A2097B2DA00210C51 /* MSIDAADV1AuthorizationCodeRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 23D744772097B2DA00210C51 /* MSIDAADV1AuthorizationCodeRequest.m */; };
@@ -2363,6 +2365,8 @@
23632365
23D2049121D1C274009B5975 /* MSIDTokenResponseSerializer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSIDTokenResponseSerializer.h; sourceTree = "<group>"; };
23642366
23D2049221D1C274009B5975 /* MSIDTokenResponseSerializer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDTokenResponseSerializer.m; sourceTree = "<group>"; };
23652367
23D204A421D5A745009B5975 /* MSIDDefaultTokenResponseValidatorTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDDefaultTokenResponseValidatorTests.m; sourceTree = "<group>"; };
2368+
23D4DEE42D92537D005A77E4 /* MSIDFlightManagerMockProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSIDFlightManagerMockProvider.h; sourceTree = "<group>"; };
2369+
23D4DEE52D92537D005A77E4 /* MSIDFlightManagerMockProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDFlightManagerMockProvider.m; sourceTree = "<group>"; };
23662370
23D744762097B2DA00210C51 /* MSIDAADV1AuthorizationCodeRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSIDAADV1AuthorizationCodeRequest.h; sourceTree = "<group>"; };
23672371
23D744772097B2DA00210C51 /* MSIDAADV1AuthorizationCodeRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSIDAADV1AuthorizationCodeRequest.m; sourceTree = "<group>"; };
23682372
23DADC0E20B8BF4F005D7389 /* MSIDAadAuthorityCacheRecord.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSIDAadAuthorityCacheRecord.h; sourceTree = "<group>"; };
@@ -3728,6 +3732,8 @@
37283732
B431B5352AF1C3BD0020CD3D /* MSIDSSOExtensionPasskeyCredentialRequestMock.h */,
37293733
B431B5362AF1C3C60020CD3D /* MSIDSSOExtensionPasskeyCredentialRequestMock.m */,
37303734
2A0278A22D6E3787005655B4 /* MSIDLastRequestTelemetry+Tests.h */,
3735+
23D4DEE42D92537D005A77E4 /* MSIDFlightManagerMockProvider.h */,
3736+
23D4DEE52D92537D005A77E4 /* MSIDFlightManagerMockProvider.m */,
37313737
);
37323738
path = mocks;
37333739
sourceTree = "<group>";
@@ -7630,6 +7636,7 @@
76307636
B2E4A07324DDE575007CE642 /* MSIDTestTelemetryEventsObserver.m in Sources */,
76317637
B217862A23A5839300839CE8 /* MSIDSSOExtensionSignoutRequestMock.m in Sources */,
76327638
D6D9A4571FBD40BF00EFA430 /* NSURL+MSIDTestUtil.m in Sources */,
7639+
23D4DEE82D92537D005A77E4 /* MSIDFlightManagerMockProvider.m in Sources */,
76337640
589842B9252544940075DFED /* MSIDAccountMetadataCacheMockUpdateAuthorityParameters.m in Sources */,
76347641
D626FFF11FBD200A00EE4487 /* MSIDTestURLResponse.m in Sources */,
76357642
963E68E721489A9500D7D0CC /* NSString+MSIDTestUtil.m in Sources */,
@@ -7691,6 +7698,7 @@
76917698
96290E5721489BB800FDD5C8 /* NSString+MSIDTestUtil.m in Sources */,
76927699
607A788E23294D6F00A1F74D /* MSIDAccountMetadataCacheAccessorMock.m in Sources */,
76937700
58D1514424A6888D001DD18A /* MSIDHttpRequest+OverrideCacheSave.m in Sources */,
7701+
23D4DEE72D92537D005A77E4 /* MSIDFlightManagerMockProvider.m in Sources */,
76947702
D6D9A44E1FBD3EEA00EFA430 /* NSDictionary+MSIDTestUtil.m in Sources */,
76957703
589842C6252544940075DFED /* MSIDAccountMetadataCacheMockUpdateAuthorityParameters.m in Sources */,
76967704
23FB5C39225588CF002BF1EB /* MSIDClaimsRequestMock.m in Sources */,

IdentityCore/src/MSIDConstants.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777
NSString *const MSID_BROWSER_RESPONSE_SWITCH_BROWSER_RESUME = @"switch_browser_resume";
7878

7979
NSString *const MSID_FLIGHT_USE_V2_WEB_RESPONSE_FACTORY = @"use_v2_web_response_factory";
80-
NSString *const MSID_FLIGHT_SUPPORT_DUNA_CBA = @"support_duna_cba";
80+
NSString *const MSID_FLIGHT_SUPPORT_DUNA_CBA = @"support_duna_cba_v2";
8181

8282

8383
#define METHODANDLINE [NSString stringWithFormat:@"%s [Line %d]", __PRETTY_FUNCTION__, __LINE__]

IdentityCore/src/MSIDFlightManager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
3535

3636
@interface MSIDFlightManager : NSObject <MSIDFlightManagerInterface>
3737

38-
@property (nonatomic) id<MSIDFlightManagerInterface> flightProvider;
38+
@property (nonatomic, nullable) id<MSIDFlightManagerInterface> flightProvider;
3939

4040
+ (instancetype)sharedInstance;
4141

IdentityCore/src/webview/operations/ios/MSIDSwitchBrowserOperation.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ - (void)invokeWithRequestParameters:(nonnull MSIDInteractiveTokenRequestParamete
102102

103103
NSError *localError;
104104
__auto_type response = [webRequestConfiguration responseWithResultURL:callbackURL factory:oauthFactory.webviewFactory context:requestParameters error:&localError];
105+
response.parentResponse = self.switchBrowserResponse;
105106

106107
if (localError)
107108
{

IdentityCore/src/webview/operations/ios/MSIDSwitchBrowserResumeOperation.m

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,19 @@ - (nullable instancetype)initWithResponse:(MSIDWebviewResponse *)response
6262
}
6363

6464
_switchBrowserResumeResponse = (MSIDSwitchBrowserResumeResponse *)response;
65+
66+
__auto_type parentResponse = _switchBrowserResumeResponse.parentResponse;
67+
if (![parentResponse isKindOfClass:MSIDSwitchBrowserResponse.class])
68+
{
69+
NSString *errorMsg = [NSString stringWithFormat:@"Parent response of type %@ is required for creating %@", MSIDSwitchBrowserResponse.class, self.class];
70+
MSID_LOG_WITH_CTX(MSIDLogLevelError, nil, @"%@", errorMsg);
71+
if (error)
72+
{
73+
*error = MSIDCreateError(MSIDErrorDomain, MSIDErrorInternal, errorMsg, nil, nil, nil, nil, nil, NO);
74+
}
75+
76+
return nil;
77+
}
6578
}
6679

6780
return self;

IdentityCore/src/webview/response/MSIDSwitchBrowserResponse.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,6 @@
4242
context:(id<MSIDRequestContext>)context
4343
error:(NSError *__autoreleasing*)error;
4444

45+
+ (BOOL)isDUNAActionUrl:(NSURL *)url operation:(NSString *)operation;
46+
4547
@end

IdentityCore/src/webview/response/MSIDSwitchBrowserResponse.m

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,24 @@ - (BOOL)useV2WebResponseHandling
7474
return useV2WebResponseHandling;
7575
}
7676

77+
+ (BOOL)isDUNAActionUrl:(NSURL *)url operation:(NSString *)operation
78+
{
79+
if (url == nil) return NO;
80+
81+
NSArray *pathComponents = url.pathComponents;
82+
if ([pathComponents count] < 2)
83+
{
84+
return NO;
85+
}
86+
87+
if ([pathComponents[1] isEqualToString:operation])
88+
{
89+
return YES;
90+
}
91+
92+
return NO;
93+
}
94+
7795
#pragma mark - Private
7896

7997
- (BOOL)isMyUrl:(NSURL *)url
@@ -102,18 +120,7 @@ - (BOOL)isMyUrl:(NSURL *)url
102120
return NO;
103121
}
104122

105-
NSArray *pathComponents = url.pathComponents;
106-
if ([pathComponents count] < 2)
107-
{
108-
return NO;
109-
}
110-
111-
if ([pathComponents[1] isEqualToString:[self.class operation]])
112-
{
113-
return YES;
114-
}
115-
116-
return NO;
123+
return [self.class isDUNAActionUrl:url operation:[self.class operation]];
117124
}
118125

119126

IdentityCore/src/webview/response/MSIDWebviewResponse.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
@property (atomic, readonly) NSURL *url;
3636
@property (nonatomic, class, readonly) NSString *operation;
3737

38+
/// Enables tracking of web response chains.
39+
/// For example, it is used in DUNA CBA flow to check that "swich_browser_resume" response
40+
/// was created as a result of "switch_browser" response.
41+
@property (nonatomic) MSIDWebviewResponse *parentResponse;
42+
3843
- (instancetype)initWithURL:(NSURL *)url
3944
context:(id<MSIDRequestContext>)context
4045
error:(NSError *__autoreleasing*)error;

IdentityCore/tests/MSIDSwitchBrowserResumeOperationTest.swift

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,15 @@ import XCTest
2828
final class MSIDSwitchBrowserResumeOperationTest: XCTestCase
2929
{
3030
lazy var validSwitchBrowserResumeResponse: MSIDSwitchBrowserResumeResponse? = {
31-
let url = URL(string: "msauth.com.microsoft.msaltestapp://auth/switch_browser_resume?action_uri=some_uri&code=some_code")!
32-
return try? MSIDSwitchBrowserResumeResponse(url: url, redirectUri: "msauth.com.microsoft.msaltestapp://auth", context: nil)
31+
32+
let switchUrl = URL(string: "msauth.com.microsoft.msaltestapp://auth/switch_browser?action_uri=some_uri&code=some_code")!
33+
let switchBrowserResponse = try? MSIDSwitchBrowserResponse(url: switchUrl, redirectUri: "msauth.com.microsoft.msaltestapp://auth", context: nil)
34+
35+
let resumeUrl = URL(string: "msauth.com.microsoft.msaltestapp://auth/switch_browser_resume?action_uri=some_uri&code=some_code")!
36+
let resumeResponse = try? MSIDSwitchBrowserResumeResponse(url: resumeUrl, redirectUri: "msauth.com.microsoft.msaltestapp://auth", context: nil)
37+
resumeResponse?.parent = switchBrowserResponse
38+
39+
return resumeResponse
3340
}()
3441

3542
override func setUpWithError() throws
@@ -51,6 +58,19 @@ final class MSIDSwitchBrowserResumeOperationTest: XCTestCase
5158

5259
XCTAssertNotNil(operation)
5360
}
61+
62+
func testInit_whenNoParentResponse_shouldReturnNil() throws
63+
{
64+
XCTAssertNotNil(self.validSwitchBrowserResumeResponse)
65+
guard let response = self.validSwitchBrowserResumeResponse else { return }
66+
response.parent = nil
67+
68+
XCTAssertThrowsError(try MSIDSwitchBrowserResumeOperation(response: response)) { error in
69+
XCTAssertEqual((error as NSError).code, MSIDErrorCode.internal.rawValue)
70+
XCTAssertEqual((error as NSError).domain, MSIDErrorDomain)
71+
XCTAssertEqual((error as NSError).userInfo["MSIDErrorDescriptionKey"] as? String, "Parent response of type MSIDSwitchBrowserResponse is required for creating MSIDSwitchBrowserResumeOperation")
72+
}
73+
}
5474

5575
func testInit_withInValidResponse_shouldReturnNil() throws
5676
{
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//
2+
// Copyright (c) Microsoft Corporation.
3+
// All rights reserved.
4+
//
5+
// This code is licensed under the MIT License.
6+
//
7+
// Permission is hereby granted, free of charge, to any person obtaining a copy
8+
// of this software and associated documentation files(the "Software"), to deal
9+
// in the Software without restriction, including without limitation the rights
10+
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
11+
// copies of the Software, and to permit persons to whom the Software is
12+
// furnished to do so, subject to the following conditions :
13+
//
14+
// The above copyright notice and this permission notice shall be included in
15+
// all copies or substantial portions of the Software.
16+
//
17+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
// THE SOFTWARE.
24+
25+
26+
#import "MSIDFlightManager.h"
27+
28+
NS_ASSUME_NONNULL_BEGIN
29+
30+
@interface MSIDFlightManagerMockProvider : NSObject <MSIDFlightManagerInterface>
31+
32+
@property (nonatomic) NSDictionary *boolForKeyContainer;
33+
34+
@end
35+
36+
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)