GithubHelp home page GithubHelp logo

trivago / heimdallr.swift Goto Github PK

View Code? Open in Web Editor NEW
639.0 639.0 86.0 4.57 MB

Easy to use OAuth 2 library for iOS, written in Swift.

License: Apache License 2.0

Swift 98.39% Ruby 1.14% Objective-C 0.47%
oauth2 swift

heimdallr.swift's People

Contributors

arthurgau0419 avatar bckr avatar daande avatar derlobi avatar donnywdavis avatar fbeeper avatar hffmnn avatar marcelofabri avatar marvinnazari avatar poislagarde avatar spunja avatar stengo avatar susannproszak avatar tibr avatar ugoarangino 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

heimdallr.swift's Issues

Continuous Integration

Should we use our Jenkins or something like Travis-CI? We can use our proven rake tasks.

How to pass scope when using resource owner flow?

Hey
I've am using this library in our app to request a token based on resource owner flow. My question is - how I should pass the scope? I've finally managed to do it using this code:

 var oauthparams = OAuthAuthorizationGrant.ResourceOwnerPasswordCredentials(username, password).parameters
        oauthparams["scope"] = "red"

        heimdallr.requestAccessToken(grantType: "password", parameters: oauthparams) { result in
            switch result {
            case .Success:
                print("success")
            case .Failure(let error):
                print("failure: \(error)")
            }
        }

But this does not feel right.
In the other hand, if this is the way to do this, maybe consider adding it to the readme, or add an overload (I can create a PR). As far as I know scope is required in this flow...

Thanks
Omer

Allow modification of OAuth decoding

The accesstoken response we are getting from a vendor for OAuth is returning expires_in as a string and not a Number, which is preventing the response from parsing successfully. Is there a way to allow for modification of how the response is parsed?

authenticateRequest in README

Hi,
I am having a bit of hard time to implement authenticateRequest.
From README file, first, in .Success(let request) shouldn't "let" be removed? Having it causes crashes.
Also, switch requires default case.
In the end, for some reason even if I get .Success(request) back, for some to me unknown reason, code enters in default instead on .Success. Some working example or snippet might be good to have.

Here is what I have:

