Skip to content

Commit 866dad9

Browse files
OKTA-748810 - Crash/Non-fatal - <CF_IS_OBJC Firebase> (#363)
1 parent 03439c9 commit 866dad9

File tree

6 files changed

+170
-16
lines changed

6 files changed

+170
-16
lines changed

.github/workflows/okta-oidc.yml

+7-7
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,27 @@ on:
88

99
jobs:
1010
UnitTests:
11-
runs-on: macos-11
11+
runs-on: macos-latest
1212
env:
13-
DEVELOPER_DIR: /Applications/Xcode_13.1.app/Contents/Developer
13+
DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer
1414
steps:
1515
- uses: actions/checkout@v2
1616
- name: iOS
17-
run: set -o pipefail && xcodebuild -project okta-oidc.xcodeproj -scheme "okta-oidc-ios" -destination "platform=iOS Simulator,OS=latest,name=iPhone 11" clean test | xcpretty
17+
run: set -o pipefail && xcodebuild -project okta-oidc.xcodeproj -scheme "okta-oidc-ios" -destination "platform=iOS Simulator,OS=latest,name=iPhone 15" clean test | xcpretty
1818
- name: macOS
1919
run: set -o pipefail && xcodebuild -project okta-oidc.xcodeproj -scheme "okta-oidc-mac" -destination "platform=macOS" clean test | xcpretty
2020
- name: Swift
2121
run: swift test -v
2222
UITests:
23-
runs-on: macos-11
23+
runs-on: macos-latest
2424
steps:
2525
- uses: actions/checkout@v2
2626
- name: iOS
27-
run: set -o pipefail && xcodebuild -project okta-oidc.xcodeproj -scheme "okta-oidc" -destination "platform=iOS Simulator,OS=latest,name=iPhone 11" clean test | xcpretty
27+
run: set -o pipefail && xcodebuild -project okta-oidc.xcodeproj -scheme "okta-oidc" -destination "platform=iOS Simulator,OS=latest,name=iPhone 15" clean test | xcpretty
2828
PackageValidation:
29-
runs-on: macos-11
29+
runs-on: macos-latest
3030
env:
31-
DEVELOPER_DIR: /Applications/Xcode_13.1.app/Contents/Developer
31+
DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer
3232
steps:
3333
- uses: actions/checkout@v2
3434
- name: Cocoapods

OktaOidc.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'OktaOidc'
3-
s.version = '3.11.5'
3+
s.version = '3.11.6'
44
s.summary = 'SDK to easily integrate AppAuth with Okta'
55
s.description = <<-DESC
66
Integrate your native app with Okta using the AppAuth library.

Sources/AppAuth/OktaUserAgent.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ +(void)setUserAgentValue:(NSString*)value {
2222
}
2323

2424
+(NSString*)userAgentVersion {
25-
return @"3.11.5";
25+
return @"3.11.6";
2626
}
2727

2828
+(NSString*)userAgentHeaderKey {

Sources/AppAuth/macOS/OKTRedirectHTTPHandler.m

+21-3
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,28 @@ - (void)stopHTTPListener {
127127
_httpServ = nil;
128128
}
129129

130+
- (BOOL)isOptionsHTTPServerRequest:(HTTPServerRequest *)request {
131+
CFStringRef method = CFHTTPMessageCopyRequestMethod(request.request);
132+
if (method == nil) {
133+
return NO;
134+
}
135+
136+
BOOL isOptionsRequest = CFStringCompare(method, (__bridge CFStringRef)@"OPTIONS", kCFCompareCaseInsensitive) == kCFCompareEqualTo;
137+
CFRelease(method);
138+
139+
return isOptionsRequest;
140+
}
141+
130142
- (void)HTTPConnection:(HTTPConnection *)conn didReceiveRequest:(HTTPServerRequest *)mess {
131143
// Handle private network preflight
132144
// https://developer.chrome.com/blog/private-network-access-preflight/
133-
CFStringRef method = CFHTTPMessageCopyRequestMethod(mess.request);
134-
BOOL isOptionsRequest = CFStringCompare(method, (__bridge CFStringRef)@"OPTIONS", 0) == kCFCompareEqualTo;
145+
BOOL isOptionsRequest = [self isOptionsHTTPServerRequest:mess];
135146

136147
CFStringRef requestPrivateNetwork = isOptionsRequest ? CFHTTPMessageCopyHeaderFieldValue(mess.request, (__bridge CFStringRef)@"Access-Control-Request-Private-Network") : nil;
137148
BOOL doesRequestPrivateNetwork = requestPrivateNetwork != nil && CFStringCompare(requestPrivateNetwork, (__bridge CFStringRef)@"true", 0) == kCFCompareEqualTo;
149+
if (requestPrivateNetwork != nil) {
150+
CFRelease(requestPrivateNetwork);
151+
}
138152
if (isOptionsRequest && doesRequestPrivateNetwork) {
139153
CFHTTPMessageRef response = CFHTTPMessageCreateResponse(
140154
kCFAllocatorDefault,
@@ -159,9 +173,13 @@ - (void)HTTPConnection:(HTTPConnection *)conn didReceiveRequest:(HTTPServerReque
159173
return;
160174
}
161175

176+
BOOL handled = NO;
162177
// Sends URL to AppAuth.
163178
CFURLRef url = CFHTTPMessageCopyRequestURL(mess.request);
164-
BOOL handled = [_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:(__bridge NSURL *)url];
179+
if (url != nil) {
180+
handled = [_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:(__bridge NSURL *)url];
181+
CFRelease(url);
182+
}
165183

166184
// Stops listening to further requests after the first valid authorization response.
167185
if (handled) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* Copyright (c) 2024-Present, Okta, Inc. and/or its affiliates. All rights reserved.
3+
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
4+
*
5+
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
6+
* Unless required by applicable law or agreed to in writing, software
7+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
8+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
*
10+
* See the License for the specific language governing permissions and limitations under the License.
11+
*/
12+
13+
#import <XCTest/XCTest.h>
14+
#import "OKTRedirectHTTPHandler.h"
15+
#import "OKTLoopbackHTTPServer.h"
16+
17+
@interface OKTRedirectHTTPHandlerTests<OKTExternalUserAgentSession> : XCTestCase
18+
19+
@property BOOL resumeExternalUserAgentFlowWithURLCalled;
20+
21+
- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)URL;
22+
23+
@end
24+
25+
@interface OKTRedirectHTTPHandler(Private)
26+
27+
- (BOOL)isOptionsHTTPServerRequest:(HTTPServerRequest *)request;
28+
- (void)HTTPConnection:(HTTPConnection *)conn didReceiveRequest:(HTTPServerRequest *)mess;
29+
30+
@end
31+
32+
@implementation OKTRedirectHTTPHandlerTests
33+
34+
- (void)testIsOptionsHTTPServerRequest {
35+
OKTRedirectHTTPHandler *handler = [OKTRedirectHTTPHandler new];
36+
CFStringRef url = CFSTR("http://www.okta.com");
37+
CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL);
38+
39+
CFStringRef requestMethod = CFSTR("GET");
40+
CFHTTPMessageRef myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
41+
HTTPConnection *connection = [[HTTPConnection alloc] initWithPeerAddress:nil inputStream:nil outputStream:nil forServer:nil];
42+
HTTPServerRequest *request = [[HTTPServerRequest alloc] initWithRequest:myRequest connection:connection];
43+
BOOL isOptionsRequest = [handler isOptionsHTTPServerRequest: request];
44+
XCTAssertFalse(isOptionsRequest);
45+
46+
requestMethod = CFSTR("OPTIONS");
47+
myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
48+
request = [[HTTPServerRequest alloc] initWithRequest:myRequest connection:connection];
49+
isOptionsRequest = [handler isOptionsHTTPServerRequest: request];
50+
XCTAssertTrue(isOptionsRequest);
51+
52+
requestMethod = CFSTR("options");
53+
myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
54+
request = [[HTTPServerRequest alloc] initWithRequest:myRequest connection:connection];
55+
isOptionsRequest = [handler isOptionsHTTPServerRequest: request];
56+
XCTAssertTrue(isOptionsRequest);
57+
58+
isOptionsRequest = [handler isOptionsHTTPServerRequest: nil];
59+
XCTAssertFalse(isOptionsRequest);
60+
}
61+
62+
- (void)testDidReceiveRequestDelegate_NoOptionsHeader {
63+
OKTRedirectHTTPHandler *handler = [OKTRedirectHTTPHandler new];
64+
handler.currentAuthorizationFlow = (id<OKTExternalUserAgentSession>)self;
65+
CFStringRef url = CFSTR("http://www.okta.com");
66+
CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL);
67+
CFStringRef requestMethod = CFSTR("GET");
68+
CFHTTPMessageRef myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
69+
HTTPConnection *connection = [[HTTPConnection alloc] initWithPeerAddress:nil inputStream:nil outputStream:nil forServer:nil];
70+
HTTPServerRequest *request = [[HTTPServerRequest alloc] initWithRequest:myRequest connection:connection];
71+
72+
self.resumeExternalUserAgentFlowWithURLCalled = NO;
73+
[handler HTTPConnection:connection didReceiveRequest:request];
74+
XCTAssertTrue(self.resumeExternalUserAgentFlowWithURLCalled);
75+
76+
myURL = nil;
77+
requestMethod = CFSTR("GET");
78+
myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
79+
request = [[HTTPServerRequest alloc] initWithRequest:myRequest connection:connection];
80+
self.resumeExternalUserAgentFlowWithURLCalled = NO;
81+
[handler HTTPConnection:connection didReceiveRequest:request];
82+
XCTAssertFalse(self.resumeExternalUserAgentFlowWithURLCalled);
83+
}
84+
85+
- (void)testDidReceiveRequestDelegate_WithOptionsHeader {
86+
OKTRedirectHTTPHandler *handler = [OKTRedirectHTTPHandler new];
87+
handler.currentAuthorizationFlow = (id<OKTExternalUserAgentSession>)self;
88+
CFStringRef url = CFSTR("http://www.okta.com");
89+
CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL);
90+
CFStringRef requestMethod = CFSTR("OPTIONS");
91+
CFHTTPMessageRef myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
92+
HTTPConnection *connection = [[HTTPConnection alloc] initWithPeerAddress:nil inputStream:nil outputStream:nil forServer:nil];
93+
HTTPServerRequest *request = [[HTTPServerRequest alloc] initWithRequest:myRequest connection:connection];
94+
CFStringRef privateNetworkHeader = CFSTR("Access-Control-Request-Private-Network");
95+
CFStringRef privateNetworkValue = CFSTR("true");
96+
CFHTTPMessageSetHeaderFieldValue(myRequest, privateNetworkHeader, privateNetworkValue);
97+
CFStringRef originHeader = CFSTR("Origin");
98+
CFStringRef originValue = CFSTR("http://www.okta.com");
99+
CFHTTPMessageSetHeaderFieldValue(myRequest, originHeader, originValue);
100+
101+
self.resumeExternalUserAgentFlowWithURLCalled = NO;
102+
[handler HTTPConnection:connection didReceiveRequest:request];
103+
XCTAssertFalse(self.resumeExternalUserAgentFlowWithURLCalled);
104+
105+
CFHTTPMessageRef response = request.response;
106+
107+
originHeader = CFHTTPMessageCopyHeaderFieldValue(response, (__bridge CFStringRef)@"Access-Control-Allow-Origin");
108+
BOOL originHeaderExists = CFStringCompare(originHeader, originValue, kCFCompareCaseInsensitive) == kCFCompareEqualTo;
109+
XCTAssertTrue(originHeaderExists);
110+
111+
CFStringRef allowCredentialsHeader = CFHTTPMessageCopyHeaderFieldValue(response, (__bridge CFStringRef)@"Access-Control-Allow-Credentials");
112+
BOOL allowCredentialsHeaderExists = CFStringCompare(allowCredentialsHeader, (__bridge CFStringRef)@"true", kCFCompareCaseInsensitive) == kCFCompareEqualTo;
113+
XCTAssertTrue(allowCredentialsHeaderExists);
114+
115+
CFStringRef allowPrivateNetworkHeader = CFHTTPMessageCopyHeaderFieldValue(response, (__bridge CFStringRef)@"Access-Control-Allow-Private-Network");
116+
BOOL allowPrivateNetworkHeaderExists = CFStringCompare(allowPrivateNetworkHeader, (__bridge CFStringRef)@"true", kCFCompareCaseInsensitive) == kCFCompareEqualTo;
117+
XCTAssertTrue(allowPrivateNetworkHeaderExists);
118+
119+
CFStringRef contentLengthHeader = CFHTTPMessageCopyHeaderFieldValue(response, (__bridge CFStringRef)@"Content-Length");
120+
BOOL contentLengthHeaderExists = CFStringCompare(contentLengthHeader, (__bridge CFStringRef)@"0", kCFCompareCaseInsensitive) == kCFCompareEqualTo;
121+
XCTAssertTrue(contentLengthHeaderExists);
122+
}
123+
124+
- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)URL {
125+
self.resumeExternalUserAgentFlowWithURLCalled = YES;
126+
return true;
127+
}
128+
129+
- (void)failExternalUserAgentFlowWithError:(NSError *)error {
130+
}
131+
132+
@end

