Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OKTA-748810 - Crash/Non-fatal - <CF_IS_OBJC Firebase> #363

Merged
merged 1 commit into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
IldarAbdullin-okta marked this conversation as resolved.
Show resolved Hide resolved
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
Loading