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

fix(auth): sign out should ignore 403s #359

Merged
merged 3 commits into from
May 6, 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
4 changes: 2 additions & 2 deletions Sources/Auth/AuthClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -712,8 +712,8 @@ public final class AuthClient: Sendable {
)
} catch {
// ignore 404s since user might not exist anymore
// ignore 401s since an invalid or expired JWT should sign out the current session
let ignoredCodes = Set([404, 401])
// ignore 401s, and 403s since an invalid or expired JWT should sign out the current session.
let ignoredCodes = Set([404, 403, 401])

if case let AuthError.api(apiError) = error, let code = apiError.code,
!ignoredCodes.contains(code)
Expand Down
31 changes: 31 additions & 0 deletions Tests/AuthTests/AuthClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,37 @@ final class AuthClientTests: XCTestCase {
XCTAssertTrue(sessionRemoved)
}

func testSignOutShouldRemoveSessionIf403Returned() async throws {
sut = makeSUT { _ in
throw AuthError.api(AuthError.APIError(code: 403))
}

let validSession = Session.validSession
try storage.storeSession(.init(session: validSession))

let eventsTask = Task {
await sut.authStateChanges.prefix(2).collect()
}

await Task.megaYield()

do {
try await sut.signOut()
} catch AuthError.api {
} catch {
XCTFail("Unexpected error: \(error)")
}

let events = await eventsTask.value.map(\.event)
let sessions = await eventsTask.value.map(\.session)

XCTAssertNoDifference(events, [.initialSession, .signedOut])
XCTAssertNoDifference(sessions, [validSession, nil])

let sessionRemoved = try storage.getSession() == nil
XCTAssertTrue(sessionRemoved)
}

func testSignInAnonymously() async throws {
let session = Session(fromMockNamed: "anonymous-sign-in-response")

Expand Down
21 changes: 21 additions & 0 deletions Tests/IntegrationTests/AuthClientIntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import CustomDump
import TestHelpers
import XCTest

#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

final class AuthClientIntegrationTests: XCTestCase {
let authClient = AuthClient(
configuration: AuthClient.Configuration(
Expand Down Expand Up @@ -189,6 +193,23 @@ final class AuthClientIntegrationTests: XCTestCase {
}
}

func testDeleteAccountAndSignOut() async throws {
let response = try await signUpIfNeededOrSignIn(email: mockEmail(), password: mockPassword())

let session = try XCTUnwrap(response.session)

var request = URLRequest(url: URL(string: "\(DotEnv.SUPABASE_URL)/rest/v1/rpc/delete_user")!)
request.httpMethod = "POST"
request.setValue(DotEnv.SUPABASE_ANON_KEY, forHTTPHeaderField: "apikey")
request.setValue("Bearer \(session.accessToken)", forHTTPHeaderField: "Authorization")

_ = try await URLSession.shared.data(for: request)

try await XCTAssertAuthChangeEvents([.initialSession, .signedOut]) {
try await authClient.signOut()
}
}

@discardableResult
private func signUpIfNeededOrSignIn(
email: String,
Expand Down
Loading