okta-oidc.xcodeproj/project.pbxproj

+8-4
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@
297297
E2FB61312536779800D26EDC /* OKTAuthorizationRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E2FB612E2536779800D26EDC /* OKTAuthorizationRequest.m */; };
298298
E2FB61322536779800D26EDC /* OKTAuthorizationRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E2FB612E2536779800D26EDC /* OKTAuthorizationRequest.m */; };
299299
E2FB61422536785200D26EDC /* OKTAuthorizationRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = E2FB612D2536779800D26EDC /* OKTAuthorizationRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
300+
F05AE8372C5874850052CB99 /* OKTRedirectHTTPHandlerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F05AE8362C5874850052CB99 /* OKTRedirectHTTPHandlerTests.m */; };
300301
/* End PBXBuildFile section */
301302

302303
/* Begin PBXContainerItemProxy section */
@@ -552,6 +553,7 @@
552553
E2F6026525104F3000492BEC /* OktaOIDAuthStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OktaOIDAuthStateTests.swift; sourceTree = "<group>"; };
553554
E2FB612D2536779800D26EDC /* OKTAuthorizationRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OKTAuthorizationRequest.h; path = include/OKTAuthorizationRequest.h; sourceTree = "<group>"; };
554555
E2FB612E2536779800D26EDC /* OKTAuthorizationRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OKTAuthorizationRequest.m; sourceTree = "<group>"; };
556+
F05AE8362C5874850052CB99 /* OKTRedirectHTTPHandlerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OKTRedirectHTTPHandlerTests.m; sourceTree = "<group>"; };
555557
/* End PBXFileReference section */
556558

