NetworkingMidOpen-ended

How do you handle authentication tokens and refresh them?

Explanation & Code

Answer: Store tokens securely in the Keychain, attach them to requests via a header, and refresh automatically when a 401 is received.

Code Example:

class AuthenticatedSession {
    private var accessToken: String { Keychain.get("access_token") ?? "" }
    private var refreshToken: String { Keychain.get("refresh_token") ?? "" }

    func request<T: Decodable>(_ type: T.Type, from url: URL) async throws -> T {
        let result = try await performRequest(type, from: url, token: accessToken)
        return result
    }

    private func performRequest<T: Decodable>(
        _ type: T.Type, from url: URL, token: String
    ) async throws -> T {
        var req = URLRequest(url: url)
        req.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")

        let (data, response) = try await URLSession.shared.data(for: req)

        // Auto-refresh on 401
        if (response as? HTTPURLResponse)?.statusCode == 401 {
            let newToken = try await refreshAccessToken()
            return try await performRequest(type, from: url, token: newToken)
        }

        return try JSONDecoder().decode(T.self, from: data)
    }

    private func refreshAccessToken() async throws -> String {
        // call refresh endpoint, store new token in Keychain
    }
}

Rate your understanding:

Ready to practice more Networking?

Test yourself with our interactive quiz mode or browse all curated questions for this topic.