Skip to content

Commit

Permalink
OKTA-748810 - Crash/Non-fatal - <CF_IS_OBJC Firebase> (#363)
Browse files Browse the repository at this point in the history
  • Loading branch information
IldarAbdullin-okta authored Jul 30, 2024
1 parent 03439c9 commit 866dad9
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 16 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/okta-oidc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,27 @@ on:

jobs:
UnitTests:
runs-on: macos-11
runs-on: macos-latest
env:
DEVELOPER_DIR: /Applications/Xcode_13.1.app/Contents/Developer
DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer
steps:
- uses: actions/checkout@v2
- name: iOS
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
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
- name: macOS
run: set -o pipefail && xcodebuild -project okta-oidc.xcodeproj -scheme "okta-oidc-mac" -destination "platform=macOS" clean test | xcpretty
- name: Swift
run: swift test -v
UITests:
runs-on: macos-11
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: iOS
run: set -o pipefail && xcodebuild -project okta-oidc.xcodeproj -scheme "okta-oidc" -destination "platform=iOS Simulator,OS=latest,name=iPhone 11" clean test | xcpretty
run: set -o pipefail && xcodebuild -project okta-oidc.xcodeproj -scheme "okta-oidc" -destination "platform=iOS Simulator,OS=latest,name=iPhone 15" clean test | xcpretty
PackageValidation:
runs-on: macos-11
runs-on: macos-latest
env:
DEVELOPER_DIR: /Applications/Xcode_13.1.app/Contents/Developer
DEVELOPER_DIR: /Applications/Xcode_15.4.app/Contents/Developer
steps:
- uses: actions/checkout@v2
- name: Cocoapods
Expand Down
2 changes: 1 addition & 1 deletion OktaOidc.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'OktaOidc'
s.version = '3.11.5'
s.version = '3.11.6'
s.summary = 'SDK to easily integrate AppAuth with Okta'
s.description = <<-DESC
Integrate your native app with Okta using the AppAuth library.
Expand Down
2 changes: 1 addition & 1 deletion Sources/AppAuth/OktaUserAgent.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ +(void)setUserAgentValue:(NSString*)value {
}

+(NSString*)userAgentVersion {
return @"3.11.5";
return @"3.11.6";
}

+(NSString*)userAgentHeaderKey {
Expand Down
24 changes: 21 additions & 3 deletions Sources/AppAuth/macOS/OKTRedirectHTTPHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,28 @@ - (void)stopHTTPListener {
_httpServ = nil;
}

- (BOOL)isOptionsHTTPServerRequest:(HTTPServerRequest *)request {
CFStringRef method = CFHTTPMessageCopyRequestMethod(request.request);
if (method == nil) {
return NO;
}

BOOL isOptionsRequest = CFStringCompare(method, (__bridge CFStringRef)@"OPTIONS", kCFCompareCaseInsensitive) == kCFCompareEqualTo;
CFRelease(method);

return isOptionsRequest;
}

- (void)HTTPConnection:(HTTPConnection *)conn didReceiveRequest:(HTTPServerRequest *)mess {
// Handle private network preflight
// https://developer.chrome.com/blog/private-network-access-preflight/
CFStringRef method = CFHTTPMessageCopyRequestMethod(mess.request);
BOOL isOptionsRequest = CFStringCompare(method, (__bridge CFStringRef)@"OPTIONS", 0) == kCFCompareEqualTo;
BOOL isOptionsRequest = [self isOptionsHTTPServerRequest:mess];

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

BOOL handled = NO;
// Sends URL to AppAuth.
CFURLRef url = CFHTTPMessageCopyRequestURL(mess.request);
BOOL handled = [_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:(__bridge NSURL *)url];
if (url != nil) {
handled = [_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:(__bridge NSURL *)url];
CFRelease(url);
}

// Stops listening to further requests after the first valid authorization response.
if (handled) {
Expand Down
132 changes: 132 additions & 0 deletions Tests/AppAuthTests/OKTRedirectHTTPHandlerTests.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* Copyright (c) 2024-Present, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the License.
*/

#import <XCTest/XCTest.h>
#import "OKTRedirectHTTPHandler.h"
#import "OKTLoopbackHTTPServer.h"

@interface OKTRedirectHTTPHandlerTests<OKTExternalUserAgentSession> : XCTestCase

@property BOOL resumeExternalUserAgentFlowWithURLCalled;

- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)URL;

@end

@interface OKTRedirectHTTPHandler(Private)

- (BOOL)isOptionsHTTPServerRequest:(HTTPServerRequest *)request;
- (void)HTTPConnection:(HTTPConnection *)conn didReceiveRequest:(HTTPServerRequest *)mess;

@end

@implementation OKTRedirectHTTPHandlerTests

- (void)testIsOptionsHTTPServerRequest {
OKTRedirectHTTPHandler *handler = [OKTRedirectHTTPHandler new];
CFStringRef url = CFSTR("http://www.okta.com");
CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL);

CFStringRef requestMethod = CFSTR("GET");
CFHTTPMessageRef myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
HTTPConnection *connection = [[HTTPConnection alloc] initWithPeerAddress:nil inputStream:nil outputStream:nil forServer:nil];
HTTPServerRequest *request = [[HTTPServerRequest alloc] initWithRequest:myRequest connection:connection];
BOOL isOptionsRequest = [handler isOptionsHTTPServerRequest: request];
XCTAssertFalse(isOptionsRequest);

requestMethod = CFSTR("OPTIONS");
myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
request = [[HTTPServerRequest alloc] initWithRequest:myRequest connection:connection];
isOptionsRequest = [handler isOptionsHTTPServerRequest: request];
XCTAssertTrue(isOptionsRequest);

requestMethod = CFSTR("options");
myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
request = [[HTTPServerRequest alloc] initWithRequest:myRequest connection:connection];
isOptionsRequest = [handler isOptionsHTTPServerRequest: request];
XCTAssertTrue(isOptionsRequest);

isOptionsRequest = [handler isOptionsHTTPServerRequest: nil];
XCTAssertFalse(isOptionsRequest);
}

- (void)testDidReceiveRequestDelegate_NoOptionsHeader {
OKTRedirectHTTPHandler *handler = [OKTRedirectHTTPHandler new];
handler.currentAuthorizationFlow = (id<OKTExternalUserAgentSession>)self;
CFStringRef url = CFSTR("http://www.okta.com");
CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL);
CFStringRef requestMethod = CFSTR("GET");
CFHTTPMessageRef myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
HTTPConnection *connection = [[HTTPConnection alloc] initWithPeerAddress:nil inputStream:nil outputStream:nil forServer:nil];
HTTPServerRequest *request = [[HTTPServerRequest alloc] initWithRequest:myRequest connection:connection];

self.resumeExternalUserAgentFlowWithURLCalled = NO;
[handler HTTPConnection:connection didReceiveRequest:request];
XCTAssertTrue(self.resumeExternalUserAgentFlowWithURLCalled);

myURL = nil;
requestMethod = CFSTR("GET");
myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
request = [[HTTPServerRequest alloc] initWithRequest:myRequest connection:connection];
self.resumeExternalUserAgentFlowWithURLCalled = NO;
[handler HTTPConnection:connection didReceiveRequest:request];
XCTAssertFalse(self.resumeExternalUserAgentFlowWithURLCalled);
}

- (void)testDidReceiveRequestDelegate_WithOptionsHeader {
OKTRedirectHTTPHandler *handler = [OKTRedirectHTTPHandler new];
handler.currentAuthorizationFlow = (id<OKTExternalUserAgentSession>)self;
CFStringRef url = CFSTR("http://www.okta.com");
CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL);
CFStringRef requestMethod = CFSTR("OPTIONS");
CFHTTPMessageRef myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1);
HTTPConnection *connection = [[HTTPConnection alloc] initWithPeerAddress:nil inputStream:nil outputStream:nil forServer:nil];
HTTPServerRequest *request = [[HTTPServerRequest alloc] initWithRequest:myRequest connection:connection];
CFStringRef privateNetworkHeader = CFSTR("Access-Control-Request-Private-Network");
CFStringRef privateNetworkValue = CFSTR("true");
CFHTTPMessageSetHeaderFieldValue(myRequest, privateNetworkHeader, privateNetworkValue);
CFStringRef originHeader = CFSTR("Origin");
CFStringRef originValue = CFSTR("http://www.okta.com");
CFHTTPMessageSetHeaderFieldValue(myRequest, originHeader, originValue);