557559
/* Begin PBXFrameworksBuildPhase section */
@@ -723,6 +725,7 @@
723725
A17E39F62358FA3000837873 /* OKTURLSessionProviderTests.m */,
724726
92C1DF5E27A459BC003773F5 /* OKTDefaultTokenValidatorTests.h */,
725727
92C1DF5F27A459BC003773F5 /* OKTDefaultTokenValidatorTests.m */,
728+
F05AE8362C5874850052CB99 /* OKTRedirectHTTPHandlerTests.m */,
726729
);
727730
path = AppAuthTests;
728731
sourceTree = "<group>";
@@ -1578,6 +1581,7 @@
15781581
A167889C2432CDD800D1651D /* OKTRedirectHTTPHandlerMock.swift in Sources */,
15791582
A167889E2433C7B500D1651D /* OktaRedirectServerConfigurationTests.swift in Sources */,
15801583
92C1DF6127A47347003773F5 /* OKTDefaultTokenValidatorTests.m in Sources */,
1584+
F05AE8372C5874850052CB99 /* OKTRedirectHTTPHandlerTests.m in Sources */,
15811585
A16788C22436B1DF00D1651D /* OKTExternalUserAgentSessionMock.swift in Sources */,
15821586
9601C356256DD14900C084F5 /* OIDExternalUserAgentNoSsoTests.swift in Sources */,
15831587
A16788AE243567A400D1651D /* OktaOidcBrowserTaskMacMock.swift in Sources */,
@@ -1796,7 +1800,7 @@
17961800
"@executable_path/Frameworks",
17971801
"@loader_path/Frameworks",
17981802
);
1799-
MARKETING_VERSION = 3.11.5;
1803+
MARKETING_VERSION = 3.11.6;
18001804
PRODUCT_BUNDLE_IDENTIFIER = "com.okta.okta-oidc";
18011805
PRODUCT_NAME = OktaOidc;
18021806
SKIP_INSTALL = YES;
@@ -1826,7 +1830,7 @@
18261830
"@executable_path/Frameworks",
18271831
"@loader_path/Frameworks",
18281832
);
1829-
MARKETING_VERSION = 3.11.5;
1833+
MARKETING_VERSION = 3.11.6;
18301834
PRODUCT_BUNDLE_IDENTIFIER = "com.okta.okta-oidc";
18311835
PRODUCT_NAME = OktaOidc;
18321836
SKIP_INSTALL = YES;
@@ -1974,7 +1978,7 @@
19741978
"@loader_path/Frameworks",
19751979
);
19761980
MACOSX_DEPLOYMENT_TARGET = 10.14;
1977-
MARKETING_VERSION = 3.11.5;
1981+
MARKETING_VERSION = 3.11.6;
19781982
PRODUCT_BUNDLE_IDENTIFIER = "com.okta.okta-oidc";
19791983
PRODUCT_NAME = OktaOidc;
19801984
SDKROOT = macosx;
@@ -2001,7 +2005,7 @@
20012005
"@loader_path/Frameworks",
20022006
);
20032007
MACOSX_DEPLOYMENT_TARGET = 10.14;
2004-
MARKETING_VERSION = 3.11.5;
2008+
MARKETING_VERSION = 3.11.6;
20052009
PRODUCT_BUNDLE_IDENTIFIER = "com.okta.okta-oidc";
20062010
PRODUCT_NAME = OktaOidc;
20072011
SDKROOT = macosx;

0 commit comments

Comments
 (0)