Browse Questions
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
}
}