Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Akhu/425452dfe11f32cae5b6f731e0cb9a14 to your computer and use it in GitHub Desktop.
Save Akhu/425452dfe11f32cae5b6f731e0cb9a14 to your computer and use it in GitHub Desktop.
Sample on how to manage authentication of an oauth api with alamofire and swift
//
// Authentication.swift
//
// Created by Anthony on 04/05/2017.
// Copyright © 2017 Aboutgoods. All rights reserved.
//
import Foundation
import Alamofire
class Authentication: RequestAdapter, RequestRetrier {
private typealias RefreshCompletion = (_ succeeded: Bool, _ refreshToken: String?) -> Void
private let sessionManager: SessionManager = {
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
return SessionManager(configuration: configuration)
}()
private let lock = NSLock()
private var baseURLString: String = Router.baseURLString
private var refreshToken: String
private var isRefreshing = false
private var requestsToRetry: [RequestRetryCompletion] = []
// MARK: - Initialization
public init(refreshToken: String){
self.refreshToken = refreshToken
}
// MARK: - RequestAdapter
func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
if let urlString = urlRequest.url?.absoluteString, urlString.hasPrefix(self.baseURLString) {
var urlRequestToSend = urlRequest
urlRequestToSend.setValue(refreshToken, forHTTPHeaderField: "token_header")
}
return urlRequest
}
// MARK: - RequestRetrier
func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
lock.lock() ; defer { lock.unlock() }
if let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 {
requestsToRetry.append(completion)
if !isRefreshing {
self.refreshTokens { [weak self] succeeded, refreshToken in
guard let strongSelf = self else { return }
strongSelf.lock.lock() ; defer { strongSelf.lock.unlock() }
if let refreshToken = refreshToken {
strongSelf.refreshToken = refreshToken
}
strongSelf.requestsToRetry.forEach { $0(succeeded, 0.0) }
strongSelf.requestsToRetry.removeAll()
}
}
}
}
private func refreshTokens(completion: @escaping RefreshCompletion){
guard !isRefreshing else { return }
isRefreshing = true
if Core.uuid != nil { //When user is already known
sessionManager.request(Router.login).responseJSON { [weak self] response in
guard let strongSelf = self else { return }
if
let json = response.result.value as? [String:Any],
let token = json["token"] as? String,
{
Core.uuid = uuid
completion(true, token)
}else {
completion(false, nil)
}
strongSelf.isRefreshing = false
}
}else { //If no UUID, its the first time that we see this user, we need to request new uuid
sessionManager.request(Router.requestUUID).responseJSON { [weak self] response in
guard let strongSelf = self else { return }
if
let json = response.result.value as? [String:Any],
let token = json["token"] as? String,
{
Core.uuid = uuid
completion(true, token)
}else{
completion(false, nil)
}
strongSelf.isRefreshing = false
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment