Logging in programmatically from another application



  • I have an application with a local sign up and login with nodebb as the forum.

    I am able to sign up users and log them in but when I click on the link that directs me to nodebb forum, the users are not signed on. The response I get from the server is all ok only it says that status is offline.

    I expected that the once the user is signed on, he should stay signed on till his session expires. I don't know what I am doing wrong and I don't understand how a user is logged on yet not logged on.


  • Admin

    Ah, looks like you started a new topic, good.

    Response as before:

    The recommended method of sharing sessions between two separate and distinct applications is through OAuth2. We recommend this approach because NodeBB maintains its own user records, so that we can keep track of user-related metrics and other data. Relying on another database would be tricky, prone to breaking, and quite possibly dangerous.

    Luckily, it's quite straightforward to get things working with OAuth2!

    The first step is getting your application to expose an OAuth2 endpoint. If you're running a Node.js based app, you can use a module called OAuth2orize.

    Once that is set up, you'll want to take a look at the SSO plugin skeleton for customised OAuth deployments -- nodebb-plugin-sso-oauth. You'll take this plugin, fork it, and modify it to communicate with your OAuth endpoint.

    Once everything is working properly, you should be able to register and log in/out via your web app.



  • @julian thanks for the prompt response. I will try it out.



  • Hi guys
    I have created a new project using nodejs, i have given a reference link of nodeBB forum but still it asks for a login to nodeBB
    My question is how to login using my existing username and password to nodebb,can anyone tell me in which file i have to change or add something


  • Admin

    @Nitin-Jadhav Please read my above post.



  • @julian i already installed auth0 plugin but still it asks for login , also created a jsonwebtoken



  • Hi @julian I have been working on this for almost a full day. I have written my oath2orize endpoints and added the constants in the plug in as shown below

    check my next post for my oauth2orize codes

    and a snippet of my library for the plugin

    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: 'http://localhost:3000/api/oauth2/authorize',
    			tokenURL: 'http://localhost:3000/api/oauth2/token',
    			clientID: 'nodeBB_logIn',
    			clientSecret: 'change_this_later'
    		},
    		userRoute: 'http://localhost:3000/api/oauth2/users'	// This is the address to your app's "user profile" API endpoint (expects JSON)
    	})
    

    When I click on the link to nodebb nothing happens. I want to know does nodebb make a get request when I click on the link after installing the plug-in. I am a bit confused now.

    I have checked my codes with postman and everything is working fine. Nodebb does not log the output for me to see my results everytime.



  • any chance @julian or someone else who has done this would help push me the right direction.

    I think I am doing everything right but there is no message whatsoever on nodebb's log to see if I am mistaken.

    PS: I just noticed something that could be causing problems for me. What is the name required supposed to do. I noticed it is being used in strategies.push 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.

     // Register authorization code grant type
            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);
                  });
                });
              });
            }));
    
            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);
                    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);
                            }
                        })
                    }
                })
    
            }
    

    btw this is my code above. I could do with some help seeing I have pushed myself to the limit.

    Why does the callback uri have callback appended to its name and should this be an endpoint in my app?

    I also intend posting my solutions once this starts working to save someone the wasted hours I spent reading, debugging and hacking my codes.


  • Admin

    @jewa name is something unique, as the comment indicates. For example, if your site is "Example Widgets and Stuff", use something like example.

    When the end user clicks on the link in the login/registration page, it should send them to /auth/example (if example was the name, as above), which would redirect them to the authorizationURL as defined in your plugin.

    From there, it's up to your site to send them back with the proper token or code.



  • @julian I see. I thought all the user needed to do was to log in on my site and when he clicks on the forum link on my website there would be a handshake between my website and nodebb and then sign him on. I didn´t know he had to click on the log in/register link on nodebb.

    I still have some questions though:

    1. So I have to make a page and endpoint for /auth/example right? I believe oauth2orize would be responsible for the redirection.

    2. I read your code and you always append callback if I am to make an endpoint or page it would never be executed because I would have /auth/example whilst the plugin would contain /auth/example/callback.

    I think the process is a bit clearer to me right now. I have been programming javascript and node for about 3 months which is not much admittedly but this is hands down the most complicated thing I have come across as I don't have a full grasp of the whole process and it has very little to do with your programming skills imo and more to do with how much you understand libraries and all.



  • @jewa so I am getting there. I finally noticed a button- alternative registration/log in.

    I clicked it and hurrah I got an error that should help at last:

    It still has to do with the call back uri. I really don't know what to do next since the url points to nodebb and not to me so I can't create an endpoint or something.

    I am not so sure but I have a little idea of what my problem is but even at that I don't know how to solve it. I traced the error logs to an oauth2 file and it requests that the page returns between 200 and 299 status code but mine is returning 500. How can I return 200 when the link is not on my site. I am really getting confused.



  • @julian this is to hoping you'd help me complete this hurdle. As shown in the picture, I am getting the code but I don't know what to make of the error I am getting. I tried to deploy nodebb on Heroku since the error could possibly be because I am using local host but I ran into other issues with nodebb crashing on Heroku and that is like opening two battle fronts needlessly. I think I would proceed one step at a time.

    Like I said, when I run my authorizationUrl on my browser, it gives an error 401 with the grant code. The resource I saw online said this was perfectly normal. If I copy the code and make a post request for my token on PostMan, it exchanges the code for a token and then I complete by posting to my user endpoint to get user details so I think the whole process is working and possibly I am just one correction away from saving you the stress of having to answer someone else trying to do this on node js because as I mentioned earlier, I will write down what worked for me and the resources I used.



  • @julian I have been patiently waiting for a response. However, I tried to install nodebb on heroku. It was a painful process but I came to my wits ends when I got to the launch page. It says congratulations your nodebb has been setup but won't get past that page. It returns a 404 error whilst making a get request for /admin.

    Here are the logs

    2017-02-16T04:21:11.458766+00:00 app[web.1]:
    2017-02-16T04:21:11.458782+00:00 app[web.1]: Starting NodeBB
    2017-02-16T04:21:11.458916+00:00 app[web.1]: "./nodebb stop" to stop the NodeBB server
    2017-02-16T04:21:11.458977+00:00 app[web.1]: "./nodebb log" to view server output
    2017-02-16T04:21:11.459020+00:00 app[web.1]: "./nodebb restart" to restart NodeBB
    2017-02-16T04:21:11.464363+00:00 app[web.1]: (node:4) DeprecationWarning: Calling an asynchronous function without callback is deprecated.
    2017-02-16T04:21:11.464621+00:00 app[web.1]: (node:4) DeprecationWarning: Calling an asynchronous function without callback is deprecated.
    2017-02-16T04:21:11.466271+00:00 app[web.1]: TypeError: Cannot read property 'apply' of undefined
    2017-02-16T04:21:11.466272+00:00 app[web.1]: at /app/node_modules/async/lib/async.js:760:22
    2017-02-16T04:21:11.466273+00:00 app[web.1]: at /app/node_modules/async/lib/async.js:166:37
    2017-02-16T04:21:11.466274+00:00 app[web.1]: at /app/node_modules/async/lib/async.js:718:13
    2017-02-16T04:21:11.466274+00:00 app[web.1]: at async.forEachOf.async.eachOf (/app/node_modules/async/lib/async.js:233:13)
    2017-02-16T04:21:11.466275+00:00 app[web.1]: at _parallel (/app/node_modules/async/lib/async.js:717:9)
    2017-02-16T04:21:11.466276+00:00 app[web.1]: at Object.async.parallel (/app/node_modules/async/lib/async.js:731:9)
    2017-02-16T04:21:11.466277+00:00 app[web.1]: at launch (/app/install/web.js:121:8)
    2017-02-16T04:21:11.466277+00:00 app[web.1]: at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
    2017-02-16T04:21:11.466278+00:00 app[web.1]: at next (/app/node_modules/express/lib/router/route.js:131:13)
    2017-02-16T04:21:11.466279+00:00 app[web.1]: at Route.dispatch (/app/node_modules/express/lib/router/route.js:112:3)
    2017-02-16T04:21:11.996384+00:00 heroku[web.1]: Process exited with status 0
    2017-02-16T04:21:12.007390+00:00 heroku[web.1]: State changed from up to crashed
    2017-02-16T04:21:12.340823+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/admin" host=xxx.herokuapp.com request_id=eb7cf3c5-60db-47a6-ba5f-11685c6d62a2 fwd="88.8.42.95" dyno= connect= service= status=503 bytes=


  • Global Moderator

    @jewa what Node version? Try Node 6 if you're on a newer version.



  • @PitaJ I am on node 6.9.2. I will uninstall that and install node 6.0.0.

    Update I have tried it still returns the same error.


  • Global Moderator

    @jewa you shouldn't need to downgrade then. Any version of Node 6.x.x should work.


  • Admin

    @jewa That error doesn't seem related to logging in programmatically... sounds like you have a plugin or theme installed that relies on async v1... are you on the develop branch?



  • @julian I am on nodebb version 1.4.3 not sure if that is develop branch as I am not so good with git. Yes it is not related. I just wanted to isolate the cause of my failure to log in programmatically by hosting on Heroku and trying it from there.

    I followed the steps here: https://community.nodebb.org/topic/9049/getting-nodebb-and-plugins-setup-with-heroku-and-mongodb

    and then modified web.js line 34 inside the install folder to port = process.env.PORT || port; Otherwise, it would load at port 4567 which was always failing. I think I also added process.env.PORT to line 145 in loader.js but I don't think that changed anything much. It only started nodebb when I modified web.js



  • @julian @pitaJ So I burnt the whole thing down. Cloned version 1.3.0 and re-installed. It broke down without modifying web.js so I modified it and it gave me the same error as before. What do I do?


  • Admin

    Do not use Heroku as that is not a standard deployment environment for us.


Log in to reply
 

Looks like your connection to NodeBB was lost, please wait while we try to reconnect.