Giter Club home page Giter Club logo

swiftyoauth's Introduction

Travis Status CocoaPods compatible Carthage compatible

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: "***", redirectURL: "foo://callback")

instagram.authorize { result in
    print(result) // success(Token(accessToken: "abc123"))
}

UsageProvidersInstallationLicense

Usage

Provider

Provider.swift

Step 1: Create a provider

Initialize a provider with the custom URL scheme that you defined:

// Provider using the server-side (explicit) flow

let provider = Provider(
    clientID:     "***",
    clientSecret: "***",
    authorizeURL: "https://example.com/authorize",
    tokenURL:     "https://example.com/authorize/token",
    redirectURL:  "foo://callback"
)

// Provider using the client-side (implicit) flow

let provider = Provider(
    clientID:     "***",
    authorizeURL: "https://example.com/authorize",
    redirectURL:  "foo://callback"
)

// Provider using the client-credentials flow

let provider = Provider(
    clientID:     "***",
    clientSecret: "***"
)

Alternatively, you can use one of the built-in providers:

let github = .gitHub(
    clientID:     "***",
    clientSecret: "***",
    redirectURL:  "foo://callback"
)

Optionally set the state and scopes properties:

github.state  = "asdfjkl;" // An random string used to protect against CSRF attacks.
github.scopes = ["user", "repo"]

Use a WKWebView if the provider doesn't support custom URL schemes as redirect URLs.

let provider = Provider(
    clientID:     "***",
    clientSecret: "***",
    authorizeURL: "https://example.com/authorize",
    tokenURL:     "https://example.com/authorize/token",
    redirectURL:  "https://an-arbitrary-redirect-url/redirect"
)

provider.useWebView = true

Define additional parameters for the authorization request or the token request with additionalAuthRequestParams and additionalTokenRequestParams respectively:

github.additionalAuthRequestParams["allow_signup"] = "false"
Step 2: Handle the incoming requests

Handle the incoming requests in your AppDelegate:

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    github.handleURL(url, options: options)

    return true
}
Step 3: Ask for authorization

Finally, ask for authorization. SwiftyOAuth will either present a SFSafariViewController (iOS 9) or open mobile safari.

github.authorize { (result: Result<Token, Error>) -> Void in
    switch result {
    case .success(let token): print(token)
    case .failure(let error): print(error)
    }
}

If the provider provides an expirable token, you may want to refresh it.

let uber: Provider = .uber(
    clientID: "***",
    clientSecret: "***",
    redirectURL: "foo://callback/uber"
)

// uber.token!.isExpired => true

uber.refreshToken { result in
    switch result {
    case .success(let token): print(token)
    case .failure(let error): print(error)
    }
}

Token

Token.swift

The access_token, token_type, scopes, and informations related to the expiration are available as Token properties:

token.accessToken // abc123
token.tokenType   // .Bearer
token.scopes      // ["user", "repo"]

token.expiresIn // 123
token.isExpired // false
token.isValid   // true

Additionally, you can access all the token data via the dictionary property:

token.dictionary // ["access_token": "abc123", "token_type": "bearer", "scope": "user repo"]

Token Store

Every Token is stored and retrieved through an object that conforms to the TokenStore protocol.

The library currently supports following TokenStores:

provider.tokenStore = Keychain.shared

Keychain: Before you use thisTokenStore, make sure you turn on the Keychain Sharing capability.

provider.tokenStore = UserDefault.standard

UserDefaults: the default TokenStore. Information are saved locally and, if properly initialized, to your App Group.

provider.tokenStore = NSUbiquitousKeyValueStore.default

NSUbiquitousKeyValueStore: the information are saved in the iCloud Key Value Store. Before you use this TokenStore make sure your project has been properly configured as described here.

Error

Error.swift

Error is a enum that conforms to the ErrorType protocol.

  • cancel The user cancelled the authorization process by closing the web browser window.

  • applicationSuspended The OAuth application you set up has been suspended.

  • redirectURIMismatch The provided redirectURL that doesn't match what you've registered with your application.

  • accessDenied The user rejects access to your application.

  • invalidClient The clientID and or clientSecret you passed are incorrect.

  • invalidGrant The verification code you passed is incorrect, expired, or doesn't match what you received in the first request for authorization.

  • other The application emitted a response in the form of {"error": "xxx", "error_description": "yyy"} but SwiftyOAuth doesn't have a enum for it. The data is available in the associated values.

  • unknown The application emitted a response that is neither in the form of a success one ({"access_token": "xxx"...}) nor in the form of a failure one ({"error": "xxx"...}). The data is available in the associated value.

  • nsError An error triggered when making network requests or parsing JSON. The data is available in the associated value.

Providers

Providers/

Check the wiki for more informations!

Installation

Carthage

Carthage is a decentralized dependency manager that automates the process of adding frameworks to your Cocoa application.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

To integrate SwiftyOAuth into your Xcode project using Carthage, specify it in your Cartfile:

github "delba/SwiftyOAuth" >= 1.1

CocoaPods

CocoaPods is a dependency manager for Cocoa projects.

You can install it with the following command:

$ gem install cocoapods

To integrate SwiftyOAuth into your Xcode project using CocoaPods, specify it in your Podfile:

use_frameworks!

pod 'SwiftyOAuth', '~> 1.1'

License

