mobile-ios/CovidSafe/API/CovidNetworking.swift
2021-05-12 17:39:38 -07:00

93 lines
2.6 KiB
Swift

//
// CovidNetworking.swift
// CovidSafe
//
// Copyright © 2020 Australian Government. All rights reserved.
//
import Foundation
import Alamofire
import KeychainSwift
final class CovidServerTrustManager: ServerTrustManager {
override func serverTrustEvaluator(forHost host: String) throws -> ServerTrustEvaluating? {
guard let evaluator = evaluators[host] else {
for key in evaluators.keys {
if (host.hasSuffix(key)) {
return evaluators[key]
}
}
if allHostsMustBeEvaluated {
throw AFError.serverTrustEvaluationFailed(reason: .noRequiredEvaluator(host: host))
}
return nil
}
return evaluator
}
}
class CovidNetworking {
static private let validCerts = [CovidCertificates.AmazonRootCA1, CovidCertificates.AmazonRootCA2, CovidCertificates.AmazonRootCA3, CovidCertificates.AmazonRootCA4, CovidCertificates.SFSRootCA]
private let evaluators = [
"covidsafe.gov.au": PinnedCertificatesTrustEvaluator(certificates: CovidNetworking.validCerts)
]
static let shared = CovidNetworking()
public let session: Session
init() {
let serverTrustPolicy = CovidServerTrustManager(evaluators: evaluators)
session = Session(serverTrustManager:serverTrustPolicy)
}
}
enum APIError: Error {
case ExpireSession
case ServerError
}
struct CovidSafeErrorResponse: Decodable {
let message: String?
}
enum CovidSafeAPIError: Error {
case RequestError
case ResponseError
case ServerError
case TokenExpiredError
case TokenAlreadyRefreshedError
case MaxRegistrationError
case UnknownError
}
class CovidSafeAuthenticatedAPI {
static var isBusy = false
static func authenticatedHeaders() throws -> HTTPHeaders {
let keychain = KeychainSwift.shared
guard let token = keychain.get("JWT_TOKEN") else {
throw CovidSafeAPIError.RequestError
}
let headers: HTTPHeaders = [
"Authorization": "Bearer \(token)"
]
return headers
}
static func processUnauthorizedError(_ data: Data) -> CovidSafeAPIError {
var errorType = CovidSafeAPIError.RequestError
do {
let errorResponse = try JSONDecoder().decode(CovidSafeErrorResponse.self, from: data)
if errorResponse.message == "Unauthorized" {
errorType = .TokenExpiredError
}
} catch {
// unable to parse response
errorType = .ResponseError
}
return errorType
}
}