-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Testing out refresh doing a new login
- Loading branch information
1 parent
68e1410
commit c5861fb
Showing
4 changed files
with
151 additions
and
99 deletions.
There are no files selected for viewing
100 changes: 12 additions & 88 deletions
100
Sources/OAuthenticator/ApplyAuthentationOperation.swift
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,111 +1,35 @@ | ||
import Foundation | ||
import AuthenticationServices | ||
import OperationPlus | ||
|
||
class ApplyAuthentationOperation: AsyncProducerOperation<Result<URLRequest, Error>> { | ||
let request: URLRequest | ||
let config: AuthConfiguration | ||
|
||
private var session: ASWebAuthenticationSession? | ||
|
||
private lazy var contextProvider: CredentialWindowProvider = { | ||
CredentialWindowProvider() | ||
}() | ||
private let applier: AuthenticationApplier | ||
|
||
init(request: URLRequest, config: AuthConfiguration) { | ||
self.request = request | ||
self.config = config | ||
self.applier = AuthenticationApplier(request: request, config: config) | ||
} | ||
|
||
override func cancel() { | ||
OperationQueue.main.addOperation { | ||
self.session?.cancel() | ||
self.session = nil | ||
} | ||
applier.cancel() | ||
|
||
super.cancel() | ||
} | ||
|
||
var config: AuthConfiguration { | ||
return applier.config | ||
} | ||
|
||
override func main() { | ||
OperationQueue.preconditionNotMain() | ||
|
||
config.loginStorage.retrieveLogin { result in | ||
switch result { | ||
case .success(let login): | ||
self.buildRequest(with: login) | ||
case .failure: | ||
self.beginLogin() | ||
} | ||
} | ||
} | ||
|
||
private func buildRequest(with login: OAuthLogin) { | ||
let authedRequest = self.request.authorizedRequest(with: login.accessToken) | ||
|
||
self.finish(with: .success(authedRequest)) | ||
} | ||
|
||
private func beginLogin() { | ||
precondition(self.session == nil) | ||
|
||
// ok, we have no token | ||
let url = config.tokenURL | ||
let scheme = config.callbackURLScheme | ||
|
||
OperationQueue.main.addOperation { | ||
let session = ASWebAuthenticationSession(url: url, callbackURLScheme: scheme, completionHandler: { result in | ||
switch result { | ||
case .failure(let error): | ||
self.finish(with: .failure(error)) | ||
case .success(let callbackURL): | ||
self.handleSessionResult(url: callbackURL) | ||
} | ||
}) | ||
|
||
session.prefersEphemeralWebBrowserSession = true | ||
session.presentationContextProvider = self.contextProvider | ||
|
||
session.start() | ||
|
||
self.session = session | ||
} | ||
} | ||
|
||
private func handleSessionResult(url: URL) { | ||
do { | ||
let tokenRequest = try self.config.flowHandler.accessRequestFromCallback(url: url) | ||
|
||
performAccessRequest(tokenRequest) | ||
} catch { | ||
self.finish(with: .failure(error)) | ||
} | ||
} | ||
|
||
private func performAccessRequest(_ request: URLRequest) { | ||
config.loader.response(for: request) { result in | ||
switch result { | ||
config.loginStorage.retrieveLogin { loginResult in | ||
switch loginResult { | ||
case .failure(let error): | ||
self.finish(with: .failure(error)) | ||
case .success(let response): | ||
self.handleLoginResponse(response) | ||
} | ||
} | ||
} | ||
|
||
private func handleLoginResponse(_ response: URLSession.DataTaskResponse) { | ||
do { | ||
let login = try JSONDecoder().decode(LoginResponse.self, from: response.data).oauthLogin | ||
|
||
self.config.loginStorage.storeLogin(login) { error in | ||
if let error = error { | ||
self.finish(with: .failure(error)) | ||
return | ||
case .success(let login): | ||
self.applier.applyAuthentication(using: login) { result in | ||
self.finish(with: result) | ||
} | ||
|
||
self.buildRequest(with: login) | ||
} | ||
} catch { | ||
self.finish(with: .failure(error)) | ||
} | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import Foundation | ||
import AuthenticationServices | ||
|
||
class AuthenticationApplier { | ||
let request: URLRequest | ||
let config: AuthConfiguration | ||
|
||
private var session: ASWebAuthenticationSession? | ||
|
||
private lazy var contextProvider: CredentialWindowProvider = { | ||
CredentialWindowProvider() | ||
}() | ||
|
||
init(request: URLRequest, config: AuthConfiguration) { | ||
self.request = request | ||
self.config = config | ||
} | ||
|
||
func cancel() { | ||
OperationQueue.main.addOperation { | ||
self.session?.cancel() | ||
self.session = nil | ||
} | ||
} | ||
|
||
func applyAuthentication(using login: OAuthLogin, completionHandler: @escaping (Result<URLRequest, Error>) -> Void) { | ||
let authedRequest = self.buildRequest(with: login) | ||
|
||
completionHandler(.success(authedRequest)) | ||
} | ||
|
||
private func buildRequest(with login: OAuthLogin) -> URLRequest { | ||
return request.authorizedRequest(with: login.accessToken) | ||
} | ||
|
||
func beginLogin(completionHandler: @escaping (Result<URLRequest, Error>) -> Void) { | ||
precondition(self.session == nil) | ||
|
||
// ok, we have no token | ||
let url = config.tokenURL | ||
let scheme = config.callbackURLScheme | ||
|
||
OperationQueue.main.addOperation { | ||
let session = ASWebAuthenticationSession(url: url, callbackURLScheme: scheme, completionHandler: { result in | ||
switch result { | ||
case .failure(let error): | ||
completionHandler(.failure(error)) | ||
case .success(let callbackURL): | ||
self.handleSessionResult(url: callbackURL, completionHandler: completionHandler) | ||
} | ||
}) | ||
|
||
session.prefersEphemeralWebBrowserSession = true | ||
session.presentationContextProvider = self.contextProvider | ||
|
||
session.start() | ||
|
||
self.session = session | ||
} | ||
} | ||
|
||
private func handleSessionResult(url: URL, completionHandler: @escaping (Result<URLRequest, Error>) -> Void) { | ||
do { | ||
let tokenRequest = try self.config.flowHandler.accessRequestFromCallback(url: url) | ||
|
||
performAccessRequest(tokenRequest, completionHandler: completionHandler) | ||
} catch { | ||
completionHandler(.failure(error)) | ||
} | ||
} | ||
|
||
private func performAccessRequest(_ request: URLRequest, completionHandler: @escaping (Result<URLRequest, Error>) -> Void) { | ||
config.loader.response(for: request) { result in | ||
switch result { | ||
case .failure(let error): | ||
completionHandler(.failure(error)) | ||
case .success(let response): | ||
self.handleLoginResponse(response, completionHandler: completionHandler) | ||
} | ||
} | ||
} | ||
|
||
private func handleLoginResponse(_ response: URLSession.DataTaskResponse, completionHandler: @escaping (Result<URLRequest, Error>) -> Void) { | ||
do { | ||
let login = try JSONDecoder().decode(LoginResponse.self, from: response.data).oauthLogin | ||
|
||
self.config.loginStorage.storeLogin(login) { error in | ||
if let error = error { | ||
completionHandler(.failure(error)) | ||
return | ||
} | ||
|
||
let authedRequest = self.buildRequest(with: login) | ||
|
||
completionHandler(.success(authedRequest)) | ||
} | ||
} catch { | ||
completionHandler(.failure(error)) | ||
} | ||
} | ||
} |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -153,3 +153,9 @@ extension OAuthenticator { | |
} | ||
} | ||
} | ||
|
||
extension OAuthenticator { | ||
static func getUserCredentials() { | ||
|
||
} | ||
} |