Swift based OAuth library for iOS

Last update: May 21, 2022

OAuthSwift

OAuthSwift

Swift based OAuth library for iOS and macOS.

Support OAuth1.0, OAuth2.0

Twitter, Flickr, Github, Instagram, Foursquare, Fitbit, Withings, Linkedin, Dropbox, Dribbble, Salesforce, BitBucket, GoogleDrive, Smugmug, Intuit, Zaim, Tumblr, Slack, Uber, Gitter, Facebook, Spotify, Typetalk, SoundCloud, Twitch, Reddit, etc

Installation

OAuthSwift is packaged as a Swift framework. Currently this is the simplest way to add it to your app:

  • Drag OAuthSwift.xcodeproj to your project in the Project Navigator.
  • Select your project and then your app target. Open the Build Phases panel.
  • Expand the Target Dependencies group, and add OAuthSwift framework.
  • import OAuthSwift whenever you want to use OAuthSwift.

Support Carthage

github "OAuthSwift/OAuthSwift" ~> 2.2.0
  • Run carthage update.
  • On your application targets’ “General” settings tab, in the “Embedded Binaries” section, drag and drop OAuthSwift.framework from the Carthage/Build/iOS folder on disk.

Support CocoaPods

  • Podfile
platform :ios, '10.0'
use_frameworks!

pod 'OAuthSwift', '~> 2.2.0'

Swift Package Manager Support

import PackageDescription

let package = Package(
    name: "MyApp",
    dependencies: [
        .package(name: "OAuthSwift",
            url: "https://github.com/OAuthSwift/OAuthSwift.git",
            .upToNextMajor(from: "2.2.0"))
    ]
)

Old versions

Swift 3

Use the swift3 branch, or the tag 1.1.2 on main branch

Swift 4

Use the tag 1.2.0 on main branch

Objective-C

Use the tag 1.4.1 on main branch

How to

Setting URL Schemes

In info tab of your target Image Replace oauth-swift by your application name

Handle URL in AppDelegate

  • On iOS implement UIApplicationDelegate method
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey  : Any] = [:]) -> Bool {
  if url.host == "oauth-callback" {
    OAuthSwift.handle(url: url)
  }
  return true
}
  • On iOS 13, UIKit will notify UISceneDelegate instead of UIApplicationDelegate.
  • Implement UISceneDelegate method
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        guard let url = URLContexts.first?.url else {
            return
        }
        if url.host == "oauth-callback" {
            OAuthSwift.handle(url: url)
        }
}

⚠️ Any other application may try to open a URL with your url scheme. So you can check the source application, for instance for safari controller :

