Skip to content

Instantly share code, notes, and snippets.

struct TokenCredentials {
let accessToken: String
let accessTokenSecret: String
}
func oAuthAccessTokenPublisher(temporaryCredentials: TemporaryCredentials, verifier: String) -> AnyPublisher<(TokenCredentials, User), OAuthError> {
// 1
let request = (baseURLString: "https://api.twitter.com/oauth/access_token",
httpMethod: "POST",
consumerKey: ClientCredentials.APIKey,
consumerSecret: ClientCredentials.APIKeySecret)
// 2
guard let baseURL = URL(string: request.baseURLString) else {
return Fail(error: OAuthError.urlError(URLError(.badURL)))
private var subscriptions: [String: AnyCancellable] = [:] // 1
func authorize() {
// 2
guard !self.authorizationSheetIsPresented else { return }
self.authorizationSheetIsPresented = true
// 3
self.subscriptions["oAuthRequestTokenSubscriber"] =
self.oAuthRequestTokenPublisher()
import SwiftUI
struct ContentView: View {
@EnvironmentObject var twitterAPI: TwitterAPI // 1
var body: some View {
VStack {
if let screenName = twitterAPI.user?.screenName { // 2
Text("Welcome").font(.largeTitle)
Text(screenName).font(.largeTitle)
class TwitterAPI: NSObject, ObservableObject {
@Published var authorizationSheetIsPresented = false // 1
@Published var authorizationURL: URL? // 2
@Published var user: User? // 3
struct User {
let ID: String
let screenName: String
}
import SwiftUI
import SafariServices
struct SafariView: UIViewControllerRepresentable {
// 1
class SafariViewControllerWrapper: UIViewController {
// 2
private var safariViewController: SFSafariViewController?
// 3
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 {
struct TemporaryCredentials {
let requestToken: String
let requestTokenSecret: String
}
enum OAuthError: Error {
case unknown
case urlError(URLError)
case httpURLResponse(Int)
case cannotDecodeRawData
case cannotParseResponse
case unexpectedResponse
case failedToConfirmCallback
}
private func oAuthAuthorizationHeader(parameters: [URLQueryItem]) -> String {
var parameterComponents: [String] = []
for parameter in parameters {
let name = parameter.name.oAuthURLEncodedString
let value = parameter.value?.oAuthURLEncodedString ?? ""
parameterComponents.append("\(name)=\"\(value)\"")
}
return "OAuth " + parameterComponents.sorted().joined(separator: ", ")
}