diff --git a/Sources/IndieWebKit/IndieAuth/AuthenticationRequest.swift b/Sources/IndieWebKit/IndieAuth/AuthenticationRequest.swift index 219b79b..5231825 100644 --- a/Sources/IndieWebKit/IndieAuth/AuthenticationRequest.swift +++ b/Sources/IndieWebKit/IndieAuth/AuthenticationRequest.swift @@ -19,19 +19,19 @@ public class AuthenticationRequest { private var codeChallenge: String? private let codeChallengeMethod = "S256" - private var url: URL { + private var url: URL? { var requestUrl = URLComponents(url: authorizationEndpoint, resolvingAgainstBaseURL: false) - requestUrl?.queryItems.push(URLQueryItem(name: "me", value: profile)) - requestUrl?.queryItems.push(URLQueryItem(name: "client_id", value: clientId)) - requestUrl?.queryItems.push(URLQueryItem(name: "redirect_uri", value: redirectUri)) - requestUrl?.queryItems.push(URLQueryItem(name: "state", value: state)) + requestUrl?.queryItems?.append(URLQueryItem(name: "me", value: profile.absoluteString)) + requestUrl?.queryItems?.append(URLQueryItem(name: "client_id", value: clientId.absoluteString)) + requestUrl?.queryItems?.append(URLQueryItem(name: "redirect_uri", value: redirectUri.absoluteString)) + requestUrl?.queryItems?.append(URLQueryItem(name: "state", value: state)) if codeChallenge != nil { - requestUrl?.queryItems.push(URLQueryItem(name: "code_challenge", value: codeChallenge)) - requestUrl?.queryItems.push(URLQueryItem(name: "code_challenge_method", value: codeChallengeMethod)) + requestUrl?.queryItems?.append(URLQueryItem(name: "code_challenge", value: codeChallenge)) + requestUrl?.queryItems?.append(URLQueryItem(name: "code_challenge_method", value: codeChallengeMethod)) } - return requestUrl.url + return requestUrl?.url } init(for profile: URL, at authorizationEndpoint: URL, clientId: URL, redirectUri: URL, state: String, codeChallenge: String?) { @@ -47,8 +47,56 @@ public class AuthenticationRequest { } } - func start() { - ASWebAuthenticationSession(url: url, callbackURLScheme: <#T##String?#>, completionHandler: <#T##ASWebAuthenticationSession.CompletionHandler##ASWebAuthenticationSession.CompletionHandler##(URL?, Error?) -> Void#>) + func start(completion: @escaping ((String?) -> ())) { + guard url != nil else { + // TODO: Throw some type of error + return + } + + ASWebAuthenticationSession(url: url!, callbackURLScheme: nil) { [weak self] responseUrl, error in + guard error == nil else { + // TODO: Throw some type of error + return + } + + guard responseUrl != nil else { + // TODO: Throw some type of error + return + } + + let authorizationCode = self?.parseResponse(responseUrl!) + guard authorizationCode != nil else { + // TODO: Throw an error because authorization code should not be nil + return + } + + verifyAuthenticationCode(authorizationCode!) + }.start() + } + + private func parseResponse(_ responseUrl: URL) -> String { + let responseComponents = URLComponents(url: responseUrl, resolvingAgainstBaseURL: false) + var state = "" + var code = "" + + responseComponents?.queryItems?.forEach { queryItem in + if queryItem.name == "code", queryItem.value != nil { + code = queryItem.value! + } else if queryItem.name == "state", queryItem.value != nil { + state = queryItem.value! + } + } + + guard state == self.state else { + // TODO: Throw some error because state doesn't match + return "" + } + + return code + } + + private func verifyAuthenticationCode(_ code: String) { + // TODO: Resume #5 here } private func generateDefaultCodeChallenge() -> String? {