Git Product home page Git Product logo

passport-http-oauth's Introduction

Passport-HTTP-OAuth

HTTP OAuth authentication strategy for Passport.

This module lets you authenticate HTTP requests using the authorization scheme defined by the OAuth 1.0 protocol. OAuth is typically used protect API endpoints, including endpoints defined by the OAuth protocol itself, as well as other endpoints exposed by the server.

By plugging into Passport, OAuth API authentication can be easily and unobtrusively integrated into any application or framework that supports Connect-style middleware, including Express.

Note that this strategy provides support for implementing OAuth as a service provider. If your application is implementing OAuth as a client for delegated authentication (for example, using Facebook or Twitter), please see Passport-OAuth for the appropriate strategy.

❤️ Sponsors

npm build coverage ...

Install

$ npm install passport-http-oauth

Usage of Consumer Strategy

Configure Strategy

The OAuth consumer authentication strategy authenticates consumers based on a consumer key and secret (and optionally a temporary request token and secret). The strategy requires a consumer callback, token callback, and validate callback. The secrets supplied by the consumer and token callbacks are used to compute a signature, and authentication fails if it does not match the request signature. consumer as supplied by the consumer callback is the authenticating entity of this strategy, and will be set by Passport at req.user.

passport.use('consumer', new ConsumerStrategy(
  function(consumerKey, done) {
    Consumer.findByKey({ key: consumerKey }, function (err, consumer) {
      if (err) { return done(err); }
      if (!consumer) { return done(null, false); }
      return done(null, consumer, consumer.secret);
    });
  },
  function(requestToken, done) {
    RequestToken.findOne(requestToken, function (err, token) {
      if (err) { return done(err); }
      if (!token) { return done(null, false); }
      // third argument is optional info.  typically used to pass
      // details needed to authorize the request (ex: `verifier`)
      return done(null, token.secret, { verifier: token.verifier });
    });
  },
  function(timestamp, nonce, done) {
    // validate the timestamp and nonce as necessary
    done(null, true)
  }
));

Authenticate Requests

Use passport.authenticate(), specifying the 'consumer' strategy, to authenticate requests. This strategy is intended for use in the request token and access token API endpoints, so the session option can be set to false.

For example, as route middleware in an Express application:

app.post('/access_token', 
  passport.authenticate('consumer', { session: false }),
  oauthorize.accessToken(
    // ...
  });

Usage of Token Strategy

Configure Strategy

The OAuth token authentication strategy authenticates users based on an access token issued to a consumer. The strategy requires a consumer callback, verify callback, and validate callback. The secrets supplied by the consumer and verify callbacks are used to compute a signature, and authentication fails if it does not match the request signature. user as supplied by the verify callback is the authenticating entity of this strategy, and will be set by Passport at req.user.

passport.use('token', new TokenStrategy(
  function(consumerKey, done) {
    Consumer.findByKey({ key: consumerKey }, function (err, consumer) {
      if (err) { return done(err); }
      if (!consumer) { return done(null, false); }
      return done(null, consumer, consumer.secret);
    });
  },
  function(accessToken, done) {
    AccessToken.findOne(accessToken, function (err, token) {
      if (err) { return done(err); }
      if (!token) { return done(null, false); }
      Users.findOne(token.userId, function(err, user) {
        if (err) { return done(err); }
        if (!user) { return done(null, false); }
        // fourth argument is optional info.  typically used to pass
        // details needed to authorize the request (ex: `scope`)
        return done(null, user, token.secret, { scope: token.scope });
      });
    });
  },
  function(timestamp, nonce, done) {
    // validate the timestamp and nonce as necessary
    done(null, true)
  }
));

Authenticate Requests

Use passport.authenticate(), specifying the 'token' strategy, to authenticate requests. This strategy is intended for use in protected API endpoints, so the session option can be set to false.

For example, as route middleware in an Express application:

app.get('/api/userinfo', 
  passport.authenticate('token', { session: false }),
  function(req, res) {
    res.json(req.user);
  });

Issuing Tokens

OAuthorize is a toolkit for implementing OAuth service providers. It bundles a suite of middleware implementing the request token, access token, and user authorization endpoints of the OAuth 1.0 protocol.

The toolkit, combined with the ConsumerStrategy and a user authentication strategy can be used to implement the complete OAuth flow, issuing access tokens to consumers. TokenStrategy can then be used to protect API endpoints using the access tokens issued.

Examples

The example included with OAuthorize demonstrates how to implement a complete OAuth service provider. ConsumerStrategy is used to authenticate clients as they request tokens from the request token and access token endpoints. TokenStrategy is used to authenticate users and clients making requests to API endpoints.

Tests

$ npm install --dev
$ make test

Build Status

Credits

License

The MIT License

Copyright (c) 2012-2013 Jared Hanson <http://jaredhanson.net/>

passport-http-oauth's People

Contributors

davidbgk avatar harrisiirak avatar jaredhanson avatar tolgaakyuz 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

passport-http-oauth's Issues

Outdated passport library

Hello,

I am trying to use this consumer strategy along with local strategy.
If i am using it as stand alone strategy, everything is ok.
Due the fact that this npm package is using an outdated version of passport, i am not able to use it.
At this moment i've updated version in package.json and is working as expected.
Please update the package.json version for passport.

/passport-http-oauth/strategies/utils:originalURL method.

First of all thanks for the library. It`s very easy to implement 'oauth' server provider side with it.

Recently I had a task of creating several routes with the same beginning part of the url. For instance, the start of all urls is '/base' and every route under the base must be checked with 'oauth' (ConsumerStrategy from the library) passport authentication middleware, like the following:

app.use('/base', passport.authenticate('oauth', {session: false}), require('./oauth-api'));

in the 'oauth-api' file I create a Route and add 8 urls. So, the complete routes look like this:

router.get('/route1', controller.route1); router.get('/routeN', controller.routeN);
When an oauth Consumer prepares a request to my server, it creates oauth_signature. The URL part of the signature would be like the following:

http://localhost:{port}/base/route1

Whereas the library would consider the url without the base, like this:

http://localhost:{port}/route1

And therefore the signatures don`t match.

The solution that worked for me was to amend ,mentioned in the topic, the 'originalURL' the line

path = req.url || '';

to the line

path = req.originalUrl || '';

TokenStrategy doesn't play nicely with Express Routes

Let's say you create an app with a router (free typing follows)

route = express.Router();
route.get('/profile',   
    passport.authenticate('token', {
            session: false
     }), _get_profile);

app = express();
app.use("/api/1.0", route);

when helpers.originalURL is called, it will come up with /profile/ which then will be fed into the HMAC-SHA1 algorithm for the base (at around line 206 of token.js)

Unfortunately, the client has computed the base using /api/1.0/profile and so the signatures don't match.

"2-legged" usage

First off, thank you for the great work. Have learned a lot about oauth while using your modules.

I have a scenario where we want to use 2-legged oauth (I'm aware that the definition of 2-legged oauth may vary and sometimes this scenario is called 0-legged, but anyway...).

Using passport-http-oauth, I'm able to implement a 2-legged scenario where the access_token isn't needed. The problem is that most descriptions on 2-legged scenarios want to send an empty access_token. In your module, you check if the access_token string is empty, and if it is, you throw an error (parameter_missing).

So, my question is, would it be safe and useful to have an option to omit the check for an empy access_token. I can write the code, but wonder if you would find it useful in you repo.

Thanks

Plain Text Signature Compare issue

The utils.plaintext function uses the utils.encode function to encode the plain text signature. This causes the this causes the plain text signature received from the request to be found invalid as the it is never encoded after having been parsed from the request (the utils.parseHeader function decodes all values).

Incorrect handling of complex & duplicate x-www-form-urlencoded parameters

RFC 5849 §3.4.1.3.1 mandates that if the HTTP request contains a single valid application/x-www-form-urlencoded entity-body, its contents be parsed into key/value pairs and added to the list of parameter sources that are covered by the OAuth 1 signature.

Currently, passport-http-oauth checks whether the Content-Type is application/x-www-form-urlencoded and uses req.body if it is. This requires a separate middleware to be present in the chain to decode the entity-body to req.body. Furthermore, this requires said middleware to decode it to a simple list of key/value pairs to follow the spec. Unfortunately, the common body-parser middleware urlencoded() does not do this.

Consider:

POST /test HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 15

foo=bar&foo=baz
const express = require('express')
const passport = require('passport')
const {ConsumerStrategy, TokenStrategy} = require('passport-http-oauth')

passport.use('consumer', new ConsumerStrategy(
	(consumerKey, done) => done(null, {}, 'secret'),
	(requestToken, done) => done(null, false),
))

const app = express()
app.post('/test',
	express.urlencoded({extended: true/false}),
	passport.authenticate('consumer', { session: false }),
	(req, res) => res.json('ok'))

As documented in the Node.js docs, querystring.parse, which is called if {extended: false}, parses this request body as:

req.body = {'foo': ['bar', 'baz']}

As a result, passport-http-oauth attempts to sign the string ...%26foo%3Dbar%252Cbaz instead of the expected ...%26foo%3Dbar%26foo%3Dbaz, and authentication fails when it should succeed (and succeeds when it should fail, if the client does the same!).

qs.parse, which is called if {extended: true}, doesn’t explicitly document this in the README, but as far as I can tell from the source code, it does the same and this cannot be disabled. Furthermore, it also parses several special syntaxes for complex objects and arrays.

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.