heimdallr.authenticateRequest(request) {
  result in 
  switch result {
    case .Success(request):
      let task = session.dataTaskWithRequest(request) {
        data, response, error in
        // deserialize data and see response code
     }
     task.resume()
   case .Failure(let error): 
    // print error
   default:
     print("Why I entered here!?")`

Can you help me out here, please?

Question: Retrieve Access Token that is store for use in the application

After I login using this:

let tokenURL = NSURL(string: URL.signin)!
        let heimdall = Heimdall(tokenURL: tokenURL)
        heimdall.requestAccessToken(username: self.txtEmail.text!, password: self.txtPassword.text!) { result in
            switch result {
            case .Success:

How would I use the access token? I need it to open a websocket using a different library. In my AppDelegate.swift I have:

protocol OAuthAccessTokenStore {
    func storeAccessToken(accessToken: OAuthAccessToken?)
    func retrieveAccessToken() -> OAuthAccessToken?
}

Any idea I just need the token string for example:

"ba81a9251150a0f229ff7bb0d117eecbe3ec75dafecf8497e42d282fc19f9772"

Support for authorisation URL

Providers like Google require to perform an authentication through a webpage in order to request an access token.
Currently the library only requests an access token by specifying a token URL without an authorisation URL.

Refresh Token in a different URL

So I'm currently working with an API that have a different endpoint for token refresh. How can I let Heimdallr know the refresh token URL (and maybe even allow the application to set parameters)?

what if refresh token expired

If the access token has already expired and a refresh token is available, Heimdallr will automatically refresh the access token

What if refresh token is also expired?
is there any function/callback to check if refresh_token itself is expired?

Extract resource request authentication

Although using the HTTP Authorization header is probably the most common way of authenticating with a resource endpoint, there are many other options. Therefore, we should extract how a resource request is authenticated and make it configurable. Something like:

public protocol HeimdallResourceRequestAuthenticator {
  func authenticateResourceRequest(request: NSURLRequest, withAccessToken: OAuthAccessToken) -> NSURLRequest
}

External dependencies

How do we want to work with external dependencies in general? Do we want to use things like kishikawakatsumi/KeychainAccess or build them ourselves?

Grant Type Failure

Hi there!

First, kudos on the library!!

I do have an issue with the requestAccessToken(username,password) method. I'm having a failure: failure: grant_type must be client_credentials, authorization_code or refresh_token

      heimdallr.requestAccessToken(username: username, password: password) { result in
            switch result {
            case .success:
                print("success")
            case .failure(let error):
                print("failure: \(error.localizedDescription)")
            }
        }

Any ideas ?

Thanks,
Morgan

Prevent firing multiple requests?

From what I've seen in the code, no special treatment is done to prevent multiple network calls being fired in authenticateRequest.

This can be a problem, as a server can invalidate one of the returned tokens. Should the library handle this?

Extract access token request creation

The HTTP client extracted in #11 and #30 should probably also take care of creating a proper request for itself. This could be something else than an NSURLRequest.

This is low priority.

Anticipate access token expiration

Example: If the access token expires in 1 second, do we want to treat it as expired before using it? Should we add a safety interval that is configurable from the outside? What should the default value be?

Migrate to Swift 3.0

The default migration tool to Swift 3.0 in Xcode 8 beta leaves a few errors in Heimdallr. It'd be nice to have an updated SwiftyJSON source available for Swift 3.0.

Thanks!

FYI Xcode 8/iOS 10 Keychain issues

I was having issues authenticating my requests, and after spending some time debugging I found out that the issue is that the Keychain was giving an error when storing a new value. Apparently this is a known issue with iOS 10, there are some threads discussing this here:

https://forums.developer.apple.com/message/179846

https://forums.developer.apple.com/thread/51071

Workaround usually is to add the Keychain Entitlement, but it doesn't solve in my case because I use Heimdallr in a framework.

Thought I'd create this here if anyone else is running into the same issues (Heimdallr doesn't seem to be reporting this error.)

Remove Argo?

Hi there!

I'm currently adding Heimdallr to our project and we already use another mapping framework. Since dynamic frameworks add a considerable overhead when loading, I was think if it was possible to remove Argo as dependency here.

My main motivation is that the models seem to be simple enough to parse them manually instead and it would keep the library simpler, avoiding:

  1. The overhead of another dynamic framework
  2. Caring about if Argo updated to Swift X.Y
  3. Potential conflicts between the Argo version used by this project and the user's project

This shouldn't even be a breaking change, since it's just an implementation detail.

I don't know the history, but it seems that on #16, everyone agreed that dependencies were fine, but 2be58cb removed KeychainAccess in favor of a custom Keychain wrapper.

If response is positive to this issue, I'm willing to work on this and open a PR.

Thanks!

Enable marking an existing access token as invalid

Imagine the case where the resource endpoint rejects a request because the provided access token is invalid, but the client still has a valid refresh token. In this case, we must allow to mark the existing access token as invalid without clearing the refresh token.

Reactive extension

I think we should use ReactiveCocoa 2 because 3 seems to be far from being usable in production. Should we put this into this repo or into a separate one?

Support other flows

What other flows are there? We could improve Heimdall by adding them whenever we've got the time.

Can't build with Carthage

Getting this error:

*** Building scheme "ReactiveHeimdallr-iOS" in Heimdallr.xcworkspace
The following build commands failed:
    Check dependencies
(1 failure)
** BUILD FAILED **


The following build commands failed:
    Check dependencies
(1 failure)
ld: warning: embedded dylibs/frameworks only run on iOS 8 or later
ld: warning: embedded dylibs/frameworks only run on iOS 8 or later
ld: warning: embedded dylibs/frameworks only run on iOS 8 or later
ld: warning: embedded dylibs/frameworks only run on iOS 8 or later
ld: warning: embedded dylibs/frameworks only run on iOS 8 or later
ld: warning: embedded dylibs/frameworks only run on iOS 8 or later
ld: warning: embedded dylibs/frameworks only run on iOS 8 or later
ld: warning: embedded dylibs/frameworks only run on iOS 8 or later

“Use Legacy Swift Language Version” (SWIFT_VERSION) is required to be configured correctly for targets which use Swift. Use the [Edit > Convert > To Current Swift Syntax…] menu to choose a Swift version or use the Build Settings editor to configure the build setting directly.

Edit: Using Swift 3. There's a PR from @marcelofabri here: #94, but it seems there's issues with RAC.

Support for SSL connections using self-signed certificates

Hi,

since Apple introduced ATS (App Transport Security) normal HTTP connections are not allowed anymore. Of course you can bypass this as long as you're still in development mode and you don't need to publish your app on the app store. Same applies to connections you need to establish to servers using a self-signed SSL certificate.

The problem now is that as far as I can see Heimdallr is not able to use SSL connections with self-signed certificates on the server-side (at least during development there should be no need to pay money for an official SSL certificate). Is there any change to implement this feature in Heimdallr so connections to servers with a self-signed certificate can be used?

Thanks for all your work so far!!

Configure NSURLSession

Should we allow the user to manipulate the NSURLSession used to request the access token?

Going even further we could add a protocol to give the consumer the flexibility to send the access token request however she wants.

expiresAt value: timeInterval.flatMap(toNSDate) vs NSDate(timeInterval)

I have a problem reading "expires_in" values from OAuthAccessToken jsons. The value comes as a Unix Epoch int from the service.

The code line at OAuthAccessToken.swift
let expiresAt = (json["expires_in"] as? NSTimeInterval).flatMap(toNSDate)
If json["expires_in"] = 1475233174
Sets expiresAt value to: 2063-06-30 20:59:08 +0000 (this NSdate converted to UNIX epoch is 1475233174*2)

But if I change the converter to
let expiresAt = NSDate(timeIntervalSince1970: (json["expires_in"] as? NSTimeInterval)!)
The expiresAt value is correct

What is the difference between .flatMap and NSDate() converters?
Should the json["expires_in"] be in another format?

Thanks

Change access token request to HTTP POST

According to RFC 6749, section 4.3.2, the access token request is made using HTTP POST with parameters added to the request entity-body, for example:

POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=password&username=johndoe&password=A3ddj3w

succeeded but returns error anyway

Hi, i send a request to my server and i get the access_token back, but in the requestAccessToken block i get .Failure result, here is my code

let credentials = OAuthClientCredentials(id: "ede4499a639710a0b5107b7b00df3cece194114871f2add64f3cd93a9418a197", secret: "4045de00ec7505f0f8e980aa063311dc8118f1bfdb7e5d160fa35eea60ee6ab5")


let tokenURL = NSURL(string: "http://localhost:3000/oauth/token")!
let heimdall = Heimdall(tokenURL: tokenURL, credentials: credentials)

heimdall.requestAccessToken(username: username, password: password) { result in
    switch result {
    case .Success:
        println("success")
    case .Failure(let error):
        println("failure: \(error)")
    }
}

and i get back this

failure: Error Domain=HeimdallErrorDomain Code=1 "Could not authorize grant" UserInfo=0x7fb86481cd40 {NSLocalizedDescription=Could not authorize grant, NSLocalizedFailureReason=Expected access token, got: {"access_token":"a0752d03bd4ac7200f0cd739f1a411df1885d47f24a3ab1c6b216c435a199847","token_type":"bearer","scope":"public","created_at":1434027186}.}

thanks in advance

Result version mismatch.

I can see that the cart file suggests it has been updated to use Result 2.0:

# Core
github "antitypical/Result" ~> 2.0

But, the podspec still referenced 1.0:

  spec.subspec 'Core' do |subspec|
     ...
    subspec.dependency 'Result', '~> 1.0'
     ...
  end

Swift 2 Branch - "Failed to build workspace Argo with scheme Argo-watchOS"

I'm attempting to install Heimdall from the Swift 2.0 branch via Carthage and I'm getting the following error:

xcodebuild: error: Failed to build workspace Argo with scheme Argo-watchOS.
Reason: The run destination My Mac is not valid for Running the scheme 'Argo-watchOS'.

Is anyone else getting this?

Heimdallr doesn't refresh token but get a new access token instead

My version: github "rheinfabrik/Heimdallr.swift" ~> 3.2

Using Wireshark, I could monitor Heimdallr calls on my app.

This is how it refreshes the OAuth token:
Wireshark capture when trying to refresh token

Which is not using refresh_token but requesting a new access_token.

Also, this is my implementation: I'm using a singleton of Heimdallr

import Heimdallr

class SharedNetwork {
    static let instance = SharedNetwork()

    var heimdallr: Heimdallr!

    private init() {
        let loginURL = NSURL(string: NEA.API.login)!
        let credentials = OAuthClientCredentials(id: NEA.API.clientId, secret: NEA.API.clientSecret)
        self.heimdallr = Heimdallr(tokenURL: loginURL, credentials: credentials)
    }
}

//Call in it like this

let accountInfoRequest = NSURLRequest(URL: NSURL(string: "http://foobar.com/api/account/info")!)
SharedNetwork.instance.heimdallr.authenticateRequest(accountInfoRequest) { result in
    //...
}

Make clientID optional

As mentioned by @Gi-lo the client_id field is not mandatory when requesting the access token. Because of that we should make it optional.

https://tools.ietf.org/html/rfc6749#section-4.3.2:

If the client type is confidential or the client was issued client
credentials (or assigned other authentication requirements), the
client MUST authenticate with the authorization server as described
in Section 3.2.1.

https://tools.ietf.org/html/rfc6749#section-3.2.1:

A client MAY use the "client_id" request parameter to identify itself
when sending requests to the token endpoint.

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.