Coder Social home page Coder Social logo

tdoauth's Introduction

TDOAuth

CI Status Swift Package Manager compatible Version License Platform

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Requirements

Swift 4, 4.2 or 5. The pure-Swift subspec has no dependencies.

Installation

CocoaPods

TDOAuth is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'TDOAuth'

SwiftPM

Add .package(url: "https://github.com/yahoo/TDOAuth.git", from: "1.6.0") to your package.swift

Usage (Swift)

Two-Legged OAuth (Client & Server Only)

The two legs of two-legged OAuth are the client and server. This method of authentication is suitable for verifying access from a blessed first-party. If you have only a consumer secret and consumer key, this the method you would use:

let consumerSecret = "my-consumer-secret"
let consumerKey = "my-consmer-key"

/// Generate our OAuth1 signer
let oauth1: OAuth1<HMACSigner> = {
    let secrets = SharedSecrets(consumerSecret: consumerSecret)
    let sha1Signer = HMACSigner(algorithm: .sha1, material: secrets)
    return OAuth1(withConsumerKey: consumerKey, signer: sha1Signer)
}()

/// Feed requests into our OAuth1 signer to produce signed versions of those requests.
/// The only modificataion to the provided request is setting the Authorization HTTP header.
func signRequest(_ request: URLRequest) -> URLRequest? {
    return oauth1.sign(request: request)
}

Three-Legged OAuth (Client, Server & Third-party)

Three-legged OAuth is a version suitable for authenticating a third-party to access a user's data. This method introduces a second set of key & secret for the third party:

let consumerSecret = "my-consumer-secret"
let consumerKey = "my-consmer-key"
let accessToken: String? = "access-token"
let accessTokenSecret: String? = "token-secret"


/// Generate our OAuth1 signer
let oauth1: OAuth1<HMACSigner> = {
    let secrets = SharedSecrets(consumerSecret: consumerSecret, accessTokenSecret: accessTokenSecret)
    let sha1Signer = HMACSigner(algorithm: .sha1, material: secrets)
    return OAuth1(withConsumerKey: consumerKey, accessToken: accessToken, signer: sha1Signer)
}()

/// Feed requests into our OAuth1 signer to produce signed versions of those requests.
/// The only modificataion to the provided request is setting the Authorization HTTP header.
func signRequest(_ request: URLRequest) -> URLRequest? {
    return oauth1.sign(request: request)
}

Signing Methods

In the examples above, we use SHA-1 HMAC to sign generate the signatures. You may want to use a more secure hashing algorithm since SHA-1 is quite weak now. TDOAuth supports more secure SHA-2 signing by default, as well as arbitrary signing (Bring Your Own Algorithm).

Supported SHA-2 variants:

  • SHA-224
  • SHA-256
  • SHA-384
  • SHA-512

Example for SHA-256

let signer: OAuth1<HMACSigner> = HMACSigner(algorithm: .sha256, material: secrets)

Plain text Signing

Plain text signing is useful mainly for debugging or use over strictly pinned SSL connections. The keys are not secured in any way, so it is very bad idea to use this strategy without pinned SSL.

Example for PlainText signing

let signer: OAuth1<PlaintextSigner> = PlaintextSigner(keyMaterial: secrets)

Custom Signing

To provide your own custom signing, implement the OAuth1Signer protocol:

public protocol OAuth1Signer {

    associatedtype KeyMaterial

    var signatureMethod: String { get }

    init(keyMaterial: KeyMaterial)

    func sign(_ value: String) -> String
}

For a simple example, see the implementation in PlaintextSigner.swift.

Usage (Legacy Objective-C)

Using the Objective-C API is not recommended. It is provided for backwards compatability with the old TDOAuth Obj-C API. While the underlying code uses the exact same Swift code as above, the legacy TDOAuth API imposed significant opinions on the requests, and those opinions were replicated in the new compatability API. For example, a User-Agent header is generated and added automatically to your request. Handling for POST and form-data has a lot of caveats and edge cases around encoding.

While the Swift API simply signs whatever URLRequest you provide it, the Objective-C API generates a new NSURLRequest for you as part of the signing process. As a result you may need to carefully alter the returned request instance to suit your needs (be sure not to break the signature).

Use the Swift API!

Objective-C API Example

@import TDOAuth;

NSURLRequest * request = [TDOAuth URLRequestForPath:@"/v1/service/name"
                         parameters:@{ "count": @10, "format": "json" }
                               host:@"api.example.com"
                        consumerKey:@"my-consumer-key"
                     consumerSecret:@"my-consumer-secret"
                        accessToken:@"my-token"
                        tokenSecret:@"my-token-secret"
                             scheme:@"https"
                      requestMethod:@"GET"
                       dataEncoding:TDOAuthContentTypeUrlEncodedForm
                       headerValues:@{ "Accept": "application/json" }
                    signatureMethod:TDOAuthSignatureMethodHmacSha1;

Author

Adam Kaplan, [email protected]

License

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

tdoauth's People

Contributors

adamkaplan avatar avaes avatar aveace avatar bdaz avatar cshaines avatar dana-aa avatar dbgrandi avatar dvp-petrov avatar eliperkins avatar fitterman avatar master-nevi avatar mxcl avatar plasmabal avatar pretz avatar rgisrael avatar stury avatar tybro0103 avatar winnielyt 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

tdoauth's Issues

Query parameters in Authorization header

It seems like query parameters are added to the Authorization header besides being appended to the resource path. I'm not very familiar with the OAuth protocol. I glanced at the examples in the RFC and it doesn't seem like they should be included in the Authorization header.

Including the query parameters in the Authorization header makes the server and client disagree on the signature.

Serious encoding problem

Hi @mxcl ,
I have an encoding problem. I know TDPCEN is used to encode parameters that we want to put it to the URL, but I think the allowedCharacters is not correct.

https://github.com/tweetdeck-archive/TDOAuth/blob/ae2c28edff37ee844cc5732870a10c75215c9384/TDOAuth.m#L37

#define TDPCEN(s)
([[s description] stringByAddingPercentEncodingWithAllowedCharacters:[[NSCharacterSet characterSetWithCharactersInString:@"^!*'();:@&=+$,/?%#[] "] invertedSet]])

For example,
Input:
{
q = "insert into db ( jsonData ) values ( '{"a":"b","c":"d"}' )";
}
TDPCEN("q")
TDPCEN("insert into db ( jsonData ) values ( '{"a":"b","c":"d"}' )")

Output:
q=insert%20into%20db%20%28%20jsonData%20%29%20values%20%28%20%27{"a"%3A"b"%2C"c"%3A"d"}%27%20%29

We notice that {, } and " are not encoded, and it cause NSURL to be nil.
It may occur in https://github.com/tweetdeck-archive/TDOAuth/blob/ae2c28edff37ee844cc5732870a10c75215c9384/TDOAuth.m#L280

I have an idea to solve the problem.
Just replace [[NSCharacterSet characterSetWithCharactersInString:@"^!*'();:@&=+$,/?%#[] "] invertedSet]] with [NSCharacterSet URLQueryAllowedCharacterSet] to correct it.

What do you think?

Maintaining TDOAuth

This pod is a great resource. It's incredibly simple with a minimalistic design. Thank you for providing and maintaining it over the past 8 years.

It has become a critical component of some popular Yahoo iOS apps, such as Yahoo Finance. Yes, we know about OAuth 2.0... however OAuth 1.0a is still very well suited for client (not user) identification purposes and abuse mitigation in many situations.

The repository has not been moved to "archive" mode, indicating that support is becoming less likely. I am proposing two potential paths forward for this project:

  1. Transfer ownership to the Yahoo Open Source Github organization, where a team of seasoned iOS engineers will actively look after and love the project for the foreseeable future.
  2. Add 2-3 agreeable Yahoo maintainers to the project to ensure ongoing stewardship.

Some thing we'd like to do:

  • Full Swift compatibility (nullability, method names, etc)
  • Update unit tests to something modern like Quick/Nimble
  • Performance optimizations
  • Fix some edge cases non-RFC-compliant signatures are generated (i.e. websockets)
  • Add a license to the next release (MIT?)

There is an elegance to OAuth 1.0 for client identification. OAuth 2.0 requires an independent token exchange service to provide the same functionality. For this reason, I see a future for this simple OAuth 1.0 request signer.

Params for DELETE & HEAD requests should be handled like GET

HTTP spec forbids an entity for HEAD requests, so specified parameters should be appended to URL (as with GET).

Older specs also seemed to not want entity in DELETE requests either. Newer RFC do allow these, however the more compatible path forward is to put them in the URL

If nobody has a problem treating HEAD & DELETE parameters like GET, I'll make a pull request to fix this.

http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-19#section-6.7

YHOO weather make request return nil

I use TDOAuth make nsmutable request, return Nil can tell me how to solve it?
The following method request returns nil .
consumerKey ,consumerSecret,appId All have value。

-(NSMutableURLRequest *)requestWithParameters:(NSDictionary *)parameters
{

NSMutableURLRequest *request = [[TDOAuth URLRequestForPath:@"/forecastrss"
                                             GETParameters:parameters
                                                    scheme:@"https"
                                                      host:@"weather-ydn-yql.media.yahoo.com"
                                               consumerKey:self.consumerKey
                                            consumerSecret:self.consumerSecret
                                               accessToken:nil
                                               tokenSecret:nil] mutableCopy];
[request addValue:self.appId forHTTPHeaderField:@"X-Yahoo-App-Id"];
return request;

}

Use HTTPS as default scheme

Modern iOS does not permit non-SSL protected HTTP by default. This library should not default to an normally unsupported scheme.

'CFURLCreateStringByAddingPercentEscapes' is deprecated in iOS 9.0

'CFURLCreateStringByAddingPercentEscapes' is deprecated: first deprecated in iOS 9.0 - Use [NSString stringByAddingPercentEncodingWithAllowedCharacters:] instead, which always uses the recommended UTF-8 encoding, and which encodes for a specific URL component or subcomponent (since each URL component or subcomponent has different rules for what characters are valid).

Signature Base does not include port when provided / non-default

Testing on a local oauth provider instance, if I run on a non-standard port and provide it in the url, TDOAuth removes the port when generating the base. This is not correct looking at the OAuth 1.0 protocol: http://tools.ietf.org/html/rfc5849#section-3.4.1.2

ie
GET on http://localhost:8080/myService
generates a signature base of: GET&http%3A%2F%2Flocalhost%2FmyService ...
when it should be: GET&http%3A%2F%2Flocalhost%3A8080%2FmyService ...

As a result, the signature is invalid to the provider. Trivial issue, but I found it annoying.

The version is still set to 1.0.4

I will fix this if you like, but I think it's dangerous to leave it set to the same number with the code changes that are in there. Would you prefer 1.0.5 or 1.1.0?

signature_base doesn't sign properly on an empty (=nil) param set

Using an empty parameter set breaks signature generation [params mutableCopy returns nil if params is nil...].

Proposed fix:

(NSString *)signature_base {
NSMutableDictionary *sigParams = nil;
if ( params != nil)
    sigParams = [params mutableCopy];
else
    sigParams = [[NSMutableDictionary alloc]init];

[sigParams addEntriesFromDictionary:oauthParams];

OMGUserAgent?

Hello, I've used this lib in the past, it's been very useful, thank you!

I just updated and see an inclusion of OMGUserAgent in TDOAuth.m and use of this object later.

Is this a required dependency?

Can you publish 1.1.4 podspec?

Currently, we have to pin our Podfile to 1.1.2 (due to an encoding issue in 1.1.3) or override TDOAuth.podspec locally. Would be nice to just use the published 1.1.4 version.

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.