1

所以我正在用 nodejs 设计一个应用程序,我需要创建一个用户论坛。我决定不重新发明轮子,所以我选择使用 nodebb。但是,我的应用程序有一个用户登录,节点 bb 也是如此,我希望用户在登录我的站点后自动登录到 nodebb。我以前从未使用过 oauth2orize ,但这就是我想出的:

       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);
              });
            });
          });
        }));

        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);

                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);
                        }
                    })
                }
            })

        }

这是我的 oauth2orize 代码块,它在邮递员上运行良好。

但是,这是我应该编辑和使用的 nodebb 上的插件。我已经编辑了它,我现在真的很难过。

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));

根据我对其工作原理的理解:nodebb 调用我的授权端点,我检查客户端是否正确并授予它访问代码,然后它访问我的令牌端点并将此访问代码交换为令牌。我将它带到用户端点并将我的用户凭据交给它以登录。我认为我错了,因为它不起作用,我认为问题可能来自名称:我正在使用的 create-and-login-user但我看不到如何改进我上面写的代码。

我不清楚回调 uri 的作用,为什么将名称回调附加到它,以及我的应用程序上是否必须有此 url 的端点。

好的,我取得了一些进展,但我遇到了这个错误:

https://www.dropbox.com/s/hm711i99iex4v1x/Screenshot%202017-02-13%2021.57.07.png?dl=0

它与回调 uri 有关。我是否应该为它提供一个端点,如果是,为什么它不指向我的应用程序端口号,而是指向 nodebb 的端口号

4

0 回答 0