self.resumeExternalUserAgentFlowWithURLCalled = NO;
[handler HTTPConnection:connection didReceiveRequest:request];
XCTAssertFalse(self.resumeExternalUserAgentFlowWithURLCalled);

CFHTTPMessageRef response = request.response;

originHeader = CFHTTPMessageCopyHeaderFieldValue(response, (__bridge CFStringRef)@"Access-Control-Allow-Origin");
BOOL originHeaderExists = CFStringCompare(originHeader, originValue, kCFCompareCaseInsensitive) == kCFCompareEqualTo;
XCTAssertTrue(originHeaderExists);

CFStringRef allowCredentialsHeader = CFHTTPMessageCopyHeaderFieldValue(response, (__bridge CFStringRef)@"Access-Control-Allow-Credentials");
BOOL allowCredentialsHeaderExists = CFStringCompare(allowCredentialsHeader, (__bridge CFStringRef)@"true", kCFCompareCaseInsensitive) == kCFCompareEqualTo;
XCTAssertTrue(allowCredentialsHeaderExists);

CFStringRef allowPrivateNetworkHeader = CFHTTPMessageCopyHeaderFieldValue(response, (__bridge CFStringRef)@"Access-Control-Allow-Private-Network");
BOOL allowPrivateNetworkHeaderExists = CFStringCompare(allowPrivateNetworkHeader, (__bridge CFStringRef)@"true", kCFCompareCaseInsensitive) == kCFCompareEqualTo;
XCTAssertTrue(allowPrivateNetworkHeaderExists);

