Skip to content

Instantly share code, notes, and snippets.

@arashkashi
Created September 24, 2017 17:33
Show Gist options
  • Save arashkashi/4f400da227d84b5d26bd96fd53d60b32 to your computer and use it in GitHub Desktop.
Save arashkashi/4f400da227d84b5d26bd96fd53d60b32 to your computer and use it in GitHub Desktop.
Github based auth2 class
class Authentication: NSObject, KnowsRootViewController, SFSafariViewControllerDelegate {
static let shared = Authentication()
private static let clientId: String = "666"
private static let clientSecret: String = "777777"
private static let loginURL = URL(string: "https://github.com/login/oauth/authorize?scope=user:email&client_id=\(Authentication.clientId)")!
private static let logoutURL = URL(string: "https://github.com/logout")!
private let kToken: String = "ACCESS_TOKEN"
private let tokenURL = "https://github.com/login/oauth/access_token"
private let logoutURL = "https://github.com/logout"
private weak var safariVC: SFSafariViewController?
private var dataTask: URLSessionDataTask?
// TODO: We should store it locally somewhere safe such as keychain
private(set) var accessToken: String? {
set {
UserDefaults.standard.set(newValue, forKey: self.kToken)
UserDefaults.standard.synchronize()
}
get {
assert(Thread.isMainThread)
if isSigningIn { return nil }
let result = UserDefaults.standard.string(forKey: self.kToken)
if result == nil {
self.login()
isSigningIn = true
}
return result
}
}
private var isSigningIn: Bool = false
private override init() {}
@objc func didCancelAuth() {
closeLoginView()
}
private func closeLoginView() {
DispatchQueue.main.async { [weak self] _ in
self?.safariVC?.dismiss(animated: true, completion: nil)
self?.isSigningIn = false
}
}
private func presentSafariWithURL(url: URL) {
assert(Thread.isMainThread)
let vc = SFSafariViewController(url: url)
safariVC = vc
safariVC?.delegate = self
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel,
target: nil,
action: #selector(Authentication.didCancelAuth))
vc.navigationItem.rightBarButtonItem = cancelButton
rootViewController.present(vc,
animated: true,
completion: nil)
}
private func login() {
presentSafariWithURL(url: Authentication.loginURL)
}
// MARK: API
func logout(completion: @escaping (Bool) -> Void) {
assert(Thread.isMainThread)
presentSafariWithURL(url: URL(string: logoutURL)!)
accessToken = nil
}
func getTokenWith(url: URL, completion: @escaping (Bool) -> Void) {
let code: String
if let validCode = url.queryParameters?["code"] {
code = validCode
} else {
completion(false)
return
}
let url = URL(string: tokenURL)!
var request = URLRequest(url: url,
cachePolicy: .reloadIgnoringCacheData,
timeoutInterval: 5000)
request.httpMethod = "POST"
let postString = "client_id=\(Authentication.clientId)&client_secret=\(Authentication.clientSecret)&code=\(code)&accept=json"
request.httpBody = postString.data(using: .utf8)
let session = URLSession(configuration: .default,
delegate: nil,
delegateQueue: nil)
if dataTask?.state == .running ||
dataTask?.state == .suspended {
dataTask?.cancel()
}
dataTask = session.dataTask(with: request) { [weak self] (data, response, error) in
// TODO: Manage all the error cases
guard let data = data else {
return
}
self?.accessToken = String(data: data, encoding: .utf8)?.components(separatedBy: "=")[1].components(separatedBy: "&")[0]
self?.closeLoginView()
completion(true)
}
dataTask?.resume()
}
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
isSigningIn = false
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment