Skip to content

Commit e75b06c

Browse files
authored
Guard against ASWebAuthenticationSession invoking the callback repeatedly. (#265)
* Guard against ASWebAuthenticationSession invoking the callback repeatedly. * Add a deprecated implementation of a previously-renamed error case Test updates: * Ensure multiple calls to the completionHandler doesn't result in a continuation misusage * Improve the sample app sign-in UI to support choosing async/await or completion-block workflows * Improvements to XCUI keyboard dismissal
1 parent 5ea8984 commit e75b06c

20 files changed

+254
-78
lines changed

OktaAuthFoundation.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Pod::Spec.new do |s|
22
s.name = "OktaAuthFoundation"
33
s.module_name = "AuthFoundation"
4-
s.version = "2.1.3"
4+
s.version = "2.1.4"
55
s.summary = "Okta Authentication Foundation"
66
s.description = <<-DESC
77
Provides the foundation and common features used to authenticate users, managing the lifecycle and storage of tokens and credentials, and provide a base for other Okta SDKs to build upon.

OktaBrowserSignin.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Pod::Spec.new do |s|
22
s.name = "OktaBrowserSignin"
33
s.module_name = "BrowserSignin"
4-
s.version = "2.1.3"
4+
s.version = "2.1.4"
55
s.summary = "Okta Browser Sign In UI"
66
s.description = <<-DESC
77
Authenticate users using web-based OIDC.

OktaClient.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "OktaClient"
3-
s.version = "2.1.3"
3+
s.version = "2.1.4"
44
s.summary = "Secure client authentication, request authorization, and user management capabilities for Swift."
55
s.description = <<-DESC
66
Provides a modularized set of libraries that provide the building blocks and convenience features used to authenticate users, manage the lifecycle and storage of tokens and user credentials, and provide a base for other libraries and applications to build upon.

OktaDirectAuth.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "OktaDirectAuth"
3-
s.version = "2.1.3"
3+
s.version = "2.1.4"
44
s.summary = "Okta Direct Authentication"
55
s.description = <<-DESC
66
Enables application developers to build native sign in experiences using the Okta Direct Authentication API.

OktaIdxAuth.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'OktaIdxAuth'
3-
s.version = '2.1.3'
3+
s.version = '2.1.4'
44
s.summary = 'SDK to easily integrate the Okta Identity Engine'
55
s.description = <<-DESC
66
Integrate your native app with Okta using the Okta Identity Engine library.

OktaOAuth2.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Pod::Spec.new do |s|
22
s.name = "OktaOAuth2"
33
s.module_name = "OAuth2Auth"
4-
s.version = "2.1.3"
4+
s.version = "2.1.4"
55
s.summary = "Okta OAuth2 Authentication"
66
s.description = <<-DESC
77
Enables application developers to authenticate users utilizing a variety of OAuth2 authentication flows.

Samples/Shared/Common/Testing/Screen+Extensions.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ extension WebLogin where Self: Screen {
7878
}
7979

8080
field.typeText(username)
81+
dismissKeyboard()
8182
}
8283

8384
tapKeyboardNextOrGo()
@@ -149,6 +150,7 @@ extension WebLogin where Self: Screen {
149150
}
150151

151152
field.typeText(password)
153+
dismissKeyboard()
152154

153155
tapKeyboardNextOrGo()
154156

Samples/Shared/Common/Testing/Screen.swift

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,26 +57,56 @@ extension Screen {
5757
return false
5858
}
5959

