Skip to content

Commit 457ada2

Browse files
authored
Prevent ASWebAuthenticationSession crash when browser reloads due to cookies being cleared (#904)
1 parent 45d9a59 commit 457ada2

File tree

8 files changed

+170
-41
lines changed

8 files changed

+170
-41
lines changed

Diff for: App/ViewController.swift

+15-23
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,25 @@ import UIKit
22
import Auth0
33

44
class ViewController: UIViewController {
5-
6-
var onAuth: ((WebAuthResult<Credentials>) -> ())!
7-
8-
override func viewDidLoad() {
9-
super.viewDidLoad()
10-
11-
self.onAuth = {
12-
switch $0 {
13-
case .failure(let error):
14-
DispatchQueue.main.async {
15-
self.alert(title: "Error", message: "\(error)")
16-
}
17-
case .success(let credentials):
18-
DispatchQueue.main.async {
19-
self.alert(title: "Success",
20-
message: "Authorized and got a token \(credentials.accessToken)")
21-
}
22-
}
23-
print($0)
24-
}
25-
}
26-
5+
276
@IBAction func login(_ sender: Any) {
287
Auth0
298
.webAuth()
309
.logging(enabled: true)
31-
.start(onAuth)
10+
.start {
11+
switch $0 {
12+
case .failure(let error):
13+
DispatchQueue.main.async {
14+
self.alert(title: "Error", message: "\(error)")
15+
}
16+
case .success(let credentials):
17+
DispatchQueue.main.async {
18+
self.alert(title: "Success",
19+
message: "Authorized and got a token \(credentials.accessToken)")
20+
}
21+
}
22+
print($0)
23+
}
3224
}
3325

3426
@IBAction func logout(_ sender: Any) {

Diff for: Auth0.xcodeproj/project.pbxproj

+8
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@
176176
5CF539292836FB0C0073F623 /* ClearSessionTransactionSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CF539272836FB0C0073F623 /* ClearSessionTransactionSpec.swift */; };
177177
5CF5392B283835470073F623 /* ASProviderSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CF5392A283835460073F623 /* ASProviderSpec.swift */; };
178178
5CF5392C283835470073F623 /* ASProviderSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CF5392A283835460073F623 /* ASProviderSpec.swift */; };
179+
5CFB82612D6D221F009FD237 /* Barrier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFB82602D6D221C009FD237 /* Barrier.swift */; };
180+
5CFB82622D6D221F009FD237 /* Barrier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFB82602D6D221C009FD237 /* Barrier.swift */; };
181+
5CFB82632D6D221F009FD237 /* Barrier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFB82602D6D221C009FD237 /* Barrier.swift */; };
179182
5F06DDC91CC66B710011842B /* Auth0.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F06DDC81CC66B710011842B /* Auth0.swift */; };
180183
5F06DDCA1CC66B710011842B /* Auth0.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F06DDC81CC66B710011842B /* Auth0.swift */; };
181184
5F1FBB9A1D8A44C0006B0B85 /* ResponseSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F1FBB981D8A4465006B0B85 /* ResponseSpec.swift */; };
@@ -678,6 +681,7 @@
678681
5CF539232836DCC10073F623 /* SafariProviderSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariProviderSpec.swift; sourceTree = "<group>"; };
679682
5CF539272836FB0C0073F623 /* ClearSessionTransactionSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearSessionTransactionSpec.swift; sourceTree = "<group>"; };
680683
5CF5392A283835460073F623 /* ASProviderSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASProviderSpec.swift; sourceTree = "<group>"; };
684+
5CFB82602D6D221C009FD237 /* Barrier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Barrier.swift; sourceTree = "<group>"; };
681685
5F049B6E1CB42C29006F6C05 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Auth0/Info.plist; sourceTree = "<group>"; };
682686
5F06DD781CC448B10011842B /* Auth0.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Auth0.framework; sourceTree = BUILT_PRODUCTS_DIR; };
683687
5F06DD851CC448C90011842B /* Auth0.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Auth0.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1111,6 +1115,7 @@
11111115
5FAE9C901D8878D400A871CE /* Auth0WebAuth.swift */,
11121116
5FD255B91D14F70B00387ECB /* WebAuthError.swift */,
11131117
5C0AF09C2833420200162044 /* WebAuthentication.swift */,
1118+
5CFB82602D6D221C009FD237 /* Barrier.swift */,
11141119
);
11151120
name = WebAuth;
11161121
sourceTree = "<group>";
@@ -2024,6 +2029,7 @@
20242029
5CB41D4823D0BA2C00074024 /* IDTokenValidator.swift in Sources */,
20252030
5C354C04276CE1A500ADBC86 /* PasswordlessType.swift in Sources */,
20262031
5FCAB1711D09005A00331C84 /* NSURLComponents+OAuth2.swift in Sources */,
2032+
5CFB82632D6D221F009FD237 /* Barrier.swift in Sources */,
20272033
5FDE876D1D8A424700EA27DC /* Handlers.swift in Sources */,
20282034
5FE2F8BB1CD0EAAD003628F4 /* Response.swift in Sources */,
20292035
970BC36B25C27095007A7745 /* Challenge.swift in Sources */,
@@ -2102,6 +2108,7 @@
21022108
5FD255B81D14F00900387ECB /* Auth0Error.swift in Sources */,
21032109
5C41F6D0244F971700252548 /* JWK+RSA.swift in Sources */,
21042110
5C41F6C7244F968B00252548 /* AuthTransaction.swift in Sources */,
2111+
5CFB82612D6D221F009FD237 /* Barrier.swift in Sources */,
21052112
5FD255B51D14DD2600387ECB /* ManagementError.swift in Sources */,
21062113
5C0AF09B28330CBA00162044 /* SafariProvider.swift in Sources */,
21072114
5FE2F8B31CCEAED8003628F4 /* Requestable.swift in Sources */,
@@ -2386,6 +2393,7 @@
23862393
C1B3BA012C24B6D4004A32A4 /* Array+Encode.swift in Sources */,
23872394
C1B3BA022C24B6D4004A32A4 /* String+URLSafe.swift in Sources */,
23882395
C1B3BA032C24B6D4004A32A4 /* NSData+URLSafe.swift in Sources */,
2396+
5CFB82622D6D221F009FD237 /* Barrier.swift in Sources */,
23892397
C1B3BA042C24B6D4004A32A4 /* NSURL+Auth0.swift in Sources */,
23902398
C1B3BA052C24B6D4004A32A4 /* NSURLComponents+OAuth2.swift in Sources */,
23912399
C1B3BA062C24B6D4004A32A4 /* JWT+Header.swift in Sources */,

Diff for: Auth0/ASProvider.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,23 @@ extension WebAuthentication {
5959

6060
class ASUserAgent: NSObject, WebAuthUserAgent {
6161

62-
let session: ASWebAuthenticationSession
62+
private(set) static var currentSession: ASWebAuthenticationSession?
6363
let callback: WebAuthProviderCallback
6464

6565
init(session: ASWebAuthenticationSession, callback: @escaping WebAuthProviderCallback) {
66-
self.session = session
6766
self.callback = callback
6867
super.init()
6968

7069
session.presentationContextProvider = self
70+
ASUserAgent.currentSession = session
7171
}
7272

7373
func start() {
74-
_ = self.session.start()
74+
_ = ASUserAgent.currentSession?.start()
7575
}
7676

7777
func finish(with result: WebAuthResult<Void>) {
78-
self.session.cancel()
78+
ASUserAgent.currentSession?.cancel()
7979
self.callback(result)
8080
}
8181

Diff for: Auth0/Auth0WebAuth.swift

+10-7
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ final class Auth0WebAuth: WebAuth {
1010
let storage: TransactionStore
1111

1212
var telemetry: Telemetry
13+
var barrier: Barrier
1314
var logger: Logger?
1415

1516
#if os(macOS)
@@ -66,12 +67,14 @@ final class Auth0WebAuth: WebAuth {
6667
url: URL,
6768
session: URLSession = URLSession.shared,
6869
storage: TransactionStore = TransactionStore.shared,
69-
telemetry: Telemetry = Telemetry()) {
70+
telemetry: Telemetry = Telemetry(),
71+
barrier: Barrier = QueueBarrier.shared) {
7072
self.clientId = clientId
7173
self.url = url
7274
self.session = session
7375
self.storage = storage
7476
self.telemetry = telemetry
77+
self.barrier = barrier
7578
self.issuer = url.absoluteString
7679
}
7780

@@ -166,8 +169,7 @@ final class Auth0WebAuth: WebAuth {
166169
}
167170

168171
func start(_ callback: @escaping (WebAuthResult<Credentials>) -> Void) {
169-
170-
if self.storage.current != nil {
172+
guard barrier.raise() else {
171173
return callback(.failure(WebAuthError(code: .transactionActiveAlready)))
172174
}
173175

@@ -198,8 +200,9 @@ final class Auth0WebAuth: WebAuth {
198200
invitation: invitation)
199201

200202
let provider = self.provider ?? WebAuthentication.asProvider(redirectURL: redirectURL, ephemeralSession: ephemeralSession)
201-
let userAgent = provider(authorizeURL) { [storage, onCloseCallback] result in
203+
let userAgent = provider(authorizeURL) { [storage, barrier, onCloseCallback] result in
202204
storage.clear()
205+
barrier.lower()
203206

204207
switch result {
205208
case .success:
@@ -220,8 +223,7 @@ final class Auth0WebAuth: WebAuth {
220223
}
221224

222225
func clearSession(federated: Bool, callback: @escaping (WebAuthResult<Void>) -> Void) {
223-
224-
if self.storage.current != nil {
226+
guard barrier.raise() else {
225227
return callback(.failure(WebAuthError(code: .transactionActiveAlready)))
226228
}
227229

@@ -239,8 +241,9 @@ final class Auth0WebAuth: WebAuth {
239241
}
240242

241243
let provider = self.provider ?? WebAuthentication.asProvider(redirectURL: redirectURL)
242-
let userAgent = provider(logoutURL) { [storage] result in
244+
let userAgent = provider(logoutURL) { [storage, barrier] result in
243245
storage.clear()
246+
barrier.lower()
244247
callback(result)
245248
}
246249
let transaction = ClearSessionTransaction(userAgent: userAgent)

Diff for: Auth0/Barrier.swift

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import Foundation
2+
3+
protocol Barrier: AnyObject {
4+
func raise() -> Bool
5+
func lower()
6+
}
7+
8+
final class QueueBarrier: Barrier {
9+
static let shared = QueueBarrier()
10+
11+
private let queue = DispatchQueue(label: "com.auth0.webauth.barrier.serial")
12+
private(set) var isRaised: Bool = false
13+
14+
private init() {}
15+
16+
func raise() -> Bool {
17+
self.queue.sync {
18+
guard !self.isRaised else { return false }
19+
self.isRaised = true
20+
return self.isRaised
21+
}
22+
}
23+
24+
func lower() {
25+
self.queue.sync {
26+
self.isRaised = false
27+
}
28+
}
29+
}

Diff for: Auth0Tests/ASProviderSpec.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ class ASProviderSpec: QuickSpec {
3636
it("should not use an ephemeral session by default") {
3737
let provider = WebAuthentication.asProvider(redirectURL: CustomSchemeRedirectURL)
3838
userAgent = provider(AuthorizeURL, { _ in }) as? ASUserAgent
39-
expect(userAgent.session.prefersEphemeralWebBrowserSession) == false
39+
expect(ASUserAgent.currentSession?.prefersEphemeralWebBrowserSession) == false
4040
}
4141

4242
it("should use an ephemeral session") {
4343
let provider = WebAuthentication.asProvider(redirectURL: CustomSchemeRedirectURL, ephemeralSession: true)
4444
userAgent = provider(AuthorizeURL, { _ in }) as? ASUserAgent
45-
expect(userAgent.session.prefersEphemeralWebBrowserSession) == true
45+
expect(ASUserAgent.currentSession?.prefersEphemeralWebBrowserSession) == true
4646
}
4747

4848
}

0 commit comments

Comments
 (0)