Code Monkey home page Code Monkey logo

oauth2orize's Introduction

OAuth2orize

OAuth2orize is an authorization server toolkit for Node.js. It provides a suite of middleware that, combined with Passport authentication strategies and application-specific route handlers, can be used to assemble a server that implements the OAuth 2.0 protocol.


Advertisement
Node.js API Masterclass With Express & MongoDB
Create a real world backend for a bootcamp directory app


Status: Build Coverage Dependencies

Install

$ npm install oauth2orize

Usage

OAuth 2.0 defines an authorization framework, allowing an extensible set of authorization grants to be exchanged for access tokens. Implementations are free to choose what grant types to support, by using bundled middleware to support common types or plugins to support extension types.

Create an OAuth Server

Call createServer() to create a new OAuth 2.0 server. This instance exposes middleware that will be mounted in routes, as well as configuration options.

var server = oauth2orize.createServer();

Register Grants

A client must obtain permission from a user before it is issued an access token. This permission is known as a grant, the most common type of which is an authorization code.

server.grant(oauth2orize.grant.code(function(client, redirectURI, user, ares, done) {
  var code = utils.uid(16);

  var ac = new AuthorizationCode(code, client.id, redirectURI, user.id, ares.scope);
  ac.save(function(err) {
    if (err) { return done(err); }
    return done(null, code);
  });
}));

OAuth2orize also bundles support for implicit token grants.

Register Exchanges

After a client has obtained an authorization grant from the user, that grant can be exchanged for an access token.

server.exchange(oauth2orize.exchange.code(function(client, code, redirectURI, done) {
  AuthorizationCode.findOne(code, function(err, code) {
    if (err) { return done(err); }
    if (client.id !== code.clientId) { return done(null, false); }
    if (redirectURI !== code.redirectUri) { return done(null, false); }

    var token = utils.uid(256);
    var at = new AccessToken(token, code.userId, code.clientId, code.scope);
    at.save(function(err) {
      if (err) { return done(err); }
      return done(null, token);
    });
  });
}));

OAuth2orize also bundles support for password and client credential grants. Additionally, bundled refresh token support allows expired access tokens to be renewed.

Implement Authorization Endpoint

When a client requests authorization, it will redirect the user to an authorization endpoint. The server must authenticate the user and obtain their permission.

app.get('/dialog/authorize',
  login.ensureLoggedIn(),
  server.authorize(function(clientID, redirectURI, done) {
    Clients.findOne(clientID, function(err, client) {
      if (err) { return done(err); }
      if (!client) { return done(null, false); }
      if (client.redirectUri != redirectURI) { return done(null, false); }
      return done(null, client, client.redirectURI);
    });
  }),
  function(req, res) {
    res.render('dialog', { transactionID: req.oauth2.transactionID,
                           user: req.user, client: req.oauth2.client });
  });

In this example, connect-ensure-login middleware is being used to make sure a user is authenticated before authorization proceeds. At that point, the application renders a dialog asking the user to grant access. The resulting form submission is processed using decision middleware.

app.post('/dialog/authorize/decision',
   login.ensureLoggedIn(),
   server.decision());

Based on the grant type requested by the client, the appropriate grant module registered above will be invoked to issue an authorization code.

Session Serialization

Obtaining the user's authorization involves multiple request/response pairs. During this time, an OAuth 2.0 transaction will be serialized to the session. Client serialization functions are registered to customize this process, which will typically be as simple as serializing the client ID, and finding the client by ID when deserializing.

server.serializeClient(function(client, done) {
  return done(null, client.id);
});

server.deserializeClient(function(id, done) {
  Clients.findOne(id, function(err, client) {
    if (err) { return done(err); }
    return done(null, client);
  });
});

Implement Token Endpoint

Once a user has approved access, the authorization grant can be exchanged by the client for an access token.

app.post('/token',
  passport.authenticate(['basic', 'oauth2-client-password'], { session: false }),
  server.token(),
  server.errorHandler());

Passport strategies are used to authenticate the client, in this case using either an HTTP Basic authentication header (as provided by passport-http) or client credentials in the request body (as provided by passport-oauth2-client-password).

Based on the grant type issued to the client, the appropriate exchange module registered above will be invoked to issue an access token. If an error occurs, errorHandler middleware will format an error response.

Implement API Endpoints

Once an access token has been issued, a client will use it to make API requests on behalf of the user.

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

In this example, bearer tokens are issued, which are then authenticated using an HTTP Bearer authentication header (as provided by passport-http-bearer)

Examples

This example demonstrates how to implement an OAuth service provider, complete with protected API access.

Related Modules

Debugging

oauth2orize uses the debug module. You can enable debugging messages on the console by doing export DEBUG=oauth2orize before running your application.

License

The MIT License

Copyright (c) 2012-2021 Jared Hanson <https://www.jaredhanson.me/>

oauth2orize's People

Contributors

cmccall avatar eatskolnikov avatar emmanuelgautier avatar frankhassanabad avatar ianmacl avatar irfanbaqui avatar jaredhanson avatar jfromaniello avatar joewagner avatar nettofarah avatar noamcb avatar panva avatar scttnlsn avatar shaiherman avatar siacomuzzi avatar silviom avatar tellnes avatar why520crazy avatar ziluvatar 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oauth2orize's Issues

A 2-legged example would be very helpful.

I'm still trying to wrap my head around oauth. I believe a 2-legged example would be very helpful to myself and anyone else trying to login with something like a simple LocalStrategy.

I think this would be great if I could get it working with Backbone, then I could secure all my api calls that Backbone needs to make.

Error When creating a new BearerStrategy

I am using the same as example but getting this error. Please can anyone help?
if (!name) throw new Error('authentication strategies must have a name');
^
Error: authentication strategies must have a name
at Passport.use (/Users/saransh2012/Developer/vypics/node_modules/passport/lib/passport/index.js:51:20)
at Object. (/Users/saransh2012/Developer/vypics/android_app/auth.js:54:10)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object. (/Users/saransh2012/Developer/vypics/android_app/app.js:11:1)
at Module._compile (module.js:456:26)

Express 3.x.x support?

Hey,

great work! Is this working properly with Express 3.x.x?

I'm asking because it shows me a "CANNOT GET /dialog/authorize" in my Express 3.1.0 project. I also tried a Express 2.0 project which runs perfectly fine.

Probably issues with my routes!?

Thanks!

Question about example

What's the proper way to run the example fully? I can hit the first set of routes just fine (/, /login, /logout, /account) and they seem to do what I would expect. However, it's not clear to me what I have to do to successfully trigger the routes dealing with the dialog.

If I just go to /dialog/authorize, it just generates the express error that's already been discussed.

Thanks in advance for any help.
-- GWF

Authorization and Authentication OAuth2

I have doubt how to proceed with this autorization.

I am new with passport and AngularJS, but i would like to use them, they are very powerfull.

I have Spring REST API Secured by Oauth2, but I have to send togheter user credentials like this:

http://localhost:8080/myapp/oauth/token
grant_type=password&username=email&password=password&client_id=09e749d8309f4044&client_secret=189309492722aa5a&scope=read

In client my application I use passport and I want to authorize/authenticate my users, how can I create a Stratagy for this ?

I will send here my server config and my security Lib.

Server.js

var fs = require('fs');
var http = require('http');
var https = require('https');
var privateKey  = fs.readFileSync(__dirname + '/cert/privatekey.pem').toString();
var certificate = fs.readFileSync(__dirname + '/cert/certificate.pem').toString();
var credentials = {key: privateKey, cert: certificate};

var express = require('express');
var config = require('./config.js');
var passport = require('passport');
var security = require('./lib/security');
var xsrf = require('./lib/xsrf');
var protectJSON = require('./lib/protectJSON');
require('express-namespace');

var app = express();
var secureServer = https.createServer(credentials, app);
var server = http.createServer(app);

// Serve up the favicon
app.use(express.favicon(config.server.distFolder + '/favicon.ico'));

// First looks for a static file: index.html, css, images, etc.
app.use(config.server.staticUrl, express.compress());
app.use(config.server.staticUrl, express['static'](config.server.distFolder));
app.use(config.server.staticUrl, function(req, res, next) {
  res.send(404); // If we get here then the request for a static file is invalid
});

app.use(protectJSON);

app.use(express.logger());                                  // Log requests to the console
app.use(express.bodyParser());                              // Extract the data from the body of the request - this is needed by the LocalStrategy authenticate method
app.use(express.cookieParser(config.server.cookieSecret));  // Hash cookies with this secret
app.use(express.cookieSession());                           // Store the session in the (secret) cookie
app.use(passport.initialize());                             // Initialize PassportJS
app.use(passport.session());                                // Use Passport's session authentication strategy - this stores the logged in user in the session and will now run on any request
app.use(xsrf);                                              // Add XSRF checks to the request
security.initialize(config.oauth.authorize_url, config.oauth.access_token, config.oauth.apiKey, config.oauth.secretKey, config.oauth.scopereq);           // Add a Oauth strategy for handling the authentication

app.use(function(req, res, next) {
  if ( req.user ) {
    console.log('Current User:', req.user.firstName, req.user.lastName);
  } else {
    console.log('Unauthenticated');
  }
  next();
});

app.post('/login', security.login);
app.post('/logout', security.logout);

// Retrieve the current user
app.get('/current-user', security.sendCurrentUser);

// Retrieve the current user only if they are authenticated
app.get('/authenticated-user', function(req, res) {
  security.authenticationRequired(req, res, function() { security.sendCurrentUser(req, res); });
});

// Retrieve the current user only if they are admin
app.get('/admin-user', function(req, res) {
  security.adminRequired(req, res, function() { security.sendCurrentUser(req, res); });
});

// This route deals enables HTML5Mode by forwarding missing files to the index.html
app.all('/*', function(req, res) {
  // Just send the index.html for other files to support HTML5Mode
  res.sendfile('index.html', { root: config.server.distFolder });
});

// A standard error handler - it picks up any left over errors and returns a nicely formatted server 500 error
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));

// Start up the server on the port specified in the config
server.listen(config.server.listenPort, 'localhost', 511, function() {
  // // Once the server is listening we automatically open up a browser
  var open = require('open');
  open('http://localhost:' + config.server.listenPort + '/');
});
console.log('Deengo Business App Server - listening on port: ' + config.server.listenPort);
secureServer.listen(config.server.securePort);
console.log('Deengo Business App Server - listening on secure port: ' + config.server.securePort);

lib/security.js

var express = require('express');
var passport = require('passport');
var app = express();
var BearerStrategy = require('passport-http-bearer').Strategy

var filterUser = function(user) {
  if ( user ) {
    return {
      user : {
        id: user._id.$oid,
        email: user.email,
        firstName: user.firstName,
        lastName: user.lastName,
        admin: user.admin
      }
    };
  } else {
    return { user: null };
  }
};

var security = {
  initialize: function(_authorize_url, _access_token, _apiKey, _secretKey, _scopereq) {
    passport.use('deengo-auth', new OAuth2Strategy({
        authorizationURL: _authorize_url,
        tokenURL: _access_token,
        clientID: _apiKey,
        clientSecret: _secretKey,
        callbackURL: 'http://localhost:3000/oauth/autorize/callback',
        scope: _scopereq,
        passReqToCallback: true,
        skipUserProfile: true        
      },
      function(req, accessToken, refreshToken, profile, done) {
        client['headers']['authorization'] = 'bearer ' + req.session.passport.accessToken;        
        User.findOrCreate({ clientId: clientId }, function(err, user) {
          done(err, user);
        });
      }
    ));

  },
  authenticationRequired: function(req, res, next) {
    console.log('authRequired');
    if (req.isAuthenticated()) {
      next();
    } else {
      res.json(401, filterUser(req.user));
    }
  },
  adminRequired: function(req, res, next) {
    console.log('adminRequired');
    if (req.user && req.user.admin ) {
      next();
    } else {
      res.json(401, filterUser(req.user));
    }
  },
  sendCurrentUser: function(req, res, next) {
    res.json(200, filterUser(req.user));
    res.end();
  },
  login: function(req, res, next) {

    console.log(req.body.email);
    console.log(req.body.password);

    function authenticationFailed(err, user, info){

      //if (err) { return next(err); }
      /*if (!user) { return res.json(filterUser(user)); }
      req.logIn(user, function(err) {
        if ( err ) { return next(err); }
        return res.json(filterUser(user));
      });*/
    }
    //passport.authenticate("deengo-auth", authenticationFailed)(req, res, next);
    return null;
  },
  logout: function(req, res, next) {
    req.logout();
    res.send(204);
  }
};

module.exports = security;

lib/DeengoStrategy.js

var util = require('util');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var BearerStrategy = require('passport-http-bearer').Strategy;
var rest = require('request');

function DeengoRestStrategy(authorize_url, access_token, apiKey, secretKey, scopereq) {
  this.authorize_url = authorize_url;
  this.access_token = access_token;
  this.apiKey = apiKey;
  this.secretKey = secretKey;
  this.scopereq = secretKey;
  this.baseUrl = 'http://localhost:8080/deengo/api/';

  // Call the super constructor - passing in our user verification function
  // We use the email field for the username
  LocalStrategy.call(this, { usernameField: 'email' }, this.verifyUser.bind(this));

  // Serialize the user into a string (id) for storing in the session
  passport.serializeUser(function(user, done) {
    done(null, user.id); 
  });

  // Deserialize the user from a string (id) into a user (via a cll to REST)
  passport.deserializeUser(this.get.bind(this));

  // We want this strategy to have a nice name for use by passport, e.g. app.post('/login', passport.authenticate('deengo'));
  this.name = DeengoRestStrategy.name;
}

// DeengoRestStrategy inherits from LocalStrategy
util.inherits(DeengoRestStrategy, LocalStrategy);

DeengoRestStrategy.name = "deengo";

// Query the users collection
DeengoRestStrategy.prototype.query = function(query, done) {
  query.accessToken = this.accessToken;     // Add the apiKey to the passed in query
  var request = rest.get(this.baseUrl, { qs: query, json: {} }, function(err, response, body) {
    done(err, body);
  });
};

// Get a user by id
DeengoRestStrategy.prototype.get = function(id, done) {
  var query = { apiKey: this.apiKey };
  var request = rest.get(this.baseUrl + id, { qs: query, json: {} }, function(err, response, body) {
    done(err, body);
  });
};

// Find a user by their email
DeengoRestStrategy.prototype.findByEmail = function(email, done) {
  this.query({ q: JSON.stringify({email: email}) }, function(err, result) {
    if ( result && result.length === 1 ) {
      return done(err, result[0]);
    }
    done(err, null);
  });
};

// Check whether the user passed in is a valid one
DeengoRestStrategy.prototype.verifyUser = function(email, password, done) {
  this.findByEmail(email, function(err, user) {
    if (!err && user) {
      if (user.password !== password) {
        user = null;
      }
    }
    done(err, user);
  });
};

module.exports = DeengoRestStrategy;

I do not know if I have to use passport-Bearer or not and how to use-it.

Thanks in advance for any help.

Regards,

Eduardo.

Implicit Token - https request but http response!

I am attempting to implement an Implicit Token and it's almost all working except the very last, the response with token.

In lib/token.js, I've added some extra debug statements to see if the actual redirect URI was wrong, however it clearly isn't as can be seen here just prior to the redirect at the end of the function issued(err, accessToken, params) function in grant/token.js...

debug("TOKEN response success and redirect issued to %s ", location);
return res.redirect(location);

shows the folloing in the console...

oauth2orize TOKEN response success and redirect issued to https://localhost:4000/dashboard#access_token=u3AxxV9Gy05Izmw...YKt5KaKFEEDfL&token_type=bearer 

However my browser (Chrome) dev tool console indicates:

The page at https://localhost:4000/oauth/authorize?response_type=token&client_id=v10data_dashboard&redirect_uri=https://localhost:4000/dashboard displayed insecure content from http://localhost:4000/dashboard#access_token=MYZZjI0jD2…E8RWGRc6S&token_type=bearer.

The location to the https://localhost:4000/oauth/dialog/authorize/decision is clearly set to (note HTTP and not HTTPS):

location:http://localhost:4000/dashboard#access_token=MYZZjI0jD2...E8RWGRc6S&token_type=bearer

I'm just at a loss here since this is simply a redirect clearly with the url going to HTTPS when actually the browser claims HTTP. Is there something somewhere I can include to further investigate?

The setup, which I doubt causes this since all other responses and redirects work is a node.js + node-https-proxy service serving an authentication, resource and dashboard servers where the authentication server is running node.js + express.js + locomotive.js and oauth2orize 0.1.0.

Note: I've shortened the token ... to reduce the description, it's a 256 token.

here is the full req/res from chrome dev console

Request URL:https://localhost:4000/oauth/dialog/authorize/decision
Request Method:POST
Status Code:302 Moved Temporarily
Request Headersview source
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:35
Content-Type:application/x-www-form-urlencoded
Cookie:splashShown1.6=1; undefined=0; csrftoken=tuY3Uoh3DDfctJ92Hbjq1070072ZNwXl; user=%7B%22username%22%3A%22%22%2C%22role%22%3A%7B%22bitMask%22%3A1%2C%22title%22%3A%22public%22%7D%7D; connect.sess=s%3Aj%3A%7B%22passport%22%3A%7B%22user%22%3A1%7D%2C%22authorize%22%3A%7B%22mxVALdZO%22%3A%7B%22protocol%22%3A%22oauth2%22%2C%22client%22%3A6%2C%22redirectURI%22%3A%22https%3A%2F%2Flocalhost%3A4000%2Fdashboard%22%2C%22req%22%3A%7B%22type%22%3A%22token%22%2C%22clientID%22%3A%22v10data_dashboard%22%2C%22redirectURI%22%3A%22%2Fdashboard%22%7D%7D%2C%22GeheVvt0%22%3A%7B%22protocol%22%3A%22oauth2%22%2C%22client%22%3A6%2C%22redirectURI%22%3A%22https%3A%2F%2Flocalhost%3A4000%2Fdashboard%22%2C%22req%22%3A%7B%22type%22%3A%22token%22%2C%22clientID%22%3A%22v10data_dashboard%22%2C%22redirectURI%22%3A%22%2Fdashboard%22%7D%7D%2C%22c6jF6vWI%22%3A%7B%22protocol%22%3A%22oauth2%22%2C%22client%22%3A6%2C%22redirectURI%22%3A%22https%3A%2F%2Flocalhost%3A4000%2Fdashboard%22%2C%22req%22%3A%7B%22type%22%3A%22token%22%2C%22clientID%22%3A%22v10data_dashboard%22%2C%22redirectURI%22%3A%22https%3A%2F%2Flocalhost%3A4000%2Fdashboard%22%7D%7D%2C%22khAyzWov%22%3A%7B%22protocol%22%3A%22oauth2%22%2C%22client%22%3A6%2C%22redirectURI%22%3A%22https%3A%2F%2Flocalhost%3A4000%2Fdashboard%22%2C%22req%22%3A%7B%22type%22%3A%22token%22%2C%22clientID%22%3A%22v10data_dashboard%22%2C%22redirectURI%22%3A%22https%3A%2F%2Flocalhost%3A4000%2Fdashboard%22%7D%7D%7D%7D.rnK3GERYzBlrWVs1zVYnic3dV5fhlNUemgndiOmk5xc
Host:localhost:4000
Origin:https://localhost:4000
Referer:https://localhost:4000/oauth/authorize?response_type=token&client_id=v10data_dashboard&redirect_uri=https://localhost:4000/dashboard
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.65 Safari/537.36
Form Dataview sourceview URL encoded
transaction_id:khAyzWov
allow:allow


Response Headers

connection:keep-alive
content-length:704
content-type:text/html
date:Fri, 13 Sep 2013 23:24:00 GMT
location:http://localhost:4000/dashboard#access_token=DUG0MO9EkCmqC7ldthULbjNXmIDybXsRJGkm6sA85jWoYnRnZx6ItfsHRv9et805GMIwVzghkGe5N605TTthdM5QX1elddWho9nYSYltgidMVoavNhUPZjDcDC4oh2zX0QB0NnBR5HRY5CMSAYC0P2dB2n6IxFw1pouUFl08CMAtSZXugTjwo77PbxPYChGsCgvAhrVmD5TSg1V9fwEjS7W4FLxUO0hXwFCaeA5RYeKOHgOrhdw1HcfXf2zzabR3&token_type=bearer
set-cookie:connect.sess=s%3Aj%3A%7B%22passport%22%3A%7B%22user%22%3A1%7D%2C%22authorize%22%3A%7B%22mxVALdZO%22%3A%7B%22protocol%22%3A%22oauth2%22%2C%22client%22%3A6%2C%22redirectURI%22%3A%22https%3A%2F%2Flocalhost%3A4000%2Fdashboard%22%2C%22req%22%3A%7B%22type%22%3A%22token%22%2C%22clientID%22%3A%22v10data_dashboard%22%2C%22redirectURI%22%3A%22%2Fdashboard%22%7D%7D%2C%22GeheVvt0%22%3A%7B%22protocol%22%3A%22oauth2%22%2C%22client%22%3A6%2C%22redirectURI%22%3A%22https%3A%2F%2Flocalhost%3A4000%2Fdashboard%22%2C%22req%22%3A%7B%22type%22%3A%22token%22%2C%22clientID%22%3A%22v10data_dashboard%22%2C%22redirectURI%22%3A%22%2Fdashboard%22%7D%7D%2C%22c6jF6vWI%22%3A%7B%22protocol%22%3A%22oauth2%22%2C%22client%22%3A6%2C%22redirectURI%22%3A%22https%3A%2F%2Flocalhost%3A4000%2Fdashboard%22%2C%22req%22%3A%7B%22type%22%3A%22token%22%2C%22clientID%22%3A%22v10data_dashboard%22%2C%22redirectURI%22%3A%22https%3A%2F%2Flocalhost%3A4000%2Fdashboard%22%7D%7D%7D%7D.lqvvNpe6fEPub7aJyA4kZV2ws7ihNZf%2Bi0pYopLEV90; Path=/; HttpOnly
vary:Accept
x-powered-by:Express

OH and BTW, amazing package guys, really! Going through Python, Ruby, PHP etc, node.js package quality such as yours made me completely change my ways!

How to get access to request in Bearer token strategy

In the example using the Bearer strategy in Passport, how do you access the request object?

passport.use(new BearerStrategy(
  function(accessToken, done) {
    db.accessTokens.find(accessToken, function(err, token) {
      if (err) { return done(err); }
      if (!token) { return done(null, false); }
      
      db.users.find(token.userID, function(err, user) {
        if (err) { return done(err); }
        if (!user) { return done(null, false); }
        // to keep this example simple, restricted scopes are not implemented,
        // and this is just for illustrative purposes
        var info = { scope: '*' }
        done(null, user, info);
      });
    });
  }
));

In the local strategy, I see there's passReqToCallback option but not sure if the only way I can do this for Bearer is by modifying the module.

AuthorizationError no longer authorized

lastAccess: 1363301546450,
cookie:
{ path: '/',
httpOnly: true,
_expires: Thu Mar 14 2013 19:52:20 GMT-0700 (MST),
originalMaxAge: 14400000 },
passport: { user: '1' },
authorize:
{ wL7qsVg3:
{ protocol: 'oauth2',
client: 1,
redirectURI: 'http://mobi-new.com:8011',

req: [Object] } } }

AuthorizationError: no longer authorized
at module.exports (/Volumes/Fileservers/Mobinnov-1/Projects/medOAuth/oauth2orize/examples/express2/node_modules/oauth2orize/lib/middleware/transactionLoader.js:53:21)
at pass (/Volumes/Fileservers/Mobinnov-1/Projects/medOAuth/oauth2orize/examples/express2/node_modules/oauth2orize/lib/server.js:229:55)
at Server.deserializeClient (/Volumes/Fileservers/Mobinnov-1/Projects/medOAuth/oauth2orize/examples/express2/node_modules/oauth2orize/lib/server.js:237:35)
at /Volumes/Fileservers/Mobinnov-1/Projects/medOAuth/oauth2orize/examples/express2/oauth2.js:33:12
at exports.find (/Volumes/Fileservers/Mobinnov-1/Projects/medOAuth/oauth2orize/examples/express2/db/clients.js:23:20)
at Cursor.nextObject (/Volumes/Fileservers/Mobinnov-1/Projects/medOAuth/oauth2orize/node_modules/mongojs/node_modules/mongodb/lib/mongodb/cursor.js:654:35)
at Cursor.close (/Volumes/Fileservers/Mobinnov-1/Projects/medOAuth/oauth2orize/node_modules/mongojs/node_modules/mongodb/lib/mongodb/cursor.js:960:5)
at Cursor.nextObject (/Volumes/Fileservers/Mobinnov-1/Projects/medOAuth/oauth2orize/node_modules/mongojs/node_modules/mongodb/lib/mongodb/cursor.js:654:17)
at Cursor.nextObject.commandHandler (/Volumes/Fileservers/Mobinnov-1/Projects/medOAuth/oauth2orize/node_modules/mongojs/node_modules/mongodb/lib/mongodb/cursor.js:631:14)
at Db._executeQueryCommand (/Volumes/Fileservers/Mobinnov-1/Projects/medOAuth/oauth2orize/node_modules/mongojs/node_modules/mongodb/lib/mongodb/db.js:1702:5)
127.0.0.1 - - [Thu, 14 Mar 2013 22:52:26 GMT] "POST /dialog/authorize/decision HTTP/1.1" 500 - "http://api.medoauth.com:8080/dialog/authorize?response_type=code&redirect_uri=http%3A%2F%2Fmobi-new.com%3A8011&client_id=mobinnov&type=web_server" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.99 Safari/537.22"
-- session --
{ lastAccess: 1363301546733,
cookie:
{ path: '/',
httpOnly: true,
_expires: Thu Mar 14 2013 19:52:26 GMT-0700 (MST),

originalMaxAge: 14400000 } }

127.0.0.1 - - [Thu, 14 Mar 2013 22:52:26 GMT] "GET /favicon.ico HTTP/1.1" 404 - "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.99 Safari/537.22"

A little question about module

Hello sir. Excuse me but I'd like to ask you a question about your module Passport.
As a student, during my internship I have to provide a client-server solution OAuth2 in Node.js and your module is just perfect. But I'd like to know if it was possible not to go through this validation page and gain access token directly because my solution should be transparant to the user.

I tried to do this but I noticed that because of the variable session.uid, I could not do a POST request directly, but I was obliged to pass through dialog.ejs.

Do you think there is a solution to my concern?

Thank you in advance for your reply.

Sincerely,
Hammou Ahabchane Ayoub

Help with grant password

Not sure if your library has implemented it, but I would like to use the password grant to get a token without having to pop open a window in iOS, (SSO) which will allow you to put in your username and password and in a request object send over the username, password, clientID, clientSecret and receive an access token. This will also help with my previous "auto-approve" ticket....

Oauth2orize with REST API

Hi,

As you may understand it's not a issue. I need some help with using your module with a rest api (express app).

My rest api need to be used with web, mobile and desktop apps. There is no login system so no client login with password. I have only a api key different for each platform (web, mobile and desktop).

The workflow that I have in mind :

  • before using any web service there is a call to https://something.com/oauth2/authorize that only create a token with the api key in the request parameters, save the token in database (mysql here) and return this token.
  • the client (web, mobile and desktop) will store this token
  • make some requests with this token and on the server I'll check if the token is correct the expected response will be sent, if not an error message will be sent.

How can I modify your example to work with my idea and respect the OAuth2 spec ?

Thank you.

Edit:
I have also an application id. So I can use the application id as ClientId and the api key as ClientSecret

Google Playground & Tokens

When using the example provided "as-is" on localhost with Google Oauth 2.0 Playground, the Exchange authorization code for tokens action returns a 400 Bad Request.

You can see the request below.

Request : 

POST /oauth/token HTTP/1.1
Host: localhost:3000
Content-length: 167
content-type: application/x-www-form-urlencoded
user-agent: google-oauth-playground

code=WAe5KFMqOlrCphc1&redirect_uri=https%3A%2F%2Fdevelopers.google.com%2Foauthplayground&client_id=abc123&scope=&client_secret=ssh-secret&grant_type=authorization_code

Answer : 
HTTP/1.1 400 Bad Request
Content-length: 0
Content-type: text/plain

Fork examples into separate project

It would be nice to fork the example projects (there's only one right now, the express project) and modify them, without forking the full development project. This would be useful for writing and running OAuth test servers during application development.

Bearer token life time & decoding token

  1. Is there any example of implementing access_token life time?
  2. Is it a good approach to encode (life_time+user+scope) as an access_token to allow OAuth 2.0 server decode this token to get life_time+user+scope without accessing database?

Is any of this planned to be implemented in oauth2orize?

Rendering Jade view with parameter 'client' fails

Jade rendering fails for:

 res.render('dialog', { transactionID: req.oauth2.transactionID,
                           user: req.user, client: req.oauth2.client });

It seems that the 'client' parameter is the problem. If the parameter name is changed to 'iclient' or something else the view is rendered correctly.

Not that this is a bug or anything just an interesting note.

Client variable showing username and password instead of client information

Firstly, great stuff with all these related projects, they are very very well put together.

I know i am doing something, and it is probably with the way i am calling my API. i am writing some tests and came across and issue when i wanted to write a test to check the client was correct.

I don't think this is anything to do with library itself, so not really an issue per say but i can't seem to find an example to check if my post message is correct. What is a bit odd, is the code actually works, in that i get a token exchanged for my username and password combination, but when i want to verify the client i don't get the correct data.

I am using supertest to test my routes with:

request('http://localhost:43862')
    .post('/oauth/token')
    .type('form')
    .send({ grant_type: 'password' })
    .send({ client_id: 'goodClient' })
    .send({ client_secret: 'secret' })
    .send({ username: '[email protected]' })
    .send({ password: 'badpassword' })
    .expect(401, done);

when i try and access the client variable i get an object back but that contains username and password?

[decision.js] req.scope is undefined

The decision.js documentation explains:

app.post('/dialog/authorize/decision',
       login.ensureLoggedIn(),
       server.decision(function(req, done) {
         return done(null, { scope: req.scope })
}));

I'm playing with the example:

exports.decision = [
  login.ensureLoggedIn(),
  server.decision()
]

It's changed to:

exports.decision = [
       login.ensureLoggedIn(),
       server.decision(function(req, done) {

         //return done(null, { scope: req.scope })
         return done(null, { scope: req.oauth2.req.scope })
       })
];

req.scope is always undefined.
I'm tracing the req object, I found the scope at: req.oauth2.req.scope

Is it alright?

An urgent issue

Hello, Excuse me but I'd like to ask you a question about your module Auth2orize.
As a student, during my internship I have to provide a client-server solution OAuth2 in Node.js and your module is just perfect. But I'd like to know if it was possible not to go through this validation page and gain access token directly because my solution should be transparant to the user.

I tried to do this but I noticed that because of the variable session.uid, I could not do a POST request directly, but I was obliged to pass through dialog.ejs.

Do you think there is a solution to my concern?

Please reply me, I'm a student and my internship ends in a short time, it's very important.

Sincerely,
Hammou Ahabchane Ayoub

Subsequent authorization request

Hi, I've implemented basic OAuth2 flow for both code and token auth flows.
Now, I'd like to enhance it a little bit: when Client redirects User to the authorization endpoint, I would like to check whether the given User has already granted given Client access to the resources for a given scope. If so, I would like not to ask User again, but rather just issue a new token and invalidate the old one.

(of course, in case User is logged out, he will be asked to log in again, but then there will be no "decision" - question "allow"/"deny" - right after successfull sign in, the user agent should be redirected to redirect_uri with a code/access_token).

I guess it should be placed somewhere near https://github.com/jaredhanson/oauth2orize/blob/master/examples/express2/oauth2.js#L100, so after authorizing the client request and before rendering the decision page. But how can I skip the rendering and go straight to issuing grant code/access_token?

Is this supported somehow in oauth2orize?

BTW, thanks for the great code!

3-legged auth

Is it possible to implement 3-legged oauth2 authorization?

Resource Owner Password Credentials flow

Hi,

Does this module support Resource Owner Password Credentials flow ? If yes, how to make it work with this module? I really appreciate if you can post an example.

Thanks!

auto-approve client

I was wondering if you can help me out. Great code by the way! Works great.

I would like to add a column in the clients called autoApprove: true/false
and once the user logs in, before the get the dialog for approve, I would like to be able to check if the client is auto-approved then skip the step about asking them.

line 107 of oauth2.js i can do a if (client.autoApprove) { ....do something... }

it's the "do something" i need a quick hand with if you don't mind.

Using oauth2orize with JS

Hi,
i want to use the oauth2orize server with JS client.
So working scenario will be

  • client will call server
  • server will auto autorize it and send back the code to client call

so in 2nd step i don't want server to use rediret_uri but juts respond back the code.
i know its not a standard flow of authorisation but i need it.
Is there any way i can use it in js app without any post back ?

Fail to obtain access token.

Is there a UG forum for oauth2orize. sorry if this is the wrong spot to post

failed to obtain access token (status: 401 data: Unauthorized)
at /Volumes/Fileservers/Mobinnov-1/Projects/drywall/node_modules/passport-oauth/lib/passport-oauth/strategies/oauth2.js:128:38
at exports.OAuth2.getOAuthAccessToken (/Volumes/Fileservers/Mobinnov-1/Projects/drywall/node_modules/passport-oauth/node_modules/oauth/lib/oauth2.js:160:18)
at passBackControl (/Volumes/Fileservers/Mobinnov-1/Projects/drywall/node_modules/passport-oauth/node_modules/oauth/lib/oauth2.js:105:9)
at IncomingMessage.exports.OAuth2._executeRequest.request.on.callbackCalled (/Volumes/Fileservers/Mobinnov-1/Projects/drywall/node_modules/passport-oauth/node_modules/oauth/lib/oauth2.js:124:7)
at IncomingMessage.EventEmitter.emit (events.js:115:20)
at IncomingMessage._emitEnd (http.js:366:10)
at HTTPParser.parserOnMessageComplete as onMessageComplete
at Socket.socketOnData as ondata
at TCP.onread (net.js:402:27)

500 AuthorizationError: invalid response type

Running the example in examples/express2/ it throws the following error:

500 AuthorizationError: invalid response type
at module.exports (/home/b/node-oauth2/examples/express2/node_modules/oauth2orize/lib/middleware/authorization.js:120:109)
at pass (/home/b/node-oauth2/examples/express2/node_modules/oauth2orize/lib/server.js:262:26)
at pass (/home/b/node-oauth2/examples/express2/node_modules/oauth2orize/lib/server.js:280:9)
at Server._parse (/home/b/node-oauth2/examples/express2/node_modules/oauth2orize/lib/server.js:285:5)
at authorization (/home/b/node-oauth2/examples/express2/node_modules/oauth2orize/lib/middleware/authorization.js:118:12)
at callbacks (/home/b/node-oauth2/examples/express2/node_modules/express/lib/router/index.js:272:11)
at /home/b/node-oauth2/examples/express2/node_modules/connect-ensure-login/lib/ensureLoggedIn.js:50:5
at callbacks (/home/b/node-oauth2/examples/express2/node_modules/express/lib/router/index.js:272:11)
at param (/home/b/node-oauth2/examples/express2/node_modules/express/lib/router/index.js:246:11)
at pass (/home/b/node-oauth2/examples/express2/node_modules/express/lib/router/index.js:253:5)

Discussion about supporting different token creation strategies (i.e: MAC Tokens)

Although the precise creation/contents of a token is out of the spec of oauth2* afaik, I like your opinion on whether oauth2orize could/should support different kind of token creation-strategies (among which MAC tokens) instead of only bearer-tokens.

To be honest, MAC-tokens may be overkill in lots of situations, especially considering more and more API's seem to be getting SSL-only nowadays. On the other hand, it would be nice to have them onboard.

What do you think?

*) http://tools.ietf.org/html/rfc6750 (bearer tokens) is separated with reason from the spec: http://tools.ietf.org/html/rfc6749

support for grant_type="refresh_token"

Apologies for spamming with some 'issues'.

As far as I can see, exchanging a refreshtoken for an accesstoken is not yet supported. (section 6 of RFC 6749). Is this correct? I could take a stab at a pull request if there's interest.

Since this is part of the spec it seems to me that this would fit within oauth2orize as opposed to a separate middleware module

Renaming the OAuth parameters

Is it somehow possible to rename the parameters like:

  • client_id
  • response_type
  • redirect_uri

So that for example the client_id is key instead.

Keep asking for approval

I love this code, great job!
Besides my other issue already in queue, I noticed that even though my session is active, it keeps asking for approval.
Is there somewhere that I should be adding in my own check to see if the user has approved it? or is that a bug in your code?
Please advise.

Session lost

I am running an oauth2orize (https) server,

When requesting authentication with an oauth2-client (http) I loose the session on the oauth2orize if already logged on the server.

Is it normal?

UPDATE
Closed issue. It has do to with multiple express apps on localhost loosing sessions.

implicit grant - Access-Control-Allow-Origin

Can I do this implicit grant with a POST to /oauth/token Endpoint including the REQUIRED client_id and response_type=token ?

i tried to to do it to get the access_token in the callback URL. But...

XMLHttpRequest cannot load http://www.duo.sallespro.com.br:3000/oauth/token?response_type=token&client_id=abc123&redirect_uri=http://www.duo.sallespro.com.br/youhave/seedy2/app/ot.html. Origin http://www.duo.sallespro.com.br is not allowed by Access-Control-Allow-Origin.

is this because of the port number / not setting the headers / is it right server ENDPOINT ?

what ?

[]'s Rafael

Oauth 2.0 for my own mobile client.

Do You support Resource Owner Password Credential Authorisation Grant as mentioned in 1.3.3 in the Oauth 2.0 http://www.rfc-editor.org/rfc/rfc6749.txt
I am looking to authenticate my own mobile client using your oauth2rize but I am getting little confused regarding the flow of authentication. Can you please help me out.

An example or just a simple gist how to achieve this would be of great help. Thanks.

500 ReferenceError: jade is not defined

Hi,
i am using oauth2orize in express3. i am getting below error on authorization to show dialog.

Express
500 ReferenceError: jade is not defined
at eval (eval at (/Users/ankitpatial/Documents/projects/node-apps/oauth2orize/examples/express3-server-client-example/server-app/node_modules/jade/lib/jade.js:169:30), :2:1)
at Object.exports.render (/Users/ankitpatial/Documents/projects/node-apps/oauth2orize/examples/express3-server-client-example/server-app/node_modules/jade/lib/jade.js:205:14)
at View.exports.renderFile as engine
at View.render (/Users/ankitpatial/Documents/projects/node-apps/oauth2orize/examples/express3-server-client-example/server-app/node_modules/express/lib/view.js:75:8)
at Function.app.render (/Users/ankitpatial/Documents/projects/node-apps/oauth2orize/examples/express3-server-client-example/server-app/node_modules/express/lib/application.js:503:10)
at ServerResponse.res.render (/Users/ankitpatial/Documents/projects/node-apps/oauth2orize/examples/express3-server-client-example/server-app/node_modules/express/lib/response.js:721:7)
at exports.authorization (/Users/ankitpatial/Documents/projects/node-apps/oauth2orize/examples/express3-server-client-example/server-app/auth/oauth2_grant_code.js:129:13)
at callbacks (/Users/ankitpatial/Documents/projects/node-apps/oauth2orize/examples/express3-server-client-example/server-app/node_modules/express/lib/router/index.js:161:37)
at /Users/ankitpatial/Documents/projects/node-apps/oauth2orize/examples/express3-server-client-example/server-app/node_modules/oauth2orize/lib/middleware/authorization.js:161:11
at pass (/Users/ankitpatial/Documents/projects/node-apps/oauth2orize/examples/express3-server-client-example/server-app/node_modules/oauth2orize/lib/server.js:184:30)

Demo of grant types and other useful information

I've been working on my built upon oauth2orize version which is OAuth2orizeRecipes for a while and I now have a tutorial/demo of the grant types running on Heroku here. My hope is that it helps people understand how OAuth2 and oauth2orize works.

I also put good information on how to operate the grant types here and I put some basic security scenarios with 2 legged here.

Feel free to take whatever you want from it if you find any of it useful. Thanks for all the hard work of oauth2orize and passport and happy hacking :-)

Access-Control-Allow-Origin

hi Jared,

i am using the example oauth2orize server and trying to connect a web page(Chrome user agent).
I am stuck in the exchange of the Authorization Code to the token.
I connect and receive the code in the redirect_url, but when i try to POST to /oauth/token, i get Access-Control-Allow-Origin error.

I tryed to set the headers , as shown below, but no success ! what am I missing ?

xhr.setRequestHeader('Access-Control-Allow-Origin', "localhost");
xhr.setRequestHeader('Accept', "application/x-www-form-urlencoded");

this is the client gist.

git://gist.github.com/4233701.git

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.