lundi 13 février 2017

Logging in programmatically with nodebb using Oauth2

Vote count: 0

So I am designing an app with nodejs and I need to create a user forum. I decided against reinventing the wheel so I choose to use nodebb. However, my app has a user log in and so does node bb and I want the user to be logged in automatically in nodebb once logged into my site. I have never used oauth2orize before but this is what I came up with:

       server.grant(oauth2orize.grant.code(function(client, redirectUri, user, ares, callback) {
          // Create a new authorization code
          var code = new Code({
            value: uid(16),
            clientId: client._id,
            redirectUri: redirectUri,
            userId: user._id
          });

          // Save the auth code and check for errors
          code.save(function(err) {
            if (err) { return callback(err); }

            callback(null, code.value);
          });
        }));


        // Exchange authorization codes for access tokens
        server.exchange(oauth2orize.exchange.code(function(client, code, redirectUri, callback) {
            console.log(client, code, redirectUri)
          Code.findOne({ value: code }, function (err, authCode) {
            if (err) { return callback(err); }
              console.log(authCode.clientId,client._id);
            if (authCode === undefined) { return callback(null, false); }
            if (client._id.toString() !== authCode.clientId) { return callback(null, false); }
            //if (redirectUri !== authCode.redirectUri) { return callback(null, false); }

            // Delete auth code now that it has been used
            authCode.remove(function (err) {
              if(err) { return callback(err); }

              // Create a new access token
              var token = new Token({
                value: uid(256),
                clientId: authCode.clientId,
                userId: authCode.userId
              });

              // Save the access token and check for errors
              token.save(function (err) {
                if (err) { return callback(err); }

                callback(null, token);
              });
            });
          });
        }));


        // User authorization endpoint
        /*module.exports.authorization = [
          server.authorization(function(clientId, redirectUri, callback) {
              console.log(clientId);
            Client.findOne({ id: clientId }, function (err, client) {
              if (err) { console.log("I ran herea");return callback(err); }

              return callback(null, client, redirectUri);
            });
          }),
          function(req, res){
              console.log("I ran hereb")
            res.render('dialog', { transactionID: req.oauth2.transactionID, user: req.user, client: req.oauth2.client });
          }
        ]*/

        setCodes = function(client, user, redirectUri, Code){
            console.log('starting...')
            var code = new Code();
                code.value = uid(16),
                code.clientId = client.id,
                code.userId = user._id
            code.save(function(error, success){
                if(!success){
                    console.log(Code.find({}), 'I ran hered', code, error);
                }
            });
            //console.log(code);
            //Code.find({}, function(error, success){if(success){console.log(success, "george")}});
        }


        module.exports.authorization = [
            server.authorization(function(clientId, redirectUri, callback) {
                Client.findOne({ id: clientId }, function (err, client) {
                  if (err) { console.log("I ran herea");return callback(err); }
                  return callback(null, client, redirectUri);
                });
              }, function (client, user, redirectUri, done) {
                console.log(redirectUri);
                setCodes(client, user, redirectUri, Code);
                /*var code = new Code({
                    value: uid(16),
                    clientId: client.id,
                    redirectUri: redirectUri,
                    userId: user._id
                });*/
                Code.find({
                    clientId: client.id,
                    userId: user._id
                }, function (err, codes) {
                    console.log(codes);
                    if (err) { console.log("second"); return done(err); }
                    if (codes.length > 0) {
                        console.log("third")
                        return done(null, true);
                    } else {
                        console.log('I ran here fourth');
                        return done(null,false);
                    }
                });
            })
        ]

        // Application client token exchange endpoint
        module.exports.token = [
          server.token(),
          server.errorHandler()
        ]



        module.exports.getNodebbUsers = function(req, res){
            console.log(req.body.token);
            Token.find({value : req.body.token}, function(error, user){
                userId = user[0].userId;
                if(!error){
                    User.find({_id : userId}, function(error, user){
                        console.log(userId);
                        if(!error){
                            res.json({
                                username : user[0].userName,
                                email : user[0].email,
                                id : user[0]._id
                            })
                        } else {
                            console.log(error);
                        }
                    })
                }
            })

        }

