a simple web app with node

Upload: sebastian-gonzalez

Post on 15-Feb-2018

217 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/23/2019 A Simple Web App With Node

    1/25

    ASimple Web App With Node.js,Express, Bootstrap & Stormpath -- in 15

    Minutes

    Here at Stormpath we Node.js its so much fun to build with! Weve built several libraries to

    help node developers achieve user management nirvana in your applications.

    If youve built a web app before, you know that all the user stuff is a royal pain. Stormpath gives

    developers all that user stuff out-of-the-box (https://docs.stormpath.com/nodejs/express/) so you

    can get on with what you really care about your app! By the time youre done with this tutorial ( < 15

    minutes, I promise), youll have a fully-working Express app.

    We will focus on our Express-Stormpath library (https://github.com/stormpath/stormpath-express) to

    roll out a simple Express.js web application, with a complete user registration and login system, with

    these features:

    Login and Registration pages

    Password reset workflows

    A profile page for your logged in users

    A customizable home pageThe ability to add other Stormpath features in our Express-Stormpath library (API

    authentication, SSO, social login, and more)

    In this demo we will be using Express 4.0, well discuss some of the great features of Express 4.0 as

    we go along. I will be using my Mac, the Terminal app, and Sublime Text for a text editor.

    What is Stormpath?Stormpath is an API service that allows developers to create, edit, and securely store user accounts

    and user account data, and connect them with one or multiple applications. Our API enables you to:

    Authenticate and authorize your users

    Store data about your users

    Perform password and social based login

    Send password reset messages

    Issue API keys for API-based web apps

    And much more! Check out our Product Documentation (https://docs.stormpath.com/home/)

    In short: we make user account management a lot easier, more secure, and more scalable than what

    youre probably used to.

    Ready to get started? Register for a free developer account at https://api.stormpath.com/register

    (https://api.stormpath.com/register)

    by Robert Damphousse on October 27 2014

    https://api.stormpath.com/registerhttps://docs.stormpath.com/nodejs/express/https://api.stormpath.com/registerhttps://docs.stormpath.com/home/https://github.com/stormpath/stormpath-expresshttps://docs.stormpath.com/nodejs/express/
  • 7/23/2019 A Simple Web App With Node

    2/25

    Start your projectGot your Stormpath developer account? Great! Lets get started.. vroom vroom

    If you dont already have Node.js on your system you should head over to https://nodejs.org

    (https://nodejs.org) and install it on your computer. In our examples we will be using a Mac, all

    commands you see should be entered in your Terminal (without the $ in front thats a symbol to let

    you know that these are terminal commands)Step one is to create a folder for this project and change into that directory:

    $ mkdir mywebapp

    $ cd mywebapp

    Now that we are in the folder we will want to create a package.json file for this project. This file is used

    by Node.js to keep track of what libraries (aka modules) your project depends on. To create the file:

    $ npm init

    You will be asked a series of questions, for most of them you can just press enter to allow the default

    value to be used. Here is what I chose, I decided to call my main file app.js, I set my own

    description and set the license to MIT everything else I just pressed enter on:

    Press ^C at any time to quit.

    name: (mywebapp)

    version: (0.0.0)description: Website for my new app

    entry point: (index.js) app.js

    test command:

    git repository:

    keywords:

    author:

    license: (ISC) MIT

    About to write to /private/tmp/mywebapp/package.json:

    {

    "name": "mywebapp",

    "version": "0.0.0",

    "description": "Website for my new app",

    "main": "app.js",

    "scripts": {

    "test": "echo \"Error: no test specified\" && exit 1"

    },

    "author": "",

    "license": "MIT"

    }

    Is this ok? (yes) yes

    https://nodejs.org/
  • 7/23/2019 A Simple Web App With Node

    3/25

    With that I will now have a package.json file in my folder. I can take a look at whats in it:

    $ cat package.json

    {

    "name": "mywebapp",

    "version": "0.0.0",

    "description": "Website for my new app", "main": "app.js",

    "scripts": {

    "test": "echo \"Error: no test specified\" && exit 1"

    },

    "author": "",

    "license": "MIT"

    }

    Looks good! Now lets install the libraries we want to use. You can install them all with this command:

    $ npm i save express expressstormpath jade forms csurf xtend

    The save option will add this module to your dependencies in package.json. Here is what each

    module does:

    Express.js (http://expressjs.com/) is the web framework that everything else is built on

    Express-stormpath (https://github.com/stormpath/stormpath-express) provides convenience

    features that can be tied in to the Express app, making it very easy to use Stormpaths features

    in ExpressJade (http://jade-lang.com/) is a templating engine for writing HTML pages

    Forms (https://github.com/caolan/forms) is a module that will take the pain out of validating

    HTML forms

    Csurf (https://github.com/expressjs/csurf) adds CSRF protection

    (http://en.wikipedia.org/wiki/Cross-site_request_forgery) to our forms

    Xtend is a utility library that makes it easy to copy properties from one JavaScript object to

    another.

    Gather your API Credentials and ApplicationHrefThe connection between your app and Stormpath is secured with API Key Pair. You will provide

    these keys to your web app and it will use them when it communicates with Stormpath. You can

    download your API key pair in our Admin Console (https://api.stormpath.com). After you login you can

    download your API key pair from the home page, it will download the apiKey.properties file we will

    use this in a moment.

    While you are in the Admin Console you want to get the href for your default Stormpath Application. InStormpath, an Application object is used to link your web app to your user stores inside Stormpath. All

    new developer accounts have an app called My Application. Click on Applications in the Admin

    Console, then click on My Application. On that page you will see the Href for the Application. Copy

    this we will need it shortly.

    https://api.stormpath.com/http://en.wikipedia.org/wiki/Cross-site_request_forgeryhttps://github.com/expressjs/csurfhttps://github.com/caolan/formshttp://jade-lang.com/https://github.com/stormpath/stormpath-expresshttp://expressjs.com/
  • 7/23/2019 A Simple Web App With Node

    4/25

    Writing the application entry (app.js)Its time to create app.js, this will be the entry point for your server application. You can do that from

    Sublime Text or you can do this in the terminal:

    $ touch app.js

    Now open that file in Sublime Text and put the following block of code in it:

    var express = require('express');

    var stormpath = require('expressstormpath');

    var app = express();

    app.set('views', './views');

    app.set('view engine', 'jade');

    var stormpathMiddleware = stormpath.init(app, {

    apiKeyFile: '/Users/robert/.stormpath/apiKey.properties',

    application: 'https://api.stormpath.com/v1/applications/xxx',

    secretKey: 'some_long_random_string',

    expandCustomData: true,

    enableForgotPassword: true

    });

    app.use(stormpathMiddleware);

    app.get('/', function(req, res) {

    res.render('home', {

    title: 'Welcome'

    });

    });

    app.listen(3000);

    Youll need to set the location of apiKeyFile to be the location on your computer where you saved the

    file. You also need to set the application href to be the one that you looked up earlier.

    The secretKey value should be changed as well, this will be used as a key for encrypting any

    cookies that are set by this webapp. I suggest using a long, random string of any type of character.

    In this example weve enabled some stormpath-specific options, they are:

    The password reset flow via enableForgotPassword this will enable a password reset page at

    /forgot

    Auto-expansion of custom data this will come in handy later when we build the profile page

    There are many more options that can be passed, and we wont cover all of them in this demo.Please seee the Express-Stormpath Documentation

    (http://docs.stormpath.com/nodejs/express/index.html) for a full list

    http://docs.stormpath.com/nodejs/express/index.html
  • 7/23/2019 A Simple Web App With Node

    5/25

    Create your home pageLets get the easy stuff out of the way: your home page. Create a views directory and then create a

    Jade file for the home page:

    $ mkdir views

    $ touch views/home.jade

    Now open that file in Sublime Text and put the following in it:

    html

    head

    title=title

    link(href='//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css', re

    l='stylesheet')

    body

    div.container div.jumbotron

    h1 Hello!

    if user

    p Welcome, #{user.fullName}

    p

    a.small(href="profile") Edit my profile

    a.btn.btnprimary(href="/logout") Logout

    else

    p Welcome to my app, ready to get started? p

    a.btn.btnprimary(href="/login") Login now

    p

    span.small Don't have an account?

    span

    a.small(href="/register") Register now

    This is a simple view that will prompt a new visitor to log in, or greet a registered user if they have

    already logged in.

    With that weve got something we can look at!

    Run the server Its Aliiiive!I kid you not: your application is ready to be used. Just run this command to start the server:

    $ node app.js

    This will start your app which is now running as a web server on your computer. You can now openthis link in your browser:

    http://localhost:3000 (http://localhost:3000)

    http://localhost:3000/
  • 7/23/2019 A Simple Web App With Node

    6/25

    You should see your home page now:

    Go ahead, try it out! Create an account, you will be redirected back to the home page and shown

    your name. Then logout and login again, same thing! Pretty amazing, right??

    Pro tip: use a file watcherAs we move forward we will be editing your server files. You will need to restart the server each time.

    You can kill the server by typing Ctrl + C in your Terminal. But I suggest using a watcher that will

    do this for you.

    I really like the Nodemon tool. You can install it globally (it will always be ready for you!) with thiscommand:

    $ npm install g nodemon

    After installation, you can then run this command:

    $ nodemon app.js

    This will start your server and watch for any file changes. Nodemon will automatically restart your

    server if you change any files sweet!

  • 7/23/2019 A Simple Web App With Node

    7/25

    Create the profile pageA common feature of most sites is a Dashboard or profile page a place where your visitor

    provide some essential information.

    For example purposes, were going to build a profile page that allows you to collect a shipping

    address from your visitors. We will leverage Custom Data, one of the most powerful features of

    stormpathTo begin, lets create a new view for this dashboard:

    $ touch views/profile.jade

    And a JavaScript file where the route handler will live:

    $ touch profile.js

    Now weve got some copy-and-paste work to do. These two files are pretty big, so well explain them

    after the paste.

    Paste this into profile.js:

  • 7/23/2019 A Simple Web App With Node

    8/25

    var express = require('express');

    var forms = require('forms');

    var csurf = require('csurf');

    var collectFormErrors = require('expressstormpath/lib/helpers').collectFormErrors;

    var stormpath = require('expressstormpath');

    var extend = require('xtend');

    // Declare the schema of our form:

    var profileForm = forms.create({

    givenName: forms.fields.string({

    required: true

    }),

    surname: forms.fields.string({ required: true }),

    streetAddress: forms.fields.string(),

    city: forms.fields.string(),

    state: forms.fields.string(),

    zip: forms.fields.string()});

    // A render function that will render our form and

    // provide the values of the fields, as well

    // as any situationspecific locals

    function renderForm(req,res,locals){

    res.render('profile', extend({

    title: 'My Profile',

    csrfToken: req.csrfToken(),

    givenName: req.user.givenName,

    surname: req.user.surname,

    streetAddress: req.user.customData.streetAddress,

    city: req.user.customData.city,

    state: req.user.customData.state,

    zip: req.user.customData.zip

    },locals||{}));

    }

    // Export a function which will create the

    // router and return it

    module.exports = function profile(){

    var router = express.Router();

    router.use(csurf({ sessionKey: 'stormpathSession' }));

    // Capture all requests, the form library will negotiate

    // between GET and POST requests

    router.all('/', function(req, res) {

    profileForm.handle(req,{

    success: function(form){

    // The form library calls this success method if the

  • 7/23/2019 A Simple Web App With Node

    9/25

    // form is being POSTED and does not have errors

    // The expressstormpath library will populate req.user,

    // all we have to do is set the properties that we care

    // about and then cal save() on the user object:

    req.user.givenName = form.data.givenName;

    req.user.surname = form.data.surname;

    req.user.customData.streetAddress = form.data.streetAddress;

    req.user.customData.city = form.data.city; req.user.customData.state = form.data.state;

    req.user.customData.zip = form.data.zip;

    req.user.customData.save();

    req.user.save(function(err){

    if(err){

    if(err.developerMessage){

    console.error(err);

    }

    renderForm(req,res,{

    errors: [{ error: err.userMessage ||

    err.message || String(err)

    }]

    });

    }else{

    renderForm(req,res,{

    saved:true

    });

    }

    });

    },

    error: function(form){

    // The form library calls this method if the form

    // has validation errors. We will collect the errors

    // and render the form again, showing the errors

    // to the user

    renderForm(req,res,{

    errors: collectFormErrors(form)

    });

    },

    empty: function(){

    // The form library calls this method if the

    // method is GET thus we just need to render

    // the form

    renderForm(req,res);

    }

    });

    });

    // This is an error handler for this router

    router.use(function (err, req, res, next) {

    // This handler catches errors for this router

    if (err.code === 'EBADCSRFTOKEN'){

    // The csurf library is telling us that it can't

  • 7/23/2019 A Simple Web App With Node

    10/25

    // find a valid token on the form

    if(req.user){

    // session token is invalid or expired.

    // render the form anyways, but tell them what happened

    renderForm(req,res,{

    errors:[{error:'Your form has expired. Please try again.'}]

    });

    }else{

    // the user's cookies have been deleted, we dont know

    // their intention is send them back to the home page

    res.redirect('/');

    }

    }else{

    // Let the parent app handle the error

    return next(err);

    }

    });

    return router;};

    Paste this into profile.jade:

  • 7/23/2019 A Simple Web App With Node

    11/25

    html

    head

    title=title

    link(

    href='//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css',

    rel='stylesheet'

    )

    body div.container

    div.pageheader

    h1 My Profile

    if errors

    each error in errors

    div.alert.alertdanger

    span #{error.error}

    if saved div.alert.alertsuccess

    span Your profile has been saved

    form.loginform.formhorizontal(method='post', role='form')

    input(name='_csrf', type='hidden', value=csrfToken)

    div.formgroup

    label.colsm4 First Name

    div.colsm8

    input.formcontrol(

    placeholder='Your first name',

    required=true,

    name='givenName',

    type='text',

    value=givenName)

    div.formgroup

    label.colsm4 Last Name

    div.colsm8

    input.formcontrol(placeholder='Your last name',

    required=true,

    name='surname',

    type='text', value=surname)

    div.formgroup

    label.colsm4 Street address

    div.colsm8

    input.formcontrol(placeholder='e.g. 123 Sunny Ave',

    required=true,

    name='streetAddress',

    type='text',

    value=streetAddress)

    div.formgroup label.colsm4 City

    div.colsm8

    input.formcontrol(placeholder='e.g. City',

    required=true,

  • 7/23/2019 A Simple Web App With Node

    12/25

    name='city',

    type='text',

    value=city)

    div.formgroup

    label.colsm4 State

    div.colsm8

    input.formcontrol(placeholder='e.g. CA',

    required=true,

    name='state', type='text',

    value=state)

    div.formgroup

    label.colsm4 ZIP

    div.colsm8

    input.formcontrol(placeholder='e.g. 94116',

    required=true,

    name='zip',

    type='text',

    value=zip) div.formgroup

    div.colsmoffset4.colsm8

    button.login.btn.btnprimary(type='submit') Save

    div.pullright

    a(href="/") Return to home page

    Breaking it downYouve just created an Express Router. Saywha? I really like how the Express maintainers havedescribed this:

    A router is an isolated instance of middleware and routes.

    Routers can be thought of as "mini" applications, capable only

    of performing middleware and routing functions. Every express

    application has a builtin app router.

    saywha?

    In my words: Express 4.0 encourages you to break up your app into mini apps. This makes

    everything much easier to understand and maintain. This is what weve done with the profile.js file

    weve created a mini app which handles JUST the details associated with the profile page.

    Dont believe me? Read on.

    Plug in your profile pageBecause we followed the Router pattern, its now this simple to add the profile page to your existing

    app.js file (put it right above the call to app.listen):

    app.use('/profile',stormpath.loginRequired,require('./profile')());

  • 7/23/2019 A Simple Web App With Node

    13/25

    Omg. Yes. YES. Youve just decoupled the implentation of a route from its addressing. Holy grail?

    Almost. Awesome? Most Def. (By the way, youve also forced authentication on this route, using

    Stormpath, nice!)

    Restart your sever and visit /profile , you should see the form now:

    Breaking it down for real

    Okay, theres a LOT more to talk about here. So let me cover the important points:

    The profile.js file is a builder or constructor, so to speak. You have to invoke it as a method

    in order to get the router out of it. Thats why we have that empty () after the

    require('./profile') statement. Why bother? Because with this pattern you can pass in any

    options that may be required for this router. At the moment we dont have any, but who knows

    what the future holds? Doing this give you room to use this router in multiple web apps and

    factor out any app-specific config.

    We are using the forms library to create a schema for the profile form. This is a good practice

    because it separates the way in which we validate from the form from the way in which the form

    is displayed.

  • 7/23/2019 A Simple Web App With Node

    14/25

    We have a renderForm function which is responsible for creating the view modelof the form

    this model is passed down to the Jade layer, so that profile.jade has all the properties it

    needs for rendering the form. This render function ensures that our template layer doesnt blow

    up with missing values

    We are using the Csurf library to add CSRF tokens to the form as a security measure. This is

    done automaticaly for the default forms (login, registration, password reset), but because this is

    a new, custom router, we have to setup those details manually

    We reach into the Express-Stormpath library to grab our collectFormErrors function, a handy

    utility for pulling validation errors out of the response we get from the forms library. Note to self:

    PR that in to forms library!

    We make use of the loginRequired middleware to ensure that users are logged in before they

    can use this profile page

    Wrapping it upAlas, weve reached the end of this tutorial. You now have a web app that can reigster new users and

    allow them to provide you with a shipping address, pretty sweet right?

    Following the profile example you now have everything you need to start building other pages in your

    application. As you build those pages, Im sure youll want to take advantage of some other great

    features, such as:

    Enable Google Login (http://docs.stormpath.com/nodejs/express/product.html#use-google-

    login)

    Enable Facebook Login (http://docs.stormpath.com/nodejs/express/product.html#use-

    facebook-login)Customize the Password Reset Experience

    (http://docs.stormpath.com/nodejs/express/product.html#use-password-reset)

    API Key Authentication (http://docs.stormpath.com/nodejs/express/product.html#api-

    authentication)

    Those are just a few of my favorites, but there is so much more!

    Please read the Express-Stormpath Product Guide

    (http://docs.stormpath.com/nodejs/express/product.html) for details on how to implement all these

    amazing features and dont hesitate to reach out to us!

    WE LOVE WEB APPS and we want your user management experience to be 10x better than you ever

    imagined.

    -robert out

    Like what you see? Follow @goStormpath to keep up with the latest releases.

    Get Started with Stormpath

    User Management API for Developers

    https://twitter.com/intent/follow?original_referer=https%3A%2F%2Fstormpath.com%2Fblog%2Fbuild-nodejs-express-stormpath-app%2F&ref_src=twsrc%5Etfw&region=follow_link&screen_name=goStormpath&tw_p=followbuttonhttp://docs.stormpath.com/nodejs/express/product.htmlhttp://docs.stormpath.com/nodejs/express/product.html#api-authenticationhttp://docs.stormpath.com/nodejs/express/product.html#use-password-resethttp://docs.stormpath.com/nodejs/express/product.html#use-facebook-loginhttp://docs.stormpath.com/nodejs/express/product.html#use-google-login
  • 7/23/2019 A Simple Web App With Node

    15/25

    63 Comments 1

    qix

    Hi, itdoesn't look like the stormpath-express npm doesn't explicitly expose the client,

    which I'd like touse to make node.js api calls as well. Is it best practice to just

    require('stormpath') in whichever module I need it, and initialize a new client each time?

    Randall Degges Mod

    Heyo -- it does expose the client via: `req.app.get('stormpathClient')`, you can also

    access it outside of a route using `app.get('stormpathClient')`.

    qix

    Gotcha, saw thatinthe codebut wasn't sure if that was the "approved"

    means. :) Thanks!

    Luis J

    beautiful tutorial continue to share

    richie

    Hi!How would youdo this with HTML and not Jade?

    Robert

    You can use EJS (which is HTML), our guide has a section on this. Go to this link

    and scroll down to "Using EJS"

    Lily THERESA

    Cannot access the link. Could you spell it out?

    Randall Degges Mod

    https://docs.stormpath.com/nod...

    Try It For Free (https://api.stormpath.com/register)

    https://disqus.com/by/disqus_tc1xoybU44/https://disqus.com/by/disqus_tc1xoybU44/https://disqus.com/by/disqus_BarHAvCkJI/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2162025929https://disqus.com/by/qixx/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2100447999https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2100560466https://disqus.com/by/rdegges/https://disqus.com/by/rdegges/https://disqus.com/by/rdegges/https://disqus.com/by/qixx/https://disqus.com/by/qixx/https://disqus.com/by/qixx/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2100249263https://disqus.com/home/forums/stormpath/https://disqus.com/home/forums/stormpath/https://api.stormpath.com/registerhttps://api.stormpath.com/registerhttps://api.stormpath.com/registerhttps://api.stormpath.com/registerhttps://api.stormpath.com/registerhttps://api.stormpath.com/registerhttps://disqus.com/by/rdegges/https://disqus.com/by/newsyhoundsy/https://disqus.com/by/disqus_tc1xoybU44/https://disqus.com/by/disqus_BarHAvCkJI/https://disqus.com/by/qixx/https://disqus.com/by/rdegges/https://disqus.com/by/qixx/https://docs.stormpath.com/nodejs/express/product.html#using-ejshttps://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2099211163https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2099231435https://disqus.com/by/rdegges/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2061970015https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2099211163https://disqus.com/by/newsyhoundsy/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2061068567https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2061970015https://disqus.com/by/disqus_tc1xoybU44/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2061068567https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2162025929https://disqus.com/by/disqus_BarHAvCkJI/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2100447999https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2100560466https://disqus.com/by/qixx/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2100249263https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2100447999https://disqus.com/by/rdegges/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2100249263https://disqus.com/by/qixx/https://disqus.com/home/inbox/https://disqus.com/home/forums/stormpath/
  • 7/23/2019 A Simple Web App With Node

    16/25

    Felipe

    I guess you need to use some template engine anyway

    akhilesh gupta

    Hi,

    How can I modify 'register' and 'login' views?

    There are no jade files

    Robert

    If you'd like to modify (or completely replace) our default views, please see this

    section of our documentation: https://docs.stormpath.com/nod...

    Hope this helps!

    Vandes

    Hi,

    I noticed that when I modify the user data in the Profile page they appear to be saved, but

    if I refresh or return to the home page they will revert to the previous values until I restart

    the server.

    Is there a way to retrieve updated user.customData without having to restart?

    Sorry for my noobness, and thanks for the great tutorial!

    Randall Degges Mod

    This should be working (just tested it locally). Is there a chance that you didn't

    include the `.save()` method call after the profile information gets updated in

    custom data? The `.save()` method must be called in order to 'persist' all data

    changes to Stormpath.

    Vandes

    Hi Randall, just to be sure I copy-pasted the whole code, so I don't think I'm

    missing something. Additionally, if I check into my Stormpath account I can

    see the users of my application and they're updated in real time. It's just my

    local installation that needs a server reboot to display a newly saved name

    or address or whatever.

    On a side note, how shoud I proceed if I want each user to have a public

    profile page that displays the kind of static data (name, address and

    whatnot) reachable under a unique url? Robert mentioned in another

    comment that something like this could be done without an external

    database, and it would be great to have a little input on that.

    https://disqus.com/by/rdegges/https://disqus.com/by/disqus_tc1xoybU44/https://disqus.com/by/disqus_QnvnyX3TAm/https://disqus.com/by/disqus_cxydYl8bLZ/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1985313071https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1985336433https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1984959600https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1985313071https://disqus.com/by/rdegges/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1984959600https://docs.stormpath.com/nodejs/express/product.html#custom-views-routeshttps://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2013588743https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2014127870https://disqus.com/by/disqus_tc1xoybU44/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2013588743https://disqus.com/by/disqus_QnvnyX3TAm/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2061068567https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-2061665404https://disqus.com/by/disqus_cxydYl8bLZ/
  • 7/23/2019 A Simple Web App With Node

    17/25

    Thanks!

    Randall Degges Mod

    Hmm, you might want to try running the example code in an

    incognito tab (maybe there's weird browser caching stuff going on)?

    I'm just curious as I'm testing it locally and it works fine -- weird.

    The way you'd handle public stuff is essentially the same -- you

    don't even really need another database.

    What you'd do is essentially do something like:

    - Create a dynamic route in express app.get('/users/:email').

    - Lookup the Stormpath user account dynamically, given the user-

    supplied email.

    - Render whatever page template you want by manually passing

    the user object you lookup into the template, eg: res.render('profle-

    page', user=account)

    Just treat it like you would any other public site =)

    Vandes

    About the public profiles... I'm kinda stuck.

    I can't understand how to look up all the users' accounts to create

    the dynamic route. Should I use application.getAccounts() ?

    Whatever I do, I can only seem to access the current user's data,

    running in "undefined" errors if not logged in.

    Randall Degges Mod

    If you want to create a public profile page for a user, you can do it

    using something like this: http://pastie.org/10122343

    Vandes

    The thing I'm not getting is: how do I define username to make the

    route valid for every user? The code as-is gives me "username is

    not defined", but if I define it manually the whole process is useless

    because it's restricted to the user or collection I defined.

    Randall Degges Mod

    I'm not sure what you mean, exactly? In express you can create

    'dynamic routes' that allow you to accept ANY input.

    https://disqus.com/by/rdegges/https://disqus.com/by/rdegges/https://disqus.com/by/rdegges/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1996361309https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1996503121https://disqus.com/by/rdegges/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1996138264https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1996361309http://pastie.org/10122343https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1996105257https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1996138264https://disqus.com/by/rdegges/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1985348335https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1996105257https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1985336433https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1985348335https://disqus.com/by/rdegges/
  • 7/23/2019 A Simple Web App With Node

    18/25

    That's what the app.get('/users/:username') stuff does.

    Here's a full example: http://pastie.org/10122647

    It means that if a user visits the user /user/rdegges, then in your

    route code you'd have a variable called username that has that

    parameter available =)

    You can read more about this in the routing guide:

    http://webapplog.com/url-param...

    Vandes

    That's what I was missing, and I couldn't find a clear explanation.

    Thanks! Now it (kinda) works and most importantly I understood the

    logic.

    It still gives me the error in the console "cannot read property

    'fullName' of undefined" if I call #{account.fullName} in the template,

    but despite the error the template renders fine and the full name is

    displayed. Any account.customData I try to call, though, is NOT

    displayed.

    The code I'm doing these tests on is here, if you have time to take a

    look.

    https://bitbucket.org/hintclub...

    I already bothered you a lot, sorry =(

    Vandes

    Ok, solved this one on my own.

    For some reason it was rendering the template two times, first with

    the correct username variable taken from the url, and then without

    defining username, therefore the error.

    By using the getCustomData method prior to the render I solved thedouble-rendering issue and also the display of customData on the

    profile page. I'll paste the final code in case anyone else has the

    same problem.

    http://pastie.org/10125371

    Vandes

    No luck in incognito either. Just tried this: Edit my profile -->changed the Street value --> Save --> Return to home --> Edit my

    profile. The Street value is always the one that was there when the

    server was started. If I restart the server, I will find my most recent

    edit. That's ver stran e, I did the whole rocess on a different linux

    https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1985348335https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1985540575http://pastie.org/10125371https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1996746453https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1999613772https://bitbucket.org/hintclub/expressjs-stormpath-testhttps://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1996503121https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1996746453http://webapplog.com/url-parameters-and-routing-in-express-js/http://pastie.org/10122647
  • 7/23/2019 A Simple Web App With Node

    19/25

    install and the result is the same... what am I doing wrong? :)

    Hey, thanks a lot for the suggestions!

    Randall Degges Mod

    Hmm, not sure what to suggest to be honest.

    You're welcome to open a ticket with support:

    [email protected] -- we can try to do a screenshare session

    with ya. That's about all I can think of!

    Gary Hortenstine

    I'm seeing the same exact behavior that Vandes described. I'm

    wondering if there might be an update to one of the other modules

    that is causing this to be an issue recently. Here is my

    package.json.

    "dependencies": {

    "body-parser": "^1.12.0",

    "csurf": "^1.8.0",

    "express": "^4.11.2",

    "express-stormpath": "^1.0.4",

    "forms": "^1.1.1",

    "jade": "^1.9.2","xtend": "^4.0.0"

    }

    Gary Hortenstine

    In addition, I am also able to navigate to the profile page after I have

    clicked "Logout". So I'm sitting on the welcome page, supposedly

    not logged in, but when I go to the URL address bar and append

    "/profile" to the end, it takes me without complaint.

    Robert

    Hi Gary,

    We figured out the issue here! Our example was missing a line of

    code. You want to put this line in your app, right above where we

    call req.user.save in profile.js:

    req.user.customData.save()

    This makes the call to save the user's custom data. While the

    req.user.save() will do the same thing, it does't invalidate the cache

    https://disqus.com/by/disqus_tc1xoybU44/https://disqus.com/by/garyhortenstine/https://disqus.com/by/garyhortenstine/https://disqus.com/by/rdegges/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1998480817https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1998488592https://disqus.com/by/disqus_tc1xoybU44/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1998423395https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1998480817https://disqus.com/by/garyhortenstine/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1985740952https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1998423395https://disqus.com/by/garyhortenstine/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1985540575https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1985740952https://disqus.com/by/rdegges/
  • 7/23/2019 A Simple Web App With Node

    20/25

    of the custom data object.

    Hope this helps!

    -Robert

    Vandes Thanks Robert, now it works great! =)

    Gary Hortenstine

    Sweet! That got it.

    Thanks!!

    Gary Hortenstine

    Oh double sweet!! That also took care of the issue about navigating

    to the profile page after logging out!

    This is cool stuff when it's set up right!!!

    Gary Hortenstine

    Just adding that by closing the browser and re-opening, I was thenNOT able to manually navigate. It would seem to me that the Logout

    actions should be enough to prevent this, but that's not happening

    from where I'm sitting.

    Arjun Gangisetty

    Hi,

    I used the following snippet for implementing FB login in my app.js file. I'm getting thefollowing error when trying to run the application. Can someone, please guide me.

    C:\Users\ArjunKumar\my-webapp\node_modules\express stormpath\lib\helpers.js:576

    throw new Error('ERROR: No Stormpath credentials specified.')^Error: ERROR: No

    Stormpath credentials specified. at C:\Users\ArjunKumar\my-

    webapp\node_modules\express-stormpath\lib\helpers.

    s:576:13

    Here is the github link for my code: https://github.com/gangisettia...

    Thank You

    Arjun Gangisetty

    https://disqus.com/by/arjungangisetty/https://disqus.com/by/garyhortenstine/https://disqus.com/by/garyhortenstine/https://disqus.com/by/garyhortenstine/https://github.com/gangisettiarjun/NodeWebApphttps://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1978479457https://disqus.com/by/arjungangisetty/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1998480817https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1998487702https://disqus.com/by/garyhortenstine/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1998508899https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1998513201https://disqus.com/by/garyhortenstine/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1998488592https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1998508899https://disqus.com/by/garyhortenstine/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1998488592https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1999078623
  • 7/23/2019 A Simple Web App With Node

    21/25

    Arjun Gangisetty

    Hi,

    Im getting the below error when trying to access the profile route. I have checked the

    dependencies and profile method invocation in app.js. Also, I followed the thread

    concerning the same error and couldn't figure out problem with my code. I'm unsure of

    what's causing the error. Here is the link of my source code. Please, help me out.

    https://github.com/gangisettia...

    Error: misconfigured csrf

    at getsecret (C:\Users\ArjunKumar\my-webapp\node_modules\csurf\index.js:194:

    11) at csrf (C:\Users\ArjunKumar\my-webapp\node_modules\csurf\index.js:59:18)

    at Layer.handle [as handle_request] (C:\Users\ArjunKumar\my-

    webapp\node_modules\express\lib\router\layer.js:82:5)

    at trim_prefix (C:\Users\ArjunKumar\my-

    webapp\node_modules\express\lib\router\index.js:302:13)at C:\Users\ArjunKumar\my-webapp\node_modules\express\lib\router\index.js:27

    0:7at Function.proto.process_params

    (C:\Users\ArjunKumar\mywebapp\node_modules\express\lib\router\index.js:321:12) at

    next (C:\Users\ArjunKumar\my-webapp\node_modules\express\lib\router\index.js:261:10)

    at Function.proto.handle

    (C:\Users\ArjunKumar\mywebapp\node_modules\express\lib\router\index.js:166:3)

    Thank You

    Arjun Gangisetty

    Robert

    Hi Arjun!

    I figured out the problem, this blog post needs an update. In the meantime, heres

    what you need to do:

    1) The registration of the profile route should look like this:

    app.use('/profile',stormpath.loginRequired,require('./profile')())

    2) In profile.js, modify the csurf() setup to look like this:

    router.use(csurf({ sessionKey: 'stormpathSession' }))

    3) Also in profile.js, remove login required (we moved it in step 1), so

    this line should look like this now in profile.js:

    router.all('/', function(req, res) {

    Hope this helps! Feel free to reach us on support if you have any more questions!

    https://disqus.com/by/disqus_tc1xoybU44/https://disqus.com/by/arjungangisetty/https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1975234768https://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1978189693https://disqus.com/by/disqus_tc1xoybU44/https://github.com/gangisettiarjun/NodeWebApphttps://stormpath.com/blog/build-nodejs-express-stormpath-app/#comment-1975234768https://disqus.com/by/arjungangisetty/
  • 7/23/2019 A Simple Web App With Node

    22/25

    Arjun Gangisetty

    Hi Robert,

    I have made the changes you told. Actually, the session libraries were

    missing in my project setup and your support team fixed that problem.

    Now, I'm able to run the application smoothly.

    Thanks very much for the help.

    Regards

    Arjun Gangisetty

    Ninz

    Hi,

    First of all thank you for sharing this tutorial.

    I followed it until the last part in profile.js, however I have encountered an issue same with

    Charles Oppenheimer below, and I followed the fixes from github. But I'm still getting the

    same misconfigured csrf.

    Ninz

    Ops, my bad! I forgot to npm install. >.