Skip to content

Commit

Permalink
fix(auth): prevent from requesting login keychain password os macOS (#…
Browse files Browse the repository at this point in the history
…455)

* fix macOS behavior

* fix failing auth tests

---------

Co-authored-by: Guilherme Souza <[email protected]>
  • Loading branch information
ekurutepe and grdsdev committed Jul 11, 2024
1 parent 2db52ae commit 3e45b5a
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 44 deletions.
5 changes: 5 additions & 0 deletions Sources/Auth/Internal/Keychain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@
query[kSecAttrAccessGroup as String] = accessGroup
}

// this is highly recommended for all keychain operations and makes the
// macOS keychain item behave like an iOS keychain item
// https://developer.apple.com/documentation/security/ksecusedataprotectionkeychain
query[kSecUseDataProtectionKeychain as String] = kCFBooleanTrue

return query
}

Expand Down
86 changes: 42 additions & 44 deletions Tests/AuthTests/SessionManagerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,6 @@ final class SessionManagerTests: XCTestCase {
)
}

override func invokeTest() {
withMainSerialExecutor {
super.invokeTest()
}
}

func testSession_shouldFailWithSessionNotFound() async {
do {
_ = try await sut.session()
Expand All @@ -58,53 +52,57 @@ final class SessionManagerTests: XCTestCase {
}

func testSession_shouldReturnValidSession() async throws {
let session = Session.validSession
try Dependencies[clientID].sessionStorage.store(session)
try await withMainSerialExecutor {
let session = Session.validSession
try Dependencies[clientID].sessionStorage.store(session)

let returnedSession = try await sut.session()
XCTAssertNoDifference(returnedSession, session)
let returnedSession = try await sut.session()
XCTAssertNoDifference(returnedSession, session)
}
}

func testSession_shouldRefreshSession_whenCurrentSessionExpired() async throws {
let currentSession = Session.expiredSession
try Dependencies[clientID].sessionStorage.store(currentSession)

let validSession = Session.validSession

let refreshSessionCallCount = LockIsolated(0)

let (refreshSessionStream, refreshSessionContinuation) = AsyncStream<Session>.makeStream()

http.when(
{ $0.url.path.contains("/token") },
return: { _ in
refreshSessionCallCount.withValue { $0 += 1 }
let session = await refreshSessionStream.first(where: { _ in true })!
return .stub(session)
try await withMainSerialExecutor {
let currentSession = Session.expiredSession
try Dependencies[clientID].sessionStorage.store(currentSession)

let validSession = Session.validSession

let refreshSessionCallCount = LockIsolated(0)

let (refreshSessionStream, refreshSessionContinuation) = AsyncStream<Session>.makeStream()

http.when(
{ $0.url.path.contains("/token") },
return: { _ in
refreshSessionCallCount.withValue { $0 += 1 }
let session = await refreshSessionStream.first(where: { _ in true })!
return .stub(session)
}
)

// Fire N tasks and call sut.session()
let tasks = (0 ..< 10).map { _ in
Task.detached { [weak self] in
try await self?.sut.session()
}
}
)

// Fire N tasks and call sut.session()
let tasks = (0 ..< 10).map { _ in
Task.detached { [weak self] in
try await self?.sut.session()
}
}
await Task.yield()

await Task.megaYield()
refreshSessionContinuation.yield(validSession)
refreshSessionContinuation.finish()

refreshSessionContinuation.yield(validSession)
refreshSessionContinuation.finish()
// Await for all tasks to complete.
var result: [Result<Session?, Error>] = []
for task in tasks {
let value = await task.result
result.append(value)
}

// Await for all tasks to complete.
var result: [Result<Session?, Error>] = []
for task in tasks {
let value = await task.result
result.append(value)
// Verify that refresher and storage was called only once.
XCTAssertEqual(refreshSessionCallCount.value, 1)
XCTAssertEqual(try result.map { try $0.get() }, (0 ..< 10).map { _ in validSession })
}

// Verify that refresher and storage was called only once.
XCTAssertEqual(refreshSessionCallCount.value, 1)
XCTAssertEqual(try result.map { try $0.get() }, (0 ..< 10).map { _ in validSession })
}
}

0 comments on commit 3e45b5a

Please sign in to comment.