CFStringRef contentLengthHeader = CFHTTPMessageCopyHeaderFieldValue(response, (__bridge CFStringRef)@"Content-Length");
BOOL contentLengthHeaderExists = CFStringCompare(contentLengthHeader, (__bridge CFStringRef)@"0", kCFCompareCaseInsensitive) == kCFCompareEqualTo;
XCTAssertTrue(contentLengthHeaderExists);
}

- (BOOL)resumeExternalUserAgentFlowWithURL:(NSURL *)URL {
self.resumeExternalUserAgentFlowWithURLCalled = YES;
return true;
}

- (void)failExternalUserAgentFlowWithError:(NSError *)error {
}

@end
12 changes: 8 additions & 4 deletions okta-oidc.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@
E2FB61312536779800D26EDC /* OKTAuthorizationRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E2FB612E2536779800D26EDC /* OKTAuthorizationRequest.m */; };
E2FB61322536779800D26EDC /* OKTAuthorizationRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = E2FB612E2536779800D26EDC /* OKTAuthorizationRequest.m */; };
E2FB61422536785200D26EDC /* OKTAuthorizationRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = E2FB612D2536779800D26EDC /* OKTAuthorizationRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
F05AE8372C5874850052CB99 /* OKTRedirectHTTPHandlerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F05AE8362C5874850052CB99 /* OKTRedirectHTTPHandlerTests.m */; };
/* End PBXBuildFile section */

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

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -723,6 +725,7 @@
A17E39F62358FA3000837873 /* OKTURLSessionProviderTests.m */,
92C1DF5E27A459BC003773F5 /* OKTDefaultTokenValidatorTests.h */,
92C1DF5F27A459BC003773F5 /* OKTDefaultTokenValidatorTests.m */,
F05AE8362C5874850052CB99 /* OKTRedirectHTTPHandlerTests.m */,
);
path = AppAuthTests;
sourceTree = "<group>";
Expand Down Expand Up @@ -1578,6 +1581,7 @@
A167889C2432CDD800D1651D /* OKTRedirectHTTPHandlerMock.swift in Sources */,
A167889E2433C7B500D1651D /* OktaRedirectServerConfigurationTests.swift in Sources */,
92C1DF6127A47347003773F5 /* OKTDefaultTokenValidatorTests.m in Sources */,
F05AE8372C5874850052CB99 /* OKTRedirectHTTPHandlerTests.m in Sources */,
A16788C22436B1DF00D1651D /* OKTExternalUserAgentSessionMock.swift in Sources */,
9601C356256DD14900C084F5 /* OIDExternalUserAgentNoSsoTests.swift in Sources */,
A16788AE243567A400D1651D /* OktaOidcBrowserTaskMacMock.swift in Sources */,
Expand Down Expand Up @@ -1796,7 +1800,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 3.11.5;
MARKETING_VERSION = 3.11.6;
PRODUCT_BUNDLE_IDENTIFIER = "com.okta.okta-oidc";
PRODUCT_NAME = OktaOidc;
SKIP_INSTALL = YES;
Expand Down Expand Up @@ -1826,7 +1830,7 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 3.11.5;
MARKETING_VERSION = 3.11.6;
PRODUCT_BUNDLE_IDENTIFIER = "com.okta.okta-oidc";
PRODUCT_NAME = OktaOidc;
SKIP_INSTALL = YES;
Expand Down Expand Up @@ -1974,7 +1978,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 3.11.5;
MARKETING_VERSION = 3.11.6;
PRODUCT_BUNDLE_IDENTIFIER = "com.okta.okta-oidc";
PRODUCT_NAME = OktaOidc;
SDKROOT = macosx;
Expand All @@ -2001,7 +2005,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 3.11.5;
MARKETING_VERSION = 3.11.6;
PRODUCT_BUNDLE_IDENTIFIER = "com.okta.okta-oidc";
PRODUCT_NAME = OktaOidc;
SDKROOT = macosx;
Expand Down

0 comments on commit 866dad9

Please sign in to comment.