Skip to content

Commit bfbcddd

Browse files
authored
refactor(auth): in memory code verifier storage (#296)
1 parent b3ac087 commit bfbcddd

File tree

4 files changed

+30
-57
lines changed

4 files changed

+30
-57
lines changed

Sources/Auth/AuthClient.swift

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -529,34 +529,31 @@ public actor AuthClient {
529529

530530
/// Log in an existing user by exchanging an Auth Code issued during the PKCE flow.
531531
public func exchangeCodeForSession(authCode: String) async throws -> Session {
532-
guard let codeVerifier = try codeVerifierStorage.getCodeVerifier() else {
532+
guard let codeVerifier = codeVerifierStorage.get() else {
533533
throw AuthError.pkce(.codeVerifierNotFound)
534534
}
535-
do {
536-
let session: Session = try await api.execute(
537-
.init(
538-
path: "/token",
539-
method: .post,
540-
query: [URLQueryItem(name: "grant_type", value: "pkce")],
541-
body: configuration.encoder.encode(
542-
[
543-
"auth_code": authCode,
544-
"code_verifier": codeVerifier,
545-
]
546-
)
535+
536+
let session: Session = try await api.execute(
537+
.init(
538+
path: "/token",
539+
method: .post,
540+
query: [URLQueryItem(name: "grant_type", value: "pkce")],
541+
body: configuration.encoder.encode(
542+
[
543+
"auth_code": authCode,
544+
"code_verifier": codeVerifier,
545+
]
547546
)
548547
)
549-
.decoded(decoder: configuration.decoder)
548+
)
549+
.decoded(decoder: configuration.decoder)
550550

551-
try codeVerifierStorage.deleteCodeVerifier()
551+
codeVerifierStorage.set(nil)
552552

553-
try await sessionManager.update(session)
554-
eventEmitter.emit(.signedIn, session: session)
553+
try await sessionManager.update(session)
554+
eventEmitter.emit(.signedIn, session: session)
555555

556-
return session
557-
} catch {
558-
throw error
559-
}
556+
return session
560557
}
561558

562559
/// Log in an existing user via a third-party provider.
@@ -1020,19 +1017,7 @@ public actor AuthClient {
10201017
}
10211018

10221019
let codeVerifier = PKCE.generateCodeVerifier()
1023-
1024-
do {
1025-
try codeVerifierStorage.storeCodeVerifier(codeVerifier)
1026-
} catch {
1027-
assertionFailure(
1028-
"""
1029-
An error occurred while storing the code verifier,
1030-
PKCE flow may not work as expected.
1031-
1032-
Error: \(error.localizedDescription)
1033-
"""
1034-
)
1035-
}
1020+
codeVerifierStorage.set(codeVerifier)
10361021

10371022
let codeChallenge = PKCE.generateCodeChallenge(from: codeVerifier)
10381023
let codeChallengeMethod = codeVerifier == codeChallenge ? "plain" : "s256"
@@ -1049,7 +1034,7 @@ public actor AuthClient {
10491034

10501035
private func isPKCEFlow(url: URL) -> Bool {
10511036
let fragments = extractParams(from: url)
1052-
let currentCodeVerifier = try? codeVerifierStorage.getCodeVerifier()
1037+
let currentCodeVerifier = codeVerifierStorage.get()
10531038
return fragments.contains(where: { $0.name == "code" }) && currentCodeVerifier != nil
10541039
}
10551040

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,19 @@
1+
import ConcurrencyExtras
12
import Foundation
23
@_spi(Internal) import _Helpers
34

45
struct CodeVerifierStorage: Sendable {
5-
var getCodeVerifier: @Sendable () throws -> String?
6-
var storeCodeVerifier: @Sendable (_ code: String) throws -> Void
7-
var deleteCodeVerifier: @Sendable () throws -> Void
6+
var get: @Sendable () -> String?
7+
var set: @Sendable (_ code: String?) -> Void
88
}
99

1010
extension CodeVerifierStorage {
1111
static let live: Self = {
12-
@Dependency(\.configuration.localStorage) var localStorage
13-
14-
let key = "supabase.code-verifier"
12+
let code = LockIsolated(String?.none)
1513

1614
return Self(
17-
getCodeVerifier: {
18-
try localStorage.retrieve(key: key).flatMap {
19-
String(data: $0, encoding: .utf8)
20-
}
21-
},
22-
storeCodeVerifier: { code in
23-
try localStorage.store(key: key, value: Data(code.utf8))
24-
},
25-
deleteCodeVerifier: {
26-
try localStorage.remove(key: key)
27-
}
15+
get: { code.value },
16+
set: { code.setValue($0) }
2817
)
2918
}()
3019
}

Tests/AuthTests/Mocks/Mocks.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ let clientURL = URL(string: "http://localhost:54321/auth/v1")!
1616

1717
extension CodeVerifierStorage {
1818
static let mock = Self(
19-
getCodeVerifier: unimplemented("CodeVerifierStorage.getCodeVerifier"),
20-
storeCodeVerifier: unimplemented("CodeVerifierStorage.storeCodeVerifier"),
21-
deleteCodeVerifier: unimplemented("CodeVerifierStorage.deleteCodeVerifier")
19+
get: unimplemented("CodeVerifierStorage.get"),
20+
set: unimplemented("CodeVerifierStorage.set")
2221
)
2322
}
2423

Tests/AuthTests/RequestsTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ final class RequestsTests: XCTestCase {
160160

161161
Current.sessionManager = .live
162162
Current.sessionStorage.storeSession = { _ in }
163-
Current.codeVerifierStorage.getCodeVerifier = { nil }
163+
Current.codeVerifierStorage.get = { nil }
164164
Current.currentDate = { currentDate }
165165

166166
let url = URL(
@@ -184,7 +184,7 @@ final class RequestsTests: XCTestCase {
184184
func testSessionFromURLWithMissingComponent() async {
185185
let sut = makeSUT()
186186

187-
Current.codeVerifierStorage.getCodeVerifier = { nil }
187+
Current.codeVerifierStorage.get = { nil }
188188

189189
let url = URL(
190190
string:

0 commit comments

Comments
 (0)