60+
#if !os(tvOS)
61+
private func _dismissSafariKeyboardIfPresent() -> Bool {
62+
let safariViewServiceApp = XCUIApplication(bundleIdentifier: "com.apple.SafariViewService")
63+
guard safariViewServiceApp.state == .runningForeground else {
64+
return false
65+
}
66+
67+
for name in ["selected", "Done"] {
68+
let button = safariViewServiceApp.buttons[name].firstMatch
69+
if button.isHittable {
70+
button.tap()
71+
return true
72+
}
73+
}
74+
75+
return false
76+
}
77+
78+
private func _dismissAppKeyboardIfPresent() -> Bool {
79+
guard app.keyboards.element(boundBy: 0).exists else {
80+
return false
81+
}
82+
83+
if UIDevice.current.userInterfaceIdiom == .pad {
84+
app.keyboards.buttons["Hide keyboard"].tap()
85+
return true
86+
} else {
87+
app.toolbars.buttons["Done"].tap()
88+
return true
89+
}
90+
}
91+
92+
private func _dismissKeyboardUsingToolbarButton() -> Bool {
93+
let doneButton = app.toolbars.matching(identifier: "Toolbar").buttons["Done"]
94+
if doneButton.exists {
95+
doneButton.tap()
96+
return true
97+
}
98+
return false
99+
}
100+
#endif
101+
60102
@discardableResult
61103
func dismissKeyboard() -> Bool {
62104
#if os(tvOS)
63105
// TODO: Update this in the future to select the appropriately named button.
64106
XCUIRemote.shared.press(.select)
107+
return false
65108
#else
66-
let doneButton = app.toolbars.matching(identifier: "Toolbar").buttons["Done"]
67-
if app.keyboards.element(boundBy: 0).exists {
68-
if UIDevice.current.userInterfaceIdiom == .pad {
69-
app.keyboards.buttons["Hide keyboard"].tap()
70-
return true
71-
} else {
72-
app.toolbars.buttons["Done"].tap()
73-
return true
74-
}
75-
} else if doneButton.exists {
76-
doneButton.tap()
77-
return true
78-
}
109+
return _dismissSafariKeyboardIfPresent() || _dismissKeyboardUsingToolbarButton() || _dismissAppKeyboardIfPresent()
79110
#endif
80-
return false
81111
}
82112
}

Samples/WebSignIn/WebSignIn (iOS)/UITests/BrowserSignInTests.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,23 @@ class BrowserSignInUITests: XCTestCase {
6565
}
6666

6767
func testEphemeralSignInAndSignOut() throws {
68+
signInScreen.isVisible()
69+
signInScreen.setEphemeral(true)
70+
signInScreen.setUsesAsyncAwait(true)
71+
signInScreen.login(username: username, password: password)
72+
73+
profileScreen.wait()
74+
save(screenshot: "Profile Screen")
75+
76+
XCTAssertEqual(profileScreen.valueLabel(for: .username).label, username)
77+
XCTAssertEqual(profileScreen.valueLabel(for: .defaultCredential).label, "Yes")
78+
79+
profileScreen.signOut(.endSession)
80+
81+
signInScreen.isVisible()
82+
}
83+
84+
func testEphemeralSignInAndSignOutWithAsyncAwait() throws {
6885
signInScreen.isVisible()
6986
signInScreen.setEphemeral(true)
7087
signInScreen.login(username: username, password: password)

Samples/WebSignIn/WebSignIn (iOS)/UITests/Pages/SignInScreen.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,24 @@ class SignInScreen: Screen, WebLogin {
1818
let testCase: XCTestCase
1919

2020
lazy var ephemeralSwitch = app.switches["ephemeral_switch"]
21+
lazy var asyncAwaitSwitch = app.switches["async_switch"]
2122
lazy var signInButton = app.buttons["sign_in_button"]
2223
lazy var clientIdLabel = app.buttons["client_id_label"]
2324

2425
init(_ testCase: XCTestCase) {
2526
self.testCase = testCase
2627
}
27-
28+
29+
var usesAsyncAwait: Bool {
30+
asyncAwaitSwitch.isOn ?? false
31+
}
32+
33+
func setUsesAsyncAwait(_ enabled: Bool) {
34+
if asyncAwaitSwitch.isOn != enabled {
35+
asyncAwaitSwitch.tap()
36+
}
37+
}
38+
2839
func isVisible(timeout: TimeInterval = 3) {
2940
XCTAssertTrue(app.staticTexts["Okta Web Sign In"].waitForExistence(timeout: timeout))
3041
XCTAssertFalse(app.staticTexts["Not configured"].exists)

0 commit comments

Comments
 (0)