if options[.sourceApplication] as? String == "com.apple.SafariViewService" {
  • On macOS you must register a handler on NSAppleEventManager for event type kAEGetURL (see demo code)
func applicationDidFinishLaunching(_ aNotification: NSNotification) {
    NSAppleEventManager.shared().setEventHandler(self, andSelector:#selector(AppDelegate.handleGetURL(event:withReplyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL))
}
func handleGetURL(event: NSAppleEventDescriptor!, withReplyEvent: NSAppleEventDescriptor!) {
    if let urlString = event.paramDescriptor(forKeyword: AEKeyword(keyDirectObject))?.stringValue, let url = URL(string: urlString) {
        OAuthSwift.handle(url: url)
    }
}

Authorize with OAuth1.0

// create an instance and retain it
oauthswift = OAuth1Swift(
    consumerKey:    "********",
    consumerSecret: "********",
    requestTokenUrl: "https://api.twitter.com/oauth/request_token",
    authorizeUrl:    "https://api.twitter.com/oauth/authorize",
    accessTokenUrl:  "https://api.twitter.com/oauth/access_token"
)
// authorize
let handle = oauthswift.authorize(
    withCallbackURL: "oauth-swift://oauth-callback/twitter") { result in
    switch result {
    case .success(let (credential, response, parameters)):
      print(credential.oauthToken)
      print(credential.oauthTokenSecret)
      print(parameters["user_id"])
      // Do your request
    case .failure(let error):
      print(error.localizedDescription)
    }             
}

OAuth1 without authorization

No urls to specify here

// create an instance and retain it
oauthswift = OAuth1Swift(
    consumerKey:    "********",
    consumerSecret: "********"
)
// do your HTTP request without authorize
oauthswift.client.get("https://api.example.com/foo/bar") { result in
    switch result {
    case .success(let response):
        //....
    case .failure(let error):
        //...
    }
}

Authorize with OAuth2.0

// create an instance and retain it
oauthswift = OAuth2Swift(
    consumerKey:    "********",
    consumerSecret: "********",
    authorizeUrl:   "https://api.instagram.com/oauth/authorize",
    responseType:   "token"
)
let handle = oauthswift.authorize(
    withCallbackURL: "oauth-swift://oauth-callback/instagram",
    scope: "likes+comments", state:"INSTAGRAM") { result in
    switch result {
    case .success(let (credential, response, parameters)):
      print(credential.oauthToken)
      // Do your request
    case .failure(let error):
      print(error.localizedDescription)
    }
}

Authorize with OAuth2.0 and proof key flow (PKCE)

// create an instance and retain it
oauthswift = OAuth2Swift(
    consumerKey:    "********",
    consumerSecret: "********",
    authorizeUrl: "https://server.com/oauth/authorize",
    responseType: "code"
)
oauthswift.accessTokenBasicAuthentification = true

guard let codeVerifier = generateCodeVerifier() else {return}
guard let codeChallenge = generateCodeChallenge(codeVerifier: codeVerifier) else {return}

let handle = oauthswift.authorize(
    withCallbackURL: "myApp://callback/",
    scope: "requestedScope", 
    state:"State01",
    codeChallenge: codeChallenge,
    codeChallengeMethod: "S256",
    codeVerifier: codeVerifier) { result in
    switch result {
    case .success(let (credential, response, parameters)):
      print(credential.oauthToken)
      // Do your request
    case .failure(let error):
      print(error.localizedDescription)
    }
}

See demo for more examples

Handle authorize URL

The authorize URL allows the user to connect to a provider and give access to your application.

By default this URL is opened into the external web browser (ie. safari), but apple does not allow it for app-store iOS applications.

To change this behavior you must set an OAuthSwiftURLHandlerType, simple protocol to handle an URL

oauthswift.authorizeURLHandler = ..

For instance you can embed a web view into your application by providing a controller that displays a web view (UIWebView, WKWebView). Then this controller must implement OAuthSwiftURLHandlerType to load the URL into the web view

func handle(_ url: NSURL) {
  let req = URLRequest(URL: targetURL)
  self.webView.loadRequest(req)
  ...

and present the view (present(viewController, performSegue(withIdentifier: , ...) You can extend OAuthWebViewController for a default implementation of view presentation and dismiss

Use the SFSafariViewController (iOS9)

A default implementation of OAuthSwiftURLHandlerType is provided using the SFSafariViewController, with automatic view dismiss.

oauthswift.authorizeURLHandler = SafariURLHandler(viewController: self, oauthSwift: oauthswift)

Of course you can create your own class or customize the controller by setting the variable SafariURLHandler#factory.

Make signed request

Just call HTTP functions of oauthswift.client

oauthswift.client.get("https://api.linkedin.com/v1/people/~") { result in
    switch result {
    case .success(let response):
        let dataString = response.string
        print(dataString)
    case .failure(let error):
        print(error)
    }
}
// same with request method
oauthswift.client.request("https://api.linkedin.com/v1/people/~", .GET,
      parameters: [:], headers: [:],
      completionHandler: { ...

See more examples in the demo application: ViewController.swift

OAuth provider pages

Images

Image Image Image

Contributing

See CONTRIBUTING.md

Add a new service in demo app

Integration

OAuthSwift could be used with others frameworks

You can sign Alamofire request with OAuthSwiftAlamofire

To achieve great asynchronous code you can use one of these integration frameworks

License

OAuthSwift is available under the MIT license. See the LICENSE file for more info.

License Platform Language Cocoapod Carthage compatible Build Status

GitHub

https://github.com/OAuthSwift/OAuthSwift
Comments
  • 1. Uber Authentication failed "HTTP Status 401: Unauthorized, Response: {"error": "invalid_client"}"

    i am using this library for Uber Authetication https://developer.uber.com/v1/auth/

    I have done like this

    func doOAuthUber(){

        let oauthswift = OAuth2Swift(
            consumerKey:    "fXfXXXXXXXUo9vtKzobXXXXXUDO",
            consumerSecret: "e5XXXXXXXq2w63qz9szEx7uXXXXXXo03W",
            authorizeUrl:   "https://login.uber.com/oauth/authorize",
            accessTokenUrl: "https://login.uber.com/oauth/token",
            responseType:   "code"
        )
    
        var originalString = "jamesappv2://oauth/callback"
        var encodedCallBackUrl = originalString.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())
    
        println("encodedCallBackUrl: \(encodedCallBackUrl)")
    
    
        let state: String = ""
        oauthswift.authorizeWithCallbackURL( NSURL(string: encodedCallBackUrl!)!, scope: "request%20history", state: state, success: {
            credential, response in
    
            println(credential.oauth_token)
            self.personalDriverLoader.stopAnimating()
    
    
    
            }, failure: {(error:NSError!) -> Void in
    
                self.personalDriverLoader.stopAnimating()
                println(error.localizedDescription)
        })
    
    
    }
    

    but getting this response HTTP Status 401: Unauthorized, Response: {"error": "invalid_client"}

    I have triple checked that my client_id (consumerKey) and secret (consumerSecret) are correct. What I have done wrong here

    Please help

    Reviewed by alikazim at 2015-05-06 09:39
  • 2. Error in signature calculation

    I ccompared with that web site : http://oauth.googlecode.com/svn/code/javascript/example/signature.html

    the signature calculated in OAuthSwiftClient, authorizationHeaderForMethod give wrong value. this imply that on some web site, upload fail. here is something I did, which works.

    hope this help. Olivier

    // convert a Dictionary, in array of string, with escaped string
    func getEscapedArrayParam(parameters: Dictionary<String, AnyObject>) -> [String] {
        // escape all oauth parameter
        var encodedParam = [String]()
        for(k, v) in parameters {
            let str = k + "=" + (v as! String)
            let escapedStr = str.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())
            encodedParam.append(escapedStr!)
        }
        // sort the result
        encodedParam.sortInPlace{ $0 < $1 }
        return encodedParam
    }
    
    // do almost like stringByAddingPercentEncodingWithAllowedCharacters, but take in account more character to be changed in %xyz
    //!*'();:@&=+$,/?%#[]
    func escapeString(str: String) -> String {
        let encoding: NSStringEncoding = NSUTF8StringEncoding
        // !*'();:@&=+$,/?%#[]
        let charactersToBeEscaped = ":/?&=;[email protected]#$()',*" as CFStringRef
        let charactersToLeaveUnescaped = "[]." as CFStringRef
        let raw: NSString = str
        let result = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, raw, charactersToLeaveUnescaped, charactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding))
        return result as String
    }
    
    
    public func encodeParameters(method: String, url: NSURL, parameters: Dictionary<String, AnyObject>, credential: OAuthSwiftCredential) -> String {
    
        // algorithm used : https://dev.twitter.com/oauth/overview/creating-signatures
        // will add the oauth_signature parameter
    
        //define the oauth parameters
        var authorizationParameters = Dictionary<String, AnyObject>()
        authorizationParameters["oauth_version"] = OAuth.version
        authorizationParameters["oauth_consumer_key"] = credential.consumer_key
        authorizationParameters["oauth_timestamp"] = String(Int64(NSDate().timeIntervalSince1970))
        authorizationParameters["oauth_nonce"] = (NSUUID().UUIDString as NSString).substringToIndex(8)
        authorizationParameters["oauth_signature_method"] =  OAuth.signatureMethod
        // add token is it exist
        if (credential.oauth_token != ""){
            authorizationParameters["oauth_token"] = credential.oauth_token
        }
        // add additionnal oauth (optionnal) parameters if not already existing
        // example, oauth_callback, defined when requesting the token
        for (key, value) in parameters {
            if key.hasPrefix("oauth_") {
                authorizationParameters.updateValue(value, forKey: key)
            }
        }
    
        // escape all oauth parameter
        let encodedParam = getEscapedArrayParam(authorizationParameters)
        // convert it into a string, each param separated by &
        var outputStr:String = ""
        for v in encodedParam {
            outputStr += v + "&"
        }
        // remove last "&"
        outputStr.removeAtIndex(outputStr.endIndex.predecessor())
        // percent encode the oauth sorted, appened, parameters
        let percentOutput = self.escapeString(outputStr)
    
        // build the signature base string
        let urlPercented = self.escapeString(String(url)) //  String(url).stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())
        var signBaseString:String = method + "&" + urlPercented
        signBaseString += "&" + percentOutput
    
        // build the signin key
        let signingKey = self.escapeString( credential.consumer_secret) + "&" + self.escapeString(credential.oauth_token_secret)
    
        // Build the signature
        let sha1 = HMAC.sha1(key: signingKey.dataUsingEncoding(NSUTF8StringEncoding)!, message: signBaseString.dataUsingEncoding(NSUTF8StringEncoding)!)!
        let oauth_signature = sha1.base64EncodedStringWithOptions([])
        authorizationParameters.updateValue(self.escapeString( oauth_signature) , forKey: "oauth_signature")
    
        // add the signature to the parameters
        //encodedParam.append("oauth_signature=" + oauth_signature )
        //encodedParam.sortInPlace{ $0 < $1 } // not sure it is useful r not
    
        // create an array, with escape before =
        var headerComponents = [String]()
        for (key, value) in authorizationParameters {
            headerComponents.append("\(key)=\"\(value)\"")
        }
    
        let finalUrl:String =  "OAuth " + headerComponents.joinWithSeparator(", ")
        return finalUrl
    }
    
    Reviewed by olivier38070 at 2015-09-29 07:44
  • 3. Instagram login issue

    Hi,

    I'm trying to make Instagram login. There is my code : • Instagram Manager

    import UIKit
    import OAuthSwift
    
    class GFInstagramManager: NSObject {
        static let shared = GFInstagramManager()
    
        var oauthswift: OAuthSwift?
    
        func login() {
            let oauthswift = OAuth2Swift(
                consumerKey:    "****...",
                consumerSecret: "****...",
                authorizeUrl:   "https://api.instagram.com/oauth/authorize",
                responseType:   "token"
            )
            oauthswift.authorizeWithCallbackURL(
                NSURL(string: "http://oauthswift.herokuapp.com/callback/instagram")!,
                scope: "likes+comments", state:"INSTAGRAM",
                success: { credential, response, parameters in
                    print(response.debugDescription)
                    print(credential.oauth_token)
                },
                failure: { error in
                    print(error.localizedDescription)
                }
            )
        }
        func testInstagram(oauthswift: OAuth2Swift) {
            let url :String = "https://api.instagram.com/v1/users/1574083/?access_token=\(oauthswift.client.credential.oauth_token)"
            let parameters :Dictionary = Dictionary<String, AnyObject>()
            oauthswift.client.get(url, parameters: parameters,
                                  success: {
                                    data, response in
                                    let jsonDict: AnyObject! = try? NSJSONSerialization.JSONObjectWithData(data, options: [])
                                    print(jsonDict)
    
                }, failure: { error in
                    print(error)
            })
        }
    }
    

    • ApplicationDelegate

        func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
            applicationHandleOpenURL(url)
            return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
        }
    
        @available(iOS 9.0, *)
        func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool
        {
            applicationHandleOpenURL(url)
            FBSDKApplicationDelegate.sharedInstance().application(app, openURL: url, sourceApplication: options["UIApplicationOpenURLOptionsSourceApplicationKey"] as! String, annotation: options["UIApplicationOpenURLOptionsAnnotationKey"])
            return true
        }
    
    // MARK: handle callback url
    extension AppDelegate {
    
        func applicationHandleOpenURL(url: NSURL) {
            if (url.host == "oauth-callback") {
                print("PASSS1")
                OAuthSwift.handleOpenURL(url)
                print("PASSS2")
            } else {
                // Google provider is the only one wuth your.bundle.id url schema.
                OAuthSwift.handleOpenURL(url)
            }
        }
    }
    

    • URL Types

    capture d ecran 2016-08-05 a 16 51 20

    Login are done, but when the login view disappear my callback pass in error with "No access_token, no code and no error provided by server"

    My Instagram URL/ call back url is "http://oauthswift.herokuapp.com/callback/instagram"... I don't know if it's the good way.. (my consumer et secret key work on our Android app)

    Anyone have idea ?

    • OS targeted (with version): 8.0
    • OAuth provider: Instagram
    • OAuthSwift version: Master 0.5.0'
    Reviewed by floriangbh at 2016-08-05 14:54
  • 4. Retain Error

    switch error {

            case OAuthSwiftError.tokenExpired:
                _ = self.renewAccessToken(withRefreshToken: self.client.credential.oauthRefreshToken, headers: renewHeaders ?? headers, success: { (credential, _, _) in
                    // Ommit response parameters so they don't override the original ones
                    // We have successfully renewed the access token.
    
                    // If provided, fire the onRenewal closure
                    if let renewalCallBack = onTokenRenewal {
                        renewalCallBack(credential)
                    }
    

    in this function when error is tokenExpired it goes into renewAccessToken function but self.client.credential.oauthRefreshToken = "".Please Help

    Reviewed by sandeepk000 at 2019-03-05 15:25
  • 5. WordPress OAuth1 returns "No OAuth parameters supplied"

    Description:

    I'm running OAuth1 against wordpress but receiving 400 error code: "No OAuth parameters supplied"

    requestError[Error Domain=NSURLErrorDomain Code=400 "HTTP Status 400: Bad Request, Response: No OAuth parameters supplied" UserInfo={NSErrorFailingURLKey=http://example.us/oauth1/request, NSLocalizedDescription=HTTP Status 400: Bad Request, Response: No OAuth parameters supplied, Response-Headers={
        "Access-Control-Allow-Headers" = Authorization;
        Connection = "keep-alive";
        "Content-Type" = "text/html; charset=UTF-8";
        Date = "Sat, 05 Nov 2016 14:13:54 GMT";
        "Keep-Alive" = "timeout=15";
        Server = nginx;
        "Transfer-Encoding" = Identity;
    }, OAuthSwiftError.response=<NSHTTPURLResponse: 0x600000032320> { URL: http://example.us/oauth1/request } { status code: 400, headers {
        "Access-Control-Allow-Headers" = Authorization;
        Connection = "keep-alive";
        "Content-Type" = "text/html; charset=UTF-8";
        Date = "Sat, 05 Nov 2016 14:13:54 GMT";
        "Keep-Alive" = "timeout=15";
        Server = nginx;
        "Transfer-Encoding" = Identity;
    } }, OAuthSwiftError.response.data=<4e6f204f 41757468 20706172 616d6574 65727320 73757070 6c696564>, Response-Body=No OAuth parameters supplied}]
    

    Here is the test functions:

    class ViewController: OAuthViewController {
        
        // oauth swift object (retain)
        var oauthswift: OAuthSwift?
    
        lazy var internalWebViewController: WebViewController = {
            let controller = WebViewController()
            controller.view = UIView(frame: UIScreen.main.bounds) // needed if no nib or not loaded from storyboard
            controller.delegate = self
            controller.viewDidLoad() // allow WebViewController to use this ViewController as parent to be presented
            return controller
        }() 
    }
    
    extension ViewController {
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            // init now web view handler
            let _ = internalWebViewController.webView
            
            self.navigationItem.title = "OAuth"
            let tableView: UITableView = UITableView(frame: self.view.bounds, style: .plain)
            tableView.delegate = self
            tableView.dataSource = self
            self.view.addSubview(tableView)
            
            self.doOAuthWordpress()
        }
        
        // MARK: Fitbit
        func doOAuthWordpress(){
            let oauthswift = OAuth1Swift(
                consumerKey:    "xxx", // Hard coded for now
                consumerSecret: "yyy", // Hard coded for now
                requestTokenUrl: "http://example.us/oauth1/request",
                authorizeUrl:    "http://example.us/oauth1/authorize",
                accessTokenUrl:  "http://example.us/oauth1/access"
            )
            
            self.oauthswift = oauthswift
            oauthswift.authorizeURLHandler = getURLHandler()
            
            let _ = oauthswift.authorize(
                withCallbackURL: URL(string: "oauth-swift://oauth-callback/wordpress")!,
                success: { credential, response, parameters in
                    self.showTokenAlert(name: "WPTesting", credential: credential)
                },
                failure: { error in
                    print(error.description)
                }
            )
        }
        
        // MARK: handler
        
        func getURLHandler() -> OAuthSwiftURLHandlerType {
            if internalWebViewController.parent == nil {
                self.addChildViewController(internalWebViewController)
            }
            return internalWebViewController
        }
        
        func showTokenAlert(name: String?, credential: OAuthSwiftCredential) {
            var message = "oauth_token:\(credential.oauthToken)"
            if !credential.oauthTokenSecret.isEmpty {
                message += "\n\noauth_toke_secret:\(credential.oauthTokenSecret)"
            }
            self.showAlertView(title: name ?? "Service", message: message)
            
        }
        
        func showAlertView(title: String, message: String) {
            let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
            alert.addAction(UIAlertAction(title: "Close", style: UIAlertActionStyle.default, handler: nil))
            self.present(alert, animated: true, completion: nil)
        }
        
    }
    
    

    OAuth Provider (WordPress):

    WP REST API - OAuth 1.0a Server

    OAuth Version:

    • [x] Version 1
    • [ ] Version 2

    OS (Please fill the version) :

    • [x] iOS :
    • [ ] OSX :
    • [ ] TVOS :
    • [ ] WatchOS :

    Installation method:

    • [ ] Carthage
    • [ ] CocoaPods
    • [x] Manually

    Library version:

    • [ ] head
    • [x] v1.0.0
    • [ ] v0.6
    • [ ] other: (Please fill in the version you are using.)

    Xcode version:

    • [ ] 8.0 (Swift 3.0)

    • [ ] 8.0 (Swift 2.3)

    • [ ] 7.3.1

    • [x] other: (8.1)

    • [ ] objective c

    Reviewed by phamdacloc at 2016-11-05 14:54
  • 6. XCode8 + Cocoapods 1.1.0.rc.2 + objective-c based

    Hi there,

    I'm having trouble building our project after upgrading to XCode8 and Cocoapods 1.1.0.rc.2. Our project is objective-c based and everything was working fine until today. Basically I'm seeing 76 errors in the Pod when it tries to build it.

    We are currently importing OAuthSwift using @import OAuthSwift statement. I've tried to switch that to #import "OAuthSwift-swift.h" but there issues are still there. Kind of makes sense as it isn't actually able to build the pod.

    A lot of the issues appear to be related to syntax error which leads me to believe it is something to do with Swift 3 or 2.3 updates. I'm not up on Swift yet but an example error is "Expected 'let' in conditional"

    Our Podfile.lock file shows that we are using OAuthSwift 0.6.0

    Any ideas?

    Reviewed by ikbenben at 2016-09-26 21:53
  • 7. [WIP] Compatibility with Swift 3.0 (up to Xcode 8 GM)

    This includes both changes suggested by Xcode's migration tool as well as manual fixing of the issues that Xcode couldn't migrate.

    Action list:

    • [ ] Double-check Int+OAuthSwift.swift
    • [ ] Code review
    • [ ] Squash commits
    • [x] Get tests to work again
    • [x] Fix test failures
    Reviewed by nighthawk at 2016-08-17 06:17
  • 8. Automatically refresh access tokens in OAuthSwiftClient

    Summary

    Access tokens have an expiration date but OAuthSwift doesn't automatically refresh access tokens by default.

    This PR proposes a solution:

    • that makes OAuthSwift automatically refresh access tokens when they expire
    • which is opt-in by providing one simple convenient method
    • containing the minimum amount of changes needed to avoid to break existing apps

    Related links:

    • Issue #217
    • PR #209

    Changes:

    • Add a new function requestWithAutomaticAccessTokenRenewal in OAuthSwiftClient. When used, it automatically refreshes the access token if it expired and restart the query.
    • Move the implementation for renewAccessToken and requestOAuthAccessToken from OAuth2Swift to OAuthSwiftClient. The methods renewAccessToken and requestOAuthAccessToken are still available in OAuth2Swift but they simply forward the call to OAuthSwiftClient to ensure that old apps don't need to be changed.

    Why?

    I developed an application, called Clatters, that needs to access various services relying on OAuth. Rather that creating my own OAuth library, I decided to use OAuthSwift as it perfectly fit my needs.

    However I believe that OAuthSwift should automatically refresh access tokens when they expire. The app itself shouldn't have to implement the logic to handle expired token.

    Clatters has been available in the iOS App Store since February 2020 and relies on the code written in this PR.

    Usage

    You can call the convenient method requestWithAutomaticAccessTokenRenewal in OAuthSwiftClient with the correct parameters. If the access token expired, requestWithAutomaticAccessTokenRenewal will automatically renew the access token and retry the query. Here is an example to perform a query on Reddit:

    static func requestIdentity(client: OAuthSwiftClient) {
    		client.requestWithAutomaticAccessTokenRenewal(url: URL(string: "https://oauth.reddit.com/api/v1/me")!, method: .GET, headers: nil, contentType: nil, accessTokenBasicAuthentification: true, accessTokenUrl: "https://www.reddit.com/api/v1/access_token", onTokenRenewal: nil) { (result) in
    			switch result {
    				case .success(let response):
    					// Do something
    					debugPrint("Received \(response)")
    					break
    				case .failure:
    					// Fail nicely
    					break
    			}
    		}
        }
    

    Notes

    I wanted to keep the changes proposed in this PR really simple. As previously mentioned:

    • this new feature is opt-in by using a convenient method.
    • apps already using OAuthSwift shouldn't be affected and don't need to adopt the new API.
    • no code has been removed or deprecated.
    Reviewed by Timac at 2020-05-12 20:19
  • 9. Modify webview

    Guys, i know this is probably a lame question, but.. How can i modify de webview ? In my app i have everyrhing under a navigation crontoller, when login in with the oauthswift , i get ro this plain blank uiviewcontroller in blank, it takes the whole screen .. I get instagram textfields and interface almost overlapoing the status bar. I would like to get that webview viewconteoller inside of my navigstion controller etc

    Reviewed by hopye at 2015-05-11 18:35
  • 10. 👥 Add contributor: phatblat

    Greetings! My team has started using this fabulous library in our inner-source auth library which will be used in 6 (and probably more) of our company's public iOS apps. We are using PingFederate as our OAuth server.

    I have noticed that there are two new GitHub releases (2.1.1 & 2.1.2) that have been tagged but not yet released to CocoaPods trunk. Version 2.1.0 is the latest that shows up on CocoaPods.

    -> OAuthSwift (2.1.0)
       Swift based OAuth library for iOS and macOS.
       pod 'OAuthSwift', '~> 2.1.0'
       - Homepage: https://github.com/OAuthSwift/OAuthSwift
       - Source:   https://github.com/OAuthSwift/OAuthSwift.git
       - Versions: 2.1.0, 2.0.0, 1.4.1, 1.4.0, 1.3.0, 1.2.2, 1.2.0, 1.1.2, 1.1.1, 1.1.0, 1.0.0, 0.6.0, 0.5.2, 0.5.1, 0.5.0, 0.4.8, 0.4.6, 0.4.5, 0.4.4, 0.4.3,
       0.3.7, 0.3.6, 0.3.5, 0.3.4, 0.3.3, 0.3.2, 0.3.1, 0.3.0, 0.2.1, 0.2.0, 0.1.9, 0.1.2, 0.1.1, 0.1.0 [cocoapods repo]
    

    I would like to help out with publishing these and future releases to CocoaPods. I just need @phimage or @dongri to run the following command to add me as an owner of this pod.

    pod trunk add-owner OAuthSwift [email protected]
    

    Note that all CocoaPods trunk session keys have been wiped due to a recent trunk vulnerability, so you'll probably need to authenticate again with pod trunk register.

    I have lots of experience publishing libraries to CocoaPods trunk and also publish our own 20+ internal iOS libraries to a private repo.

    ↪ pod trunk me
      - Name:     Ben Chatelain
      - Email:    [email protected]
      - Since:    August 31st, 2015 19:47
      - Pods:
        - ObjectiveGit
        - libgit2
        - Nimble
        - Fetchable
        - BlueDot
        - Quick
        - RBQFetchedResultsController
        - ABFRealmMapView
        - RBQSafeRealmObject
        - SafeRealmObject
        - SwiftFetchedResultsController
        - RealmMapView
        - Outlets
        - Commandant
    

    I can also help out with issue triage and PR review if you would be open to adding me as a contributor on this repo.

    Reviewed by phatblat at 2021-04-27 21:20
  • 11. Set OAuthSwift pod version to 2.1.3

    This updates OAuthSwift version in OAuthSwift.podspec to 2.1.3, assuming this is the version to be used for the upcoming release.

    OAuthSwift 2.1.2 has been already released and tagged, but since it was marked as 2.1.0 in podspec (https://github.com/OAuthSwift/OAuthSwift/blob/2.1.2/OAuthSwift.podspec) it can not now be used with CocoaPods. This can't be resolved without altering the tag, but, going forward, this commit ensures that upcoming 2.1.3 is going to have the right version in the OAuthSwift.podspec file and can be then published on CocoaPods.

    Relates to issue: https://github.com/OAuthSwift/OAuthSwift/issues/615

    Reviewed by vgritsenko at 2020-08-14 18:29
  • 12. Dispatch network activity changes on main thread

    This change ensures that isNetworkActivityIndicatorVisible is always called on the main thread, even when the execution context has been switched to another queue.

    Besides, the OAUTH_APP_EXTENSIONS build flag is of no use when being used as a swift package. At least I wasn't able to get this flag to be set.

    Reviewed by cmittendorf at 2022-04-29 11:09
  • 13. Improvements to `requestWithAutomaticAccessTokenRenewal`

    This fixes error handling, and makes a couple of improvements to implementation of the requestWithAutomaticAccessTokenRenewal function:

    • Pass all error responses as-is, and look only for the tokenExpired;
    • Treat onTokenRenewal parameter as truly optional - perform the token renewal even if onTokenRenewal is nil;
    • Do not keep a strong reference to self in the completion block for renewAccessToken call.

    The main issue I had was that requestWithAutomaticAccessTokenRenewal would swallow all errors and convert them to the empty tokenExpired errors, preventing any possibility of implementing custom error handling logic on the client side:

    completion(.failure(.tokenExpired(error: nil)))
    
    Reviewed by vgritsenko at 2022-01-31 14:43
  • 14. Twitch Dev URL Scheme Issue

    Description:

    I want to use the twitch login option but I can't add a URL scheme on the Twitch Dev portal. So, how can I get data without CallbackURL?

    image

    OAuth Provider? (Twitter, Github, ..):

    Twitch

    OAuth Version:

    • [ ] Version 1
    • [x] Version 2

    OS (Please fill the version) :

    • [x] iOS :
    • [ ] OSX :
    • [ ] TVOS :
    • [ ] WatchOS :

    Installation method:

    • [ ] Carthage
    • [x] CocoaPods
    • [ ] Swift Package Manager
    • [ ] Manually

    Library version:

    • [ ] head
    • [x] v2.1.0
    • [ ] v2.0.0
    • [ ] v1.4.1
    • [ ] other: (Please fill in the version you are using.)

    Xcode version:

    • [ ] 11.4 (Swift 5.2)
    • [ ] 11.x (Swift 5.1)
    • [ ] 10.x (Swift 5.0)
    • [x] other: (Please fill in the version you are using.) 13.2.1
    • [ ] objective c
    Reviewed by halilyuce at 2022-01-31 00:30
  • 15. Small buttons after login on webview OAuth2

    Description:

    When I request a token, the webview shows me the login view to enter the user and password, but after that, it shows two really small buttons with "Allow" and "Deny". Any way to apply zoom to this two buttons on the webview, or I have to contact the people of marvelcdb.com to change that? Thanks in advance!

    OAuth Provider? (Twitter, Github, ..):

    marvelcdb.com

    OAuth Version:

    • [ ] Version 1
    • [X] Version 2

    OS (Please fill the version) :

    • [x] iOS :
    • [ ] OSX :
    • [ ] TVOS :
    • [ ] WatchOS :

    Installation method:

    • [ ] Carthage
    • [X] CocoaPods
    • [ ] Swift Package Manager
    • [ ] Manually

    Library version:

    • [X] head
    • [ ] v2.1.0
    • [ ] v2.0.0
    • [ ] v1.4.1
    • [ ] other: (Please fill in the version you are using.)

    Xcode version:

    • [X] 11.4 (Swift 5.2)

    • [ ] 11.x (Swift 5.1)

    • [ ] 10.x (Swift 5.0)

    • [ ] other: (Please fill in the version you are using.)

    • [ ] objective c

    Reviewed by socquique at 2022-01-21 12:54
  • 16. how can I send http request with url scheme?

    Description:

    how can I send http request with url scheme?

    I want to send a request "https://portal.tencentciam.com/logout?client_id=YjBiYzNU1YTI&logout_redirect_uri=ciam://oauth-callback/Ciam" , and if success the app will redirect to ciam://oauth-callback/Ciam and it is url scheme

    I used oauthswift.client to send request but I failed ,what can I do?

    Thanks for you reading,any suggestion appreciated.

    OAuth Provider? (Twitter, Github, ..):

    OAuth Version:

    • [ ] Version 1
    • [✔️ ] Version 2

    OS (Please fill the version) :

    • [✔️] iOS :
    • [ ] OSX :
    • [ ] TVOS :
    • [ ] WatchOS :

    Installation method:

    • [ ] Carthage
    • [✔️] CocoaPods
    • [ ] Swift Package Manager
    • [ ] Manually

    Library version:

    • [x] head
    • [ ] v2.1.0
    • [ ] v2.0.0
    • [ ] v1.4.1
    • [ ] other: (Please fill in the version you are using.)

    Xcode version:

    • [ ] 11.4 (Swift 5.2)
    • [ ] 11.x (Swift 5.1)
    • [ ] 10.x (Swift 5.0)
    • [✔️] other: (Please fill in the version you are using.) 13.2
    • [ ] objective c
    Reviewed by sakura-acm at 2022-01-17 08:31
A simple OAuth library for iOS with a built-in set of providers
A simple OAuth library for iOS with a built-in set of providers

SwiftyOAuth is a small OAuth library with a built-in set of providers and a nice API to add your owns. let instagram: Provider = .instagram(clientID:

Apr 10, 2022
A native, lightweight and secure time-based (TOTP) & counter-based (HOTP) password client built for iOS
A native, lightweight and secure time-based (TOTP) & counter-based (HOTP) password client built for iOS

A native, lightweight and secure time-based (TOTP) & counter-based (HOTP) password client built for iOS Built by Tijme Gommers – Buy me a coffee via P

May 20, 2022
A lightweight but powerful network library with simplified and expressive syntax based on AFNetworking.
A lightweight but powerful network library with simplified and expressive syntax based on AFNetworking.

XMNetworking English Document XMNetworking 是一个轻量的、简单易用但功能强大的网络库,基于 AFNetworking 3.0+ 封装。 其中,XM 前缀是我们团队 Xcode-Men 的缩写。 简介 如上图所示,XMNetworking 采用中心化的设计思想

May 1, 2022
A resource based, protocol oriented networking library designed for pure-SwiftUI applications.

Monarch ?? - WIP A resource based, protocol oriented networking library designed for pure-SwiftUI applications. Features: Async/Await Resource Based P

May 5, 2022
Swift-flows - Simplistic hot and cold flow-based reactive observer pattern for Swift… ideal for MVVM architectures

SwiftFlows Simplistic hot and cold flow-based reactive observer pattern for Swif

Feb 2, 2022
DNS tunnel for iOS based off of Iodine

Purple Haze A DNS tunnel client for iOS based on Iodine. A paid Apple Developer account is required to build because of the entitlements needed for Ne

Apr 25, 2022
Super lightweight web framework in Swift based on SWSGI

Ambassador Super lightweight web framework in Swift based on SWSGI Features Super lightweight Easy to use, designed for UI automatic testing API mocki

Mar 18, 2022
A simple GCD based HTTP client and server, written in 'pure' Swift
A simple GCD based HTTP client and server, written in 'pure' Swift

SwiftyHTTP Note: I'm probably not going to update this any further - If you need a Swift networking toolset for the server side, consider: Macro.swift

Jan 29, 2022
DispatchSource based socket framework written in pure Swift

SwiftDSSocket Overview SwiftDSSocket is a purely swift based asynchronous socket framework built atop DispatchSource. Function signatures are pretty m

Apr 24, 2022
Swift async/await based socket

Socket Swift async/await based socket library Introduction This library exposes an idiomatic Swift API for interacting with POSIX sockets via an async

Apr 25, 2022
SwiftCANLib is a library used to process Controller Area Network (CAN) frames utilizing the Linux kernel open source library SOCKETCAN.

SwiftCANLib SwiftCANLib is a library used to process Controller Area Network (CAN) frames utilizing the Linux kernel open source library SOCKETCAN. Th

Oct 25, 2021
Securely synchronize any CareKit 2.1+ based app to a Parse Server Cloud. Compatible with parse-hipaa.
Securely synchronize any CareKit 2.1+ based app to a Parse Server Cloud. Compatible with parse-hipaa.

ParseCareKit Use at your own risk. There is no promise that this is HIPAA compliant and we are not responsible for any mishandling of your data This f

May 13, 2022
A modern download manager based on NSURLSession to deal with asynchronous downloading, management and persistence of multiple files.
A modern download manager based on NSURLSession to deal with asynchronous downloading, management and persistence of multiple files.

TWRDownloadManager TWRDownloadManager A modern download manager for iOS (Objective C) based on NSURLSession to deal with asynchronous downloading, man

Apr 11, 2022
YTKNetwork is a high level request util based on AFNetworking.

YTKNetwork What YTKNetwork is a high level request util based on AFNetworking. It's developed by the iOS Team of YuanTiKu. It provides a High Level AP

May 19, 2022
Simple REST Client based on RxSwift and Alamofire.

RxRestClient Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements iOS 10.0+ tvOS 10.

Apr 18, 2022
An easy to integrate Model Based Google Maps Helper (SVHTTPClient, AFNetworking) That lets you Geo Code , Reverse Geocode, Get Directions , Places Autocomplete.

GoogleMapsHelper Read Me in Russian : http://gargo.of.by/googlemapshelper/ A GOOGLE MAPS Helper that help you do multiple tasks like HOW TO USE // usi

Feb 21, 2019
Simple REST Client based on RxSwift and Alamofire.

RxRestClient Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements iOS 10.0+ tvOS 10.

Apr 18, 2022
Super lightweight async HTTP server library in pure Swift runs in iOS / MacOS / Linux

Embassy Super lightweight async HTTP server in pure Swift. Please read: Embedded web server for iOS UI testing. See also: Our lightweight web framewor

May 15, 2022
NWReachability - a pure Swift library for monitoring the network connection of iOS devices using Apple's Network framework.

NWReachability is a pure Swift library for monitoring the network connection of iOS devices using Apple's Network framework.

Mar 4, 2022