trivago / heimdallr.swift Goto Github PK
View Code? Open in Web Editor NEWEasy to use OAuth 2 library for iOS, written in Swift.
License: Apache License 2.0
Easy to use OAuth 2 library for iOS, written in Swift.
License: Apache License 2.0
Add CocoaPods as an alternative to Carthage.
Should we use our Jenkins or something like Travis-CI? We can use our proven rake tasks.
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
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?
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?
My authorization server doesn't always send a new refresh token when refreshing access tokens (as allowed by the spec). When it doesn't, Heimdallr overrides the stored refresh token with nil.
This causes the next refresh to fail with a HeimdallrErrorNotAuthorized
error.
I'll try to work on a PR for a fix. Let me know what you think.
Hi! My authorization server returns some extra parameters in the access token response and I need a way to read them.
For reference, check out example_parameter
in this example in the spec
Jazzy?
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"
Should we give this a descriptive name like OAuth-Swift
or go for something else?
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.
The library should save the access token to the keychain.
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)?
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?
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
}
How do we want to work with external dependencies in general? Do we want to use things like kishikawakatsumi/KeychainAccess or build them ourselves?
Let the library consumer decide how and where to store the access token.
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
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?
https://github.com/aerogear/aerogear-ios-httpstub has been deprecated. We could either switch to https://github.com/AliSoftware/OHHTTPStubs or check out https://github.com/kylef/Mockingjay.
MIT?
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?
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!
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.)
Mention that the library is built based on https://tools.ietf.org/html/rfc6749
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:
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!
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.
Since Apple doesn't allow to upload targets using a "beta" to iTunesConnect, please update the dependency of Result to 1.0.0.
Thank you!
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?
What other flows are there? We could improve Heimdall by adding them whenever we've got the time.
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.
I think NSDateExtensions
would be a good (albeit small) library that we could release by itself.
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!!
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.
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
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
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
I think we should squash the history before releasing the library to the public.
As described in the RFC: https://tools.ietf.org/html/rfc6749#page-45
Because we can.
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
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?
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:
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
//...
}
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.