Copyright (c) 2016-2019 Damien (http://delba.io)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

swiftyoauth's People

Contributors

delba avatar fabiomassimo avatar johannwilfling avatar radianttap avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swiftyoauth's Issues

Multi platform support

The OAuth Authentication process nowadays can be triggered from many devices equipped with different os: watch OS, iOS, tvOS.

Unfortunately, not all of this operating system can rely on a safe way to implement the OAuth 2.0 authentication flow:

  • tvOS does not support SafariServices or Webkit.
  • watchOS does not support SafariServices or Webkit.
  • Today extension can not present webpages.

My idea to address this issue would be to implement for SwiftyOAuth following goals:

  • Make the library use app extension API only.
  • Add support for multiple platform: iOS, watchOS, tvOS.
  • Improve -authorize method depending on current platform and capabilities.

What do you think?

Token.init(dictionary:) should be public..?

If I want/need to write my own TokenStore, I need to be able to store/recreate the Token. The easiest way is to do Token.dictionary, convert to Data and then store. And the opposite would be easy, if you make your init public, instead of internal.

Is there a reason for it to be internal..?

Compiler Errors

I am receiving many compiler errors when integrating into a basic Swift 3 application with cocoa pods.

pod 'SwiftyOAuth', '~> 0.3' // the pod 

screen shot 2017-02-27 at 12 40 03 pm

Add support for self-signed SSL certificates

Self-signed certificates are very common in developer environments. Network calls are done using static function on HTTP struct and with URLSession.shared which silently ignores auth challenges and simply leads to failure branch.

Support OAuth 2.0 Device Flow

Device flow's goal is to implement OAuth 2.0 authorisation flow on devices with limited capabilities (i.e. no WebKit).

In my overview to support this:

  • Add new grant type: http://oauth.net/grant_type/device/1.0
  • Handle new error cases: "authorisation_pending" , "slow_down", "code_expired"
  • Extend the Provider with support to request an access token with new grant type.

Instagram does not supply token_type and the flow breaks

In Token.swift, this init makes the all 3 parameters mandatory:

        guard let
            accessToken = json["access_token"] as? String,
            tokenType = json["token_type"] as? String,
            scope = json["scope"] as? String
        else { return nil }

However, Instagram only returns access_token

{
    "access_token": "2342264381.bc3c943.6086017a221b427a997e4928f0ea197b",
    "user": {
...
    }
}

What do you think about this:

    internal init?(json: JSON) {
        guard let
            accessToken = json["access_token"] as? String
        else { return nil }

        self.accessToken = accessToken

        self.tokenType = json["token_type"] as? String ?? ""
        self.scope = json["scope"] as? String ?? ""

        self.dictionary = json
    }

Issue in following the README for handling incoming requests in the AppDelegate

From the docs:

Step 2: Handle the incoming requests

Handle the incoming requests in your AppDelegate:

func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
    github.handleURL(url, options: options)

    return true
}

Unfortunately, while I was following the README, I found out that that the delegate method signature is slightly different:

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool

This causes an inconsistency with the designated method to handle an URL from the Provider.

    /**
     Handles the incoming URL.

     - parameter URL:     The incoming URL to handle.
     - parameter options: A dictionary of launch options.
     */
    public func handleURL(URL: NSURL, options: [String : AnyObject])

I think it should be rewritten in something like:

public func handleURL(URL: NSURL, sourceApplication: String?) 

Such that the Step 2 from the README would look like:

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
    github.handleURL(url, sourceApplication: sourceApplication)

    return true
}

Xcode 8 GM

Does anyone have SwiftyOAuth working with the Xcode 8 GM? I marked the completion blocks in Provider as @escaping where necessary and it is building fine but the issue now is that the new method in the AppDelegate to open urls now has the following signature:

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool

so the Provider method handleURL is not working.

Great library by the way. It's nice and lightweight and has the Result type built-in. SwiftyOAuth is definitely going to be my default OAuth library from now on.

Manual Installation

Carthage and CocoaPods are awesome tools and make our life really easier, but there are some devs who still don't know how to use them.

It would be cool to add the Manual installation guide in your README.md. You can take a look at my iOS Readme Template to see how you can do it.

Authentication with Google: not matching redirect URL

I was trying to perform a login with Google Service.

Hereby the executed code

let provider = Provider.Google(clientID: "$(the_client_id)", clientSecret: "$(the_client_secret)", redirectURL: "$(bundle_identifier):/urn:ietf:wg:oauth:2.0:oob")

provider.scopes = ["https://www.googleapis.com/auth/analytics.readonly"]

provider.authorize(self) { (result) in
    switch result {
    case .Success(let token):
        print(token)
    case .Failure(let error):
        print(error)
}

When the authorisation is granted in the Safari View Controller the redirect URL gets triggered with following format:

$(bundle_identifier):/urn:ietf:wg:oauth:2.0:oob?code=$(the_authorization_code)

This cause an issue for when the library checks if the redirect URL use during the initialisation of the Provider matches the received redirect URL from the AppDelegate.

I've tried other combination of redirect URL but that's the redirect URL format that the Google guide advocates.

Did anyone experienced this when trying the built in Google Provider?

I think an easy fix would be to match the retrieved URL by removing the GET parameter from the URL but before open a new PR I'd like to receive some feedback about this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.