Skip to content

Instantly share code, notes, and snippets.

@markvanwijnen
Last active March 8, 2021 16:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markvanwijnen/4b66de2f924527d5e4b338b85f01873e to your computer and use it in GitHub Desktop.
Save markvanwijnen/4b66de2f924527d5e4b338b85f01873e to your computer and use it in GitHub Desktop.
func oAuthRequestTokenPublisher() -> AnyPublisher<TemporaryCredentials, OAuthError> {
// 1
let request = (baseURLString: "https://api.twitter.com/oauth/request_token",
httpMethod: "POST",
consumerKey: ClientCredentials.APIKey,
consumerSecret: ClientCredentials.APIKeySecret,
callbackURLString: "\(ClientCredentials.CallbackURLScheme)://")
// 2
guard let baseURL = URL(string: request.baseURLString) else {
return Fail(error: OAuthError.urlError(URLError(.badURL)))
.eraseToAnyPublisher()
}
// 3
var parameters = [
URLQueryItem(name: "oauth_callback", value: request.callbackURLString),
URLQueryItem(name: "oauth_consumer_key", value: request.consumerKey),
URLQueryItem(name: "oauth_nonce", value: UUID().uuidString),
URLQueryItem(name: "oauth_signature_method", value: "HMAC-SHA1"),
URLQueryItem(name: "oauth_timestamp", value: String(Int(Date().timeIntervalSince1970))),
URLQueryItem(name: "oauth_version", value: "1.0")
]
// 4
let signature = oAuthSignature(httpMethod: request.httpMethod,
baseURLString: request.baseURLString,
parameters: parameters,
consumerSecret: request.consumerSecret)
// 5
parameters.append(URLQueryItem(name: "oauth_signature", value: signature))
// 6
var urlRequest = URLRequest(url: baseURL)
urlRequest.httpMethod = request.httpMethod
urlRequest.setValue(oAuthAuthorizationHeader(parameters: parameters),
forHTTPHeaderField: "Authorization")
return
//7
URLSession.shared.dataTaskPublisher(for: urlRequest)
// 8
.tryMap { data, response -> TemporaryCredentials in
// 9
guard let response = response as? HTTPURLResponse
else { throw OAuthError.unknown }
// 10
guard response.statusCode == 200
else { throw OAuthError.httpURLResponse(response.statusCode) }
// 11
guard let parameterString = String(data: data, encoding: .utf8)
else { throw OAuthError.cannotDecodeRawData }
// 12
if let parameters = parameterString.urlQueryItems {
// 13
guard let oAuthToken = parameters["oauth_token"],
let oAuthTokenSecret = parameters["oauth_token_secret"],
let oAuthCallbackConfirmed = parameters["oauth_callback_confirmed"]
else {
throw OAuthError.unexpectedResponse
}
// 14
if oAuthCallbackConfirmed != "true" {
throw OAuthError.failedToConfirmCallback
}
// 15
return TemporaryCredentials(requestToken: oAuthToken,
requestTokenSecret: oAuthTokenSecret)
} else {
throw OAuthError.cannotParseResponse
}
}
// 16
.mapError { error -> OAuthError in
switch (error) {
case let oAuthError as OAuthError:
return oAuthError
default:
return OAuthError.unknown
}
}
// 17
.eraseToAnyPublisher()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment