11

I am new to PassportJS and AngularJS and I have a doubt about how to proceed with this authorization.

I have Spring REST API Secured by Oauth2, but I have to send together 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.

4
  • For the OAuth2 part, I assume you have seen: github.com/jaredhanson/oauth2orize/tree/master/examples/… Commented Aug 17, 2013 at 13:51
  • 1
    Sorry, disregard my comment, I miss read, my link is for the OAuth2 server which you already have and want to connect to. I'm not at the client yet. Commented Aug 17, 2013 at 13:58
  • Here's an example app using everyauth: github.com/ganarajpr/express-angular Commented Jan 5, 2014 at 13:21
  • 1
    I'm not sure how this is an Angular question... Commented Jul 28, 2014 at 6:09

1 Answer 1

7

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

No. There are other options, such as:

Here is an example of how to use passport:

// Express using passport-local
// This code is adaptation of examples/express3 from https://github.com/jaredhanson/passport-local


// configure Express
app.configure(function() {
// ...
app.use(express.session({
// The domain should start with a dot, as this allows the subdomain.
domain: '.app.local',
secret: 'keyboard cat'
}));

// Enable cors.
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
next();
});

// ...
});

app.get('/account', ensureAuthenticated, function(req, res){
// Return the current user's info
res.json(req.user);
});

References

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.