Created
September 24, 2017 17:33
-
-
Save arashkashi/4f400da227d84b5d26bd96fd53d60b32 to your computer and use it in GitHub Desktop.
Github based auth2 class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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