// // OAuth1Swift.swift // OAuthSwift // // Created by Dongri Jin on 6/22/14. // Copyright (c) 2014 Dongri Jin. All rights reserved. // import Foundation open class OAuth1Swift: OAuthSwift { /// If your oauth provider doesn't provide `oauth_verifier` /// set this value to true (default: false) open var allowMissingOAuthVerifier: Bool = false /// Optionally add callback URL to authorize Url (default: false) open var addCallbackURLToAuthorizeURL: Bool = false var consumerKey: String var consumerSecret: String var requestTokenUrl: String var authorizeUrl: String var accessTokenUrl: String // MARK: init public init(consumerKey: String, consumerSecret: String, requestTokenUrl: String, authorizeUrl: String, accessTokenUrl: String) { self.consumerKey = consumerKey self.consumerSecret = consumerSecret self.requestTokenUrl = requestTokenUrl self.authorizeUrl = authorizeUrl self.accessTokenUrl = accessTokenUrl super.init(consumerKey: consumerKey, consumerSecret: consumerSecret) self.client.credential.version = .oauth1 } public convenience override init(consumerKey: String, consumerSecret: String) { self.init(consumerKey: consumerKey, consumerSecret: consumerSecret, requestTokenUrl: "", authorizeUrl: "", accessTokenUrl: "") } public convenience init?(parameters: ConfigParameters) { guard let consumerKey = parameters["consumerKey"], let consumerSecret = parameters["consumerSecret"], let requestTokenUrl = parameters["requestTokenUrl"], let authorizeUrl = parameters["authorizeUrl"], let accessTokenUrl = parameters["accessTokenUrl"] else { return nil } self.init(consumerKey: consumerKey, consumerSecret: consumerSecret, requestTokenUrl: requestTokenUrl, authorizeUrl: authorizeUrl, accessTokenUrl: accessTokenUrl) } open var parameters: ConfigParameters { return [ "consumerKey": consumerKey, "consumerSecret": consumerSecret, "requestTokenUrl": requestTokenUrl, "authorizeUrl": authorizeUrl, "accessTokenUrl": accessTokenUrl ] } // MARK: functions // 0. Start @discardableResult open func authorize(withCallbackURL callbackURL: URL, success: @escaping TokenSuccessHandler, failure: FailureHandler?) -> OAuthSwiftRequestHandle? { self.postOAuthRequestToken(callbackURL: callbackURL, success: { [unowned self] credential, _, _ in self.observeCallback { [weak self] url in guard let this = self else { OAuthSwift.retainError(failure); return } var responseParameters = [String: String]() if let query = url.query { responseParameters += query.parametersFromQueryString } if let fragment = url.fragment, !fragment.isEmpty { responseParameters += fragment.parametersFromQueryString } if let token = responseParameters["token"] { responseParameters["oauth_token"] = token } if let token = responseParameters["oauth_token"], !token.isEmpty { this.client.credential.oauthToken = token.safeStringByRemovingPercentEncoding if let oauth_verifier = responseParameters["oauth_verifier"] { this.client.credential.oauthVerifier = oauth_verifier.safeStringByRemovingPercentEncoding } else { if !this.allowMissingOAuthVerifier { failure?(OAuthSwiftError.configurationError(message: "Missing oauth_verifier. Maybe use allowMissingOAuthVerifier=true")) return } } this.postOAuthAccessTokenWithRequestToken(success: success, failure: failure) } else { failure?(OAuthSwiftError.missingToken) return } } // 2. Authorize if let token = credential.oauthToken.urlQueryEncoded { var urlString = self.authorizeUrl + (self.authorizeUrl.contains("?") ? "&" : "?") urlString += "oauth_token=\(token)" if self.addCallbackURLToAuthorizeURL { urlString += "&oauth_callback=\(callbackURL.absoluteString)" } if let queryURL = URL(string: urlString) { self.authorizeURLHandler.handle(queryURL) } else { failure?(OAuthSwiftError.encodingError(urlString: urlString)) } } else { failure?(OAuthSwiftError.encodingError(urlString: credential.oauthToken)) //TODO specific error } }, failure: failure) return self } @discardableResult open func authorize(withCallbackURL urlString: String, success: @escaping TokenSuccessHandler, failure: FailureHandler?) -> OAuthSwiftRequestHandle? { guard let url = URL(string: urlString) else { failure?(OAuthSwiftError.encodingError(urlString: urlString)) return nil } return authorize(withCallbackURL: url, success: success, failure: failure) } // 1. Request token func postOAuthRequestToken(callbackURL: URL, success: @escaping TokenSuccessHandler, failure: FailureHandler?) { var parameters = [String: Any]() parameters["oauth_callback"] = callbackURL.absoluteString if let handle = self.client.post( self.requestTokenUrl, parameters: parameters, success: { [weak self] response in guard let this = self else { OAuthSwift.retainError(failure); return } let parameters = response.string?.parametersFromQueryString ?? [:] if let oauthToken = parameters["oauth_token"] { this.client.credential.oauthToken = oauthToken.safeStringByRemovingPercentEncoding } if let oauthTokenSecret=parameters["oauth_token_secret"] { this.client.credential.oauthTokenSecret = oauthTokenSecret.safeStringByRemovingPercentEncoding } success(this.client.credential, response, parameters) }, failure: failure ) { self.putHandle(handle, withKey: UUID().uuidString) } } // 3. Get Access token func postOAuthAccessTokenWithRequestToken(success: @escaping TokenSuccessHandler, failure: FailureHandler?) { var parameters = [String: Any]() parameters["oauth_token"] = self.client.credential.oauthToken if !self.allowMissingOAuthVerifier { parameters["oauth_verifier"] = self.client.credential.oauthVerifier } if let handle = self.client.post( self.accessTokenUrl, parameters: parameters, success: { [weak self] response in guard let this = self else { OAuthSwift.retainError(failure); return } let parameters = response.string?.parametersFromQueryString ?? [:] if let oauthToken = parameters["oauth_token"] { this.client.credential.oauthToken = oauthToken.safeStringByRemovingPercentEncoding } if let oauthTokenSecret = parameters["oauth_token_secret"] { this.client.credential.oauthTokenSecret = oauthTokenSecret.safeStringByRemovingPercentEncoding } success(this.client.credential, response, parameters) }, failure: failure ) { self.putHandle(handle, withKey: UUID().uuidString) } } }