This is my oauth2orize block of code and it works well on postman.

However, this is the plugin on nodebb that I was supposed to edit and use. I have already edited it I am really stumped now.

var constants = Object.freeze({
                        type: 'oauth2', // Either 'oauth' or 'oauth2'
                        name: 'create-and-login-user',  // Something unique to your OAuth provider in lowercase, like "github", or "nodebb"
                        oauth: {
                            requestTokenURL: '',
                            accessTokenURL: '',
                            userAuthorizationURL: '',
                            consumerKey: '',
                            consumerSecret: ''
                        },
                        oauth2: {
                            authorizationURL: '/api/oauth2/authorize',
                            tokenURL: '/api/oauth2/token',
                            clientID: 'nodeBB_logIn',
                            clientSecret: 'change_this_later'
                        },
                        userRoute: '/api/oauth2/users'  // This is the address to your app's "user profile" API endpoint (expects JSON)
                    }),
                    configOk = false,
                    OAuth = {}, passportOAuth, opts;

                if (!constants.name) {
                    winston.error('[sso-oauth] Please specify a name for your OAuth provider (library.js:32)');
                } else if (!constants.type || (constants.type !== 'oauth' && constants.type !== 'oauth2')) {
                    winston.error('[sso-oauth] Please specify an OAuth strategy to utilise (library.js:31)');
                } else if (!constants.userRoute) {
                    winston.error('[sso-oauth] User Route required (library.js:31)');
                } else {
                    configOk = true;
                }

                OAuth.getStrategy = function(strategies, callback) {
                    if (configOk) {
                        passportOAuth = require('passport-oauth')[constants.type === 'oauth' ? 'OAuthStrategy' : 'OAuth2Strategy'];

                        if (constants.type === 'oauth') {
                            // OAuth options
                            opts = constants.oauth;
                            opts.callbackURL = nconf.get('url') + '/auth/' + constants.name + '/callback';

                            passportOAuth.Strategy.prototype.userProfile = function(token, secret, params, done) {
                                this._oauth.get(constants.userRoute, token, secret, function(err, body, res) {
                                    if (err) { return done(new InternalOAuthError('failed to fetch user profile', err)); }

                                    try {
                                        var json = JSON.parse(body);
                                        OAuth.parseUserReturn(json, function(err, profile) {
                                            if (err) return done(err);
                                            profile.provider = constants.name;

                                            done(null, profile);
                                        });
                                    } catch(e) {
                                        done(e);
                                    }
                                });
                            };
                        } else if (constants.type === 'oauth2') {
                            // OAuth 2 options
                            opts = constants.oauth2;
                            opts.callbackURL = nconf.get('url') + '/auth/' + constants.name + '/callback';

                            passportOAuth.Strategy.prototype.userProfile = function(accessToken, done) {
                                this._oauth2.get(constants.userRoute, accessToken, function(err, body, res) {
                                    if (err) { return done(new InternalOAuthError('failed to fetch user profile', err)); }

                                    try {
                                        var json = JSON.parse(body);
                                        OAuth.parseUserReturn(json, function(err, profile) {
                                            if (err) return done(err);
                                            profile.provider = constants.name;

                                            done(null, profile);
                                        });
                                    } catch(e) {
                                        done(e);
                                    }
                                });
                            };
                        }

                        opts.passReqToCallback = true;

                        passport.use(constants.name, new passportOAuth(opts, function(req, token, secret, profile, done) {
                            OAuth.login({
                                oAuthid: profile.id,
                                handle: profile.displayName,
                                email: profile.emails[0].value,
                                isAdmin: profile.isAdmin
                            }, function(err, user) {
                                if (err) {
                                    return done(err);
                                }

                                authenticationController.onSuccessfulLogin(req, user.uid);
                                done(null, user);
                            });
                        }));

                        strategies.push({
                            name: constants.name,
                            url: '/auth/' + constants.name,
                            callbackURL: '/auth/' + constants.name + '/callback',
                            icon: 'fa-check-square',
                            scope: (constants.scope || '').split(',')
                        });

                        callback(null, strategies);
                    } else {
                        callback(new Error('OAuth Configuration is invalid'));
                    }
                };

                OAuth.parseUserReturn = function(data, callback) {
                    // Alter this section to include whatever data is necessary
                    // NodeBB *requires* the following: id, displayName, emails.
                    // Everything else is optional.

                    // Find out what is available by uncommenting this line:
                    // console.log(data);

                    var profile = {};
                    profile.id = data.id;
                    profile.displayName = data.name;
                    profile.emails = [{ value: data.email }];

                    // Do you want to automatically make somebody an admin? This line might help you do that...
                    // profile.isAdmin = data.isAdmin ? true : false;

                    // Delete or comment out the next TWO (2) lines when you are ready to proceed
                    process.stdout.write('===\nAt this point, you\'ll need to customise the above section to id, displayName, and emails into the "profile" object.\n===');
                    return callback(new Error('Congrats! So far so good -- please see server log for details'));

                    callback(null, profile);
                }

                OAuth.login = function(payload, callback) {
                    OAuth.getUidByOAuthid(payload.oAuthid, function(err, uid) {
                        if(err) {
                            return callback(err);
                        }

                        if (uid !== null) {
                            // Existing User
                            callback(null, {
                                uid: uid
                            });
                        } else {
                            // New User
                            var success = function(uid) {
                                // Save provider-specific information to the user
                                User.setUserField(uid, constants.name + 'Id', payload.oAuthid);
                                db.setObjectField(constants.name + 'Id:uid', payload.oAuthid, uid);

                                if (payload.isAdmin) {
                                    Groups.join('administrators', uid, function(err) {
                                        callback(null, {
                                            uid: uid
                                        });
                                    });
                                } else {
                                    callback(null, {
                                        uid: uid
                                    });
                                }
                            };

                            User.getUidByEmail(payload.email, function(err, uid) {
                                if(err) {
                                    return callback(err);
                                }

                                if (!uid) {
                                    User.create({
                                        username: payload.handle,
                                        email: payload.email
                                    }, function(err, uid) {
                                        if(err) {
                                            return callback(err);
                                        }

                                        success(uid);
                                    });
                                } else {
                                    success(uid); // Existing account -- merge
                                }
                            });
                        }
                    });
                };

                OAuth.getUidByOAuthid = function(oAuthid, callback) {
                    db.getObjectField(constants.name + 'Id:uid', oAuthid, function(err, uid) {
                        if (err) {
                            return callback(err);
                        }
                        callback(null, uid);
                    });
                };

                OAuth.deleteUserData = function(data, callback) {
                    async.waterfall([
                        async.apply(User.getUserField, data.uid, constants.name + 'Id'),
                        function(oAuthIdToDelete, next) {
                            db.deleteObjectField(constants.name + 'Id:uid', oAuthIdToDelete, next);
                        }
                    ], function(err) {
                        if (err) {
                            winston.error('[sso-oauth] Could not remove OAuthId data for uid ' + data.uid + '. Error: ' + err);
                            return callback(err);
                        }

                        callback(null, data);
                    });
                };

                module.exports = OAuth;
            }(module));

From my understanding of how this works: nodebb makes a call to my authorization end point and I check if the client is correct and grant it an access code, it then visits my token end point and exchanges this access code for a token. I take it to the user end point and hands it my users credentials to log in. I think I am wrong since it is not working and I think the issue could be from the name: create-and-login-user that I am using but I don't see how to improve on the code I have written above

asked 32 secs ago

Let's block ads! (Why?)



Logging in programmatically with nodebb using Oauth2

Aucun commentaire:

Enregistrer un commentaire