You are on page 1of 25

ASimpleWebAppWithNode.

js,
Express,Bootstrap&Stormpathin15
Minutes
byRobertDamphousseonOctober272014

HereatStormpathwe <heart> Node.jsitssomuchfuntobuildwith!Wevebuiltseverallibrariesto


helpnodedevelopersachieveusermanagementnirvanainyourapplications.
Ifyouvebuiltawebappbefore,youknowthatalltheuserstuffisaroyalpain.Stormpathgives
developersallthatuserstuffoutofthebox(https://docs.stormpath.com/nodejs/express/)soyou
cangetonwithwhatyoureallycareaboutyourapp!Bythetimeyouredonewiththistutorial(<15
minutes,Ipromise),youllhaveafullyworkingExpressapp.
WewillfocusonourExpressStormpathlibrary(https://github.com/stormpath/stormpathexpress)to
rolloutasimpleExpress.jswebapplication,withacompleteuserregistrationandloginsystem,with
thesefeatures:
LoginandRegistrationpages
Passwordresetworkflows
Aprofilepageforyourloggedinusers
Acustomizablehomepage
TheabilitytoaddotherStormpathfeaturesinourExpressStormpathlibrary(API
authentication,SSO,sociallogin,andmore)
InthisdemowewillbeusingExpress4.0,welldiscusssomeofthegreatfeaturesofExpress4.0as
wegoalong.IwillbeusingmyMac,theTerminalapp,andSublimeTextforatexteditor.

WhatisStormpath?
StormpathisanAPIservicethatallowsdeveloperstocreate,edit,andsecurelystoreuseraccounts
anduseraccountdata,andconnectthemwithoneormultipleapplications.OurAPIenablesyouto:
Authenticateandauthorizeyourusers
Storedataaboutyourusers
Performpasswordandsocialbasedlogin
Sendpasswordresetmessages
IssueAPIkeysforAPIbasedwebapps
Andmuchmore!CheckoutourProductDocumentation(https://docs.stormpath.com/home/)
Inshort:wemakeuseraccountmanagementaloteasier,moresecure,andmorescalablethanwhat
youreprobablyusedto.
Readytogetstarted?Registerforafreedeveloperaccountathttps://api.stormpath.com/register
(https://api.stormpath.com/register)

Startyourproject
GotyourStormpathdeveloperaccount?Great!Letsgetstarted..vroomvroom
IfyoudontalreadyhaveNode.jsonyoursystemyoushouldheadovertohttps://nodejs.org
(https://nodejs.org)andinstallitonyourcomputer.InourexampleswewillbeusingaMac,all
commandsyouseeshouldbeenteredinyourTerminal(withoutthe$infrontthatsasymboltolet
youknowthattheseareterminalcommands)
Steponeistocreateafolderforthisprojectandchangeintothatdirectory:
$mkdirmywebapp
$cdmywebapp

Nowthatweareinthefolderwewillwanttocreateapackage.jsonfileforthisproject.Thisfileisused
byNode.jstokeeptrackofwhatlibraries(akamodules)yourprojectdependson.Tocreatethefile:
$npminit

Youwillbeaskedaseriesofquestions,formostofthemyoucanjustpressentertoallowthedefault
valuetobeused.HereiswhatIchose,Idecidedtocallmymainfile app.js ,Isetmyown
descriptionandsetthelicensetoMITeverythingelseIjustpressedenteron:
Press^Catanytimetoquit.
name:(mywebapp)
version:(0.0.0)
description:Websiteformynewapp
entrypoint:(index.js)app.js
testcommand:
gitrepository:
keywords:
author:
license:(ISC)MIT
Abouttowriteto/private/tmp/mywebapp/package.json:
{
"name":"mywebapp",
"version":"0.0.0",
"description":"Websiteformynewapp",
"main":"app.js",
"scripts":{
"test":"echo\"Error:notestspecified\"&&exit1"
},
"author":"",
"license":"MIT"
}

Isthisok?(yes)yes

WiththatIwillnowhaveapackage.jsonfileinmyfolder.Icantakealookatwhatsinit:
$catpackage.json
{
"name":"mywebapp",
"version":"0.0.0",
"description":"Websiteformynewapp",
"main":"app.js",
"scripts":{
"test":"echo\"Error:notestspecified\"&&exit1"
},
"author":"",
"license":"MIT"
}

Looksgood!Nowletsinstallthelibrarieswewanttouse.Youcaninstallthemallwiththiscommand:
$npmisaveexpressexpressstormpathjadeformscsurfxtend

Thesaveoptionwilladdthismoduletoyourdependenciesinpackage.json.Hereiswhateach
moduledoes:
Express.js(http://expressjs.com/)isthewebframeworkthateverythingelseisbuilton
Expressstormpath(https://github.com/stormpath/stormpathexpress)providesconvenience
featuresthatcanbetiedintotheExpressapp,makingitveryeasytouseStormpathsfeatures
inExpress
Jade(http://jadelang.com/)isatemplatingengineforwritingHTMLpages
Forms(https://github.com/caolan/forms)isamodulethatwilltakethepainoutofvalidating
HTMLforms
Csurf(https://github.com/expressjs/csurf)addsCSRFprotection
(http://en.wikipedia.org/wiki/Crosssite_request_forgery)toourforms
XtendisautilitylibrarythatmakesiteasytocopypropertiesfromoneJavaScriptobjectto
another.

GatheryourAPICredentialsandApplication
Href
TheconnectionbetweenyourappandStormpathissecuredwithAPIKeyPair.Youwillprovide
thesekeystoyourwebappanditwillusethemwhenitcommunicateswithStormpath.Youcan
downloadyourAPIkeypairinourAdminConsole(https://api.stormpath.com).Afteryouloginyoucan
downloadyourAPIkeypairfromthehomepage,itwilldownloadthe apiKey.properties filewewill
usethisinamoment.
WhileyouareintheAdminConsoleyouwanttogetthehrefforyourdefaultStormpathApplication.In
Stormpath,anApplicationobjectisusedtolinkyourwebapptoyouruserstoresinsideStormpath.All
newdeveloperaccountshaveanappcalledMyApplication.ClickonApplicationsintheAdmin
Console,thenclickonMyApplication.OnthatpageyouwillseetheHreffortheApplication.Copy
thiswewillneeditshortly.

Writingtheapplicationentry(app.js)
Itstimetocreateapp.js,thiswillbetheentrypointforyourserverapplication.Youcandothatfrom
SublimeTextoryoucandothisintheterminal:
$touchapp.js

NowopenthatfileinSublimeTextandputthefollowingblockofcodeinit:
varexpress=require('express');
varstormpath=require('expressstormpath');
varapp=express();
app.set('views','./views');
app.set('viewengine','jade');
varstormpathMiddleware=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);

YoullneedtosetthelocationofapiKeyFiletobethelocationonyourcomputerwhereyousavedthe
file.Youalsoneedtosettheapplicationhreftobetheonethatyoulookedupearlier.
The secretKey valueshouldbechangedaswell,thiswillbeusedasakeyforencryptingany
cookiesthataresetbythiswebapp.Isuggestusingalong,randomstringofanytypeofcharacter.
Inthisexampleweveenabledsomestormpathspecificoptions,theyare:
Thepasswordresetflowvia enableForgotPassword thiswillenableapasswordresetpageat
/forgot

Autoexpansionofcustomdatathiswillcomeinhandylaterwhenwebuildtheprofilepage
Therearemanymoreoptionsthatcanbepassed,andwewontcoveralloftheminthisdemo.
PleaseseeetheExpressStormpathDocumentation
(http://docs.stormpath.com/nodejs/express/index.html)forafulllist

Createyourhomepage
Letsgettheeasystuffoutoftheway:yourhomepage.Createa views directoryandthencreatea
Jadefileforthehomepage:
$mkdirviews
$touchviews/home.jade

NowopenthatfileinSublimeTextandputthefollowinginit:
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
h1Hello!
ifuser
pWelcome,#{user.fullName}
p
a.small(href="profile")Editmyprofile
a.btn.btnprimary(href="/logout")Logout
else
pWelcometomyapp,readytogetstarted?
p
a.btn.btnprimary(href="/login")Loginnow
p
span.smallDon'thaveanaccount?
span&nbsp;
a.small(href="/register")Registernow

Thisisasimpleviewthatwillpromptanewvisitortologin,orgreetaregistereduseriftheyhave
alreadyloggedin.
Withthatwevegotsomethingwecanlookat!

RuntheserverItsAliiiive!
Ikidyounot:yourapplicationisreadytobeused.Justrunthiscommandtostarttheserver:
$nodeapp.js

Thiswillstartyourappwhichisnowrunningasawebserveronyourcomputer.Youcannowopen
thislinkinyourbrowser:
http://localhost:3000(http://localhost:3000)

Youshouldseeyourhomepagenow:

Goahead,tryitout!Createanaccount,youwillberedirectedbacktothehomepageandshown
yourname.Thenlogoutandloginagain,samething!Prettyamazing,right??

Protip:useafilewatcher
Aswemoveforwardwewillbeeditingyourserverfiles.Youwillneedtorestarttheservereachtime.
Youcankilltheserverbytyping Ctrl+C inyourTerminal.ButIsuggestusingawatcherthatwill
dothisforyou.
IreallyliketheNodemontool.Youcaninstallitglobally(itwillalwaysbereadyforyou!)withthis
command:
$npminstallgnodemon

Afterinstallation,youcanthenrunthiscommand:
$nodemonapp.js

Thiswillstartyourserverandwatchforanyfilechanges.Nodemonwillautomaticallyrestartyour
serverifyouchangeanyfilessweet!

Createtheprofilepage
AcommonfeatureofmostsitesisaDashboardorprofilepageaplacewhereyourvisitor
providesomeessentialinformation.
Forexamplepurposes,weregoingtobuildaprofilepagethatallowsyoutocollectashipping
addressfromyourvisitors.WewillleverageCustomData,oneofthemostpowerfulfeaturesof
stormpath
Tobegin,letscreateanewviewforthisdashboard:
$touchviews/profile.jade

AndaJavaScriptfilewheretheroutehandlerwilllive:
$touchprofile.js

Nowwevegotsomecopyandpasteworktodo.Thesetwofilesareprettybig,sowellexplainthem
afterthepaste.
Pastethisinto profile.js :

varexpress=require('express');
varforms=require('forms');
varcsurf=require('csurf');
varcollectFormErrors=require('expressstormpath/lib/helpers').collectFormErrors;
varstormpath=require('expressstormpath');
varextend=require('xtend');
//Declaretheschemaofourform:
varprofileForm=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()
});
//Arenderfunctionthatwillrenderourformand
//providethevaluesofthefields,aswell
//asanysituationspecificlocals
functionrenderForm(req,res,locals){
res.render('profile',extend({
title:'MyProfile',
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||{}));
}
//Exportafunctionwhichwillcreatethe
//routerandreturnit
module.exports=functionprofile(){
varrouter=express.Router();
router.use(csurf({sessionKey:'stormpathSession'}));
//Captureallrequests,theformlibrarywillnegotiate
//betweenGETandPOSTrequests
router.all('/',function(req,res){
profileForm.handle(req,{
success:function(form){
//Theformlibrarycallsthissuccessmethodifthe

//formisbeingPOSTEDanddoesnothaveerrors
//Theexpressstormpathlibrarywillpopulatereq.user,
//allwehavetodoissetthepropertiesthatwecare
//aboutandthencalsave()ontheuserobject:
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){
//Theformlibrarycallsthismethodiftheform
//hasvalidationerrors.Wewillcollecttheerrors
//andrendertheformagain,showingtheerrors
//totheuser
renderForm(req,res,{
errors:collectFormErrors(form)
});
},
empty:function(){
//Theformlibrarycallsthismethodifthe
//methodisGETthuswejustneedtorender
//theform
renderForm(req,res);
}
});
});
//Thisisanerrorhandlerforthisrouter
router.use(function(err,req,res,next){
//Thishandlercatcheserrorsforthisrouter
if(err.code==='EBADCSRFTOKEN'){
//Thecsurflibraryistellingusthatitcan't

//findavalidtokenontheform
if(req.user){
//sessiontokenisinvalidorexpired.
//rendertheformanyways,buttellthemwhathappened
renderForm(req,res,{
errors:[{error:'Yourformhasexpired.Pleasetryagain.'}]
});
}else{
//theuser'scookieshavebeendeleted,wedontknow
//theirintentionissendthembacktothehomepage
res.redirect('/');
}
}else{
//Lettheparentapphandletheerror
returnnext(err);
}
});
returnrouter;
};

Pastethisinto profile.jade :

html
head
title=title
link(
href='//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css',
rel='stylesheet'
)
body
div.container
div.pageheader
h1MyProfile
iferrors
eacherrorinerrors
div.alert.alertdanger
span#{error.error}
ifsaved
div.alert.alertsuccess
spanYourprofilehasbeensaved
form.loginform.formhorizontal(method='post',role='form')
input(name='_csrf',type='hidden',value=csrfToken)
div.formgroup
label.colsm4FirstName
div.colsm8
input.formcontrol(
placeholder='Yourfirstname',
required=true,
name='givenName',
type='text',
value=givenName)
div.formgroup
label.colsm4LastName
div.colsm8
input.formcontrol(placeholder='Yourlastname',
required=true,
name='surname',
type='text',
value=surname)
div.formgroup
label.colsm4Streetaddress
div.colsm8
input.formcontrol(placeholder='e.g.123SunnyAve',
required=true,
name='streetAddress',
type='text',
value=streetAddress)
div.formgroup
label.colsm4City
div.colsm8
input.formcontrol(placeholder='e.g.City',
required=true,

name='city',
type='text',
value=city)
div.formgroup
label.colsm4State
div.colsm8
input.formcontrol(placeholder='e.g.CA',
required=true,
name='state',
type='text',
value=state)
div.formgroup
label.colsm4ZIP
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="/")Returntohomepage

Breakingitdown
YouvejustcreatedanExpressRouter.Saywha?IreallylikehowtheExpressmaintainershave
describedthis:
Arouterisanisolatedinstanceofmiddlewareandroutes.
Routerscanbethoughtofas"mini"applications,capableonly
ofperformingmiddlewareandroutingfunctions.Everyexpress
applicationhasabuiltinapprouter.

saywha?
Inmywords:Express4.0encouragesyoutobreakupyourappintominiapps.Thismakes
everythingmucheasiertounderstandandmaintain.Thisiswhatwevedonewiththe profile.js file
wevecreatedaminiappwhichhandlesJUSTthedetailsassociatedwiththeprofilepage.
Dontbelieveme?Readon.

Pluginyourprofilepage
BecausewefollowedtheRouterpattern,itsnowthissimpletoaddtheprofilepagetoyourexisting
app.jsfile(putitrightabovethecallto app.listen ):
app.use('/profile',stormpath.loginRequired,require('./profile')());

Omg.Yes.YES.Youvejustdecoupledtheimplentationofaroutefromitsaddressing.Holygrail?
Almost.Awesome?MostDef.(Bytheway,youvealsoforcedauthenticationonthisroute,using
Stormpath,nice!)
Restartyourseverandvisit /profile ,youshouldseetheformnow:

Breakingitdownforreal
Okay,theresaLOTmoretotalkabouthere.Soletmecovertheimportantpoints:
The profile.js fileisabuilderorconstructor,sotospeak.Youhavetoinvokeitasamethod
inordertogettherouteroutofit.Thatswhywehavethatempty () afterthe
require('./profile') statement.Whybother?Becausewiththispatternyoucanpassinany
optionsthatmayberequiredforthisrouter.Atthemomentwedonthaveany,butwhoknows
whatthefutureholds?Doingthisgiveyouroomtousethisrouterinmultiplewebappsand
factoroutanyappspecificconfig.
Weareusingthe forms librarytocreateaschemafortheprofileform.Thisisagoodpractice
becauseitseparatesthewayinwhichwevalidatefromtheformfromthewayinwhichtheform
isdisplayed.

Wehavea renderForm functionwhichisresponsibleforcreatingtheviewmodeloftheform


thismodelispasseddowntotheJadelayer,sothat profile.jade hasallthepropertiesit
needsforrenderingtheform.Thisrenderfunctionensuresthatourtemplatelayerdoesntblow
upwithmissingvalues
WeareusingtheCsurflibrarytoaddCSRFtokenstotheformasasecuritymeasure.Thisis
doneautomaticalyforthedefaultforms(login,registration,passwordreset),butbecausethisis
anew,customrouter,wehavetosetupthosedetailsmanually
WereachintotheExpressStormpathlibrarytograbour collectFormErrors function,ahandy
utilityforpullingvalidationerrorsoutoftheresponsewegetfromtheformslibrary.Notetoself:
PRthatintoformslibrary!
Wemakeuseofthe loginRequired middlewaretoensurethatusersareloggedinbeforethey
canusethisprofilepage

Wrappingitup
Alas,wevereachedtheendofthistutorial.Younowhaveawebappthatcanreigsternewusersand
allowthemtoprovideyouwithashippingaddress,prettysweetright?
Followingtheprofileexampleyounowhaveeverythingyouneedtostartbuildingotherpagesinyour
application.Asyoubuildthosepages,Imsureyoullwanttotakeadvantageofsomeothergreat
features,suchas:
EnableGoogleLogin(http://docs.stormpath.com/nodejs/express/product.html#usegoogle
login)
EnableFacebookLogin(http://docs.stormpath.com/nodejs/express/product.html#use
facebooklogin)
CustomizethePasswordResetExperience
(http://docs.stormpath.com/nodejs/express/product.html#usepasswordreset)
APIKeyAuthentication(http://docs.stormpath.com/nodejs/express/product.html#api
authentication)
Thosearejustafewofmyfavorites,butthereissomuchmore!
PleasereadtheExpressStormpathProductGuide
(http://docs.stormpath.com/nodejs/express/product.html)fordetailsonhowtoimplementallthese
amazingfeaturesanddonthesitatetoreachouttous!
WELOVEWEBAPPSandwewantyourusermanagementexperiencetobe10xbetterthanyouever
imagined.
robertout

Likewhatyousee?

Follow@goStormpath

tokeepupwiththelatestreleases.

GetStartedwithStormpath
UserManagementAPIforDevelopers

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

63Comments

Stormpath

Share

Recommend 5

Login

SortbyBest

Jointhediscussion
qix 2monthsago

Hi,itdoesn'tlooklikethestormpathexpressnpmdoesn'texplicitlyexposetheclient,
whichI'dliketousetomakenode.jsapicallsaswell.Isitbestpracticetojust
require('stormpath')inwhichevermoduleIneedit,andinitializeanewclienteachtime?
1

Reply Share

RandallDegges

Mod >qix

2monthsago

Heyoitdoesexposetheclientvia:`req.app.get('stormpathClient')`,youcanalso
accessitoutsideofarouteusing`app.get('stormpathClient')`.

Reply Share

qix>RandallDegges 2monthsago

Gotcha,sawthatinthecodebutwasn'tsureifthatwasthe"approved"
means.:)Thanks!

Reply Share

LuisJ amonthago

beautifultutorialcontinuetoshare

Reply Share

richie 3monthsago

Hi!HowwouldyoudothiswithHTMLandnotJade?

Reply Share

Robert>richie 3monthsago

YoucanuseEJS(whichisHTML),ourguidehasasectiononthis.Gotothislink
andscrolldownto"UsingEJS"
1

Reply Share

LilyTHERESA>Robert 2monthsago

Cannotaccessthelink.Couldyouspellitout?

Reply Share

RandallDegges

Mod >LilyTHERESA

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

2monthsago

Reply Share

Felipe>richie 3monthsago

Iguessyouneedtousesometemplateengineanyway

Reply Share

akhileshgupta 4monthsago

Hi,
HowcanImodify'register'and'login'views?
Therearenojadefiles

Reply Share

Robert>akhileshgupta 4monthsago

Ifyou'dliketomodify(orcompletelyreplace)ourdefaultviews,pleaseseethis
sectionofourdocumentation:https://docs.stormpath.com/nod...
Hopethishelps!

Reply Share

Vandes 5monthsago

Hi,
InoticedthatwhenImodifytheuserdataintheProfilepagetheyappeartobesaved,but
ifIrefreshorreturntothehomepagetheywillreverttothepreviousvaluesuntilIrestart
theserver.
Isthereawaytoretrieveupdateduser.customDatawithouthavingtorestart?
Sorryformynoobness,andthanksforthegreattutorial!

Reply Share

RandallDegges

Mod >Vandes

5monthsago

Thisshouldbeworking(justtesteditlocally).Isthereachancethatyoudidn't
includethe`.save()`methodcallaftertheprofileinformationgetsupdatedin
customdata?The`.save()`methodmustbecalledinorderto'persist'alldata
changestoStormpath.

Reply Share

Vandes>RandallDegges 5monthsago

HiRandall,justtobesureIcopypastedthewholecode,soIdon'tthinkI'm
missingsomething.Additionally,ifIcheckintomyStormpathaccountIcan
seetheusersofmyapplicationandthey'reupdatedinrealtime.It'sjustmy
localinstallationthatneedsaserverreboottodisplayanewlysavedname
oraddressorwhatever.
Onasidenote,howshoudIproceedifIwanteachusertohaveapublic
profilepagethatdisplaysthekindofstaticdata(name,addressand
whatnot)reachableunderauniqueurl?Robertmentionedinanother
commentthatsomethinglikethiscouldbedonewithoutanexternal
database,anditwouldbegreattohavealittleinputonthat.

Thanks!

Reply Share

RandallDegges

Mod >Vandes

5monthsago

Hmm,youmightwanttotryrunningtheexamplecodeinan
incognitotab(maybethere'sweirdbrowsercachingstuffgoingon)?
I'mjustcuriousasI'mtestingitlocallyanditworksfineweird.
Thewayyou'dhandlepublicstuffisessentiallythesameyou
don'tevenreallyneedanotherdatabase.
Whatyou'ddoisessentiallydosomethinglike:
Createadynamicrouteinexpressapp.get('/users/:email').
LookuptheStormpathuseraccountdynamically,giventheuser
suppliedemail.
Renderwhateverpagetemplateyouwantbymanuallypassing
theuserobjectyoulookupintothetemplate,eg:res.render('profle
page',user=account)
Justtreatitlikeyouwouldanyotherpublicsite=)

Reply Share

Vandes>RandallDegges 4monthsago

Aboutthepublicprofiles...I'mkindastuck.
Ican'tunderstandhowtolookupalltheusers'accountstocreate
thedynamicroute.ShouldIuseapplication.getAccounts()?
WhateverIdo,Icanonlyseemtoaccessthecurrentuser'sdata,
runningin"undefined"errorsifnotloggedin.

Reply Share

RandallDegges

Mod >Vandes

4monthsago

Ifyouwanttocreateapublicprofilepageforauser,youcandoit
usingsomethinglikethis:http://pastie.org/10122343

Reply Share

Vandes>RandallDegges 4monthsago

ThethingI'mnotgettingis:howdoIdefineusernametomakethe
routevalidforeveryuser?Thecodeasisgivesme"usernameis
notdefined",butifIdefineitmanuallythewholeprocessisuseless
becauseit'srestrictedtotheuserorcollectionIdefined.

Reply Share

RandallDegges

Mod >Vandes

4monthsago

I'mnotsurewhatyoumean,exactly?Inexpressyoucancreate
'dynamicroutes'thatallowyoutoacceptANYinput.
That'swhattheapp.get('/users/:username')stuffdoes.

That'swhattheapp.get('/users/:username')stuffdoes.
Here'safullexample:http://pastie.org/10122647
Itmeansthatifauservisitstheuser/user/rdegges,theninyour
routecodeyou'dhaveavariablecalledusernamethathasthat
parameteravailable=)
Youcanreadmoreaboutthisintheroutingguide:
http://webapplog.com/urlparam...

Reply Share

Vandes>RandallDegges 4monthsago

That'swhatIwasmissing,andIcouldn'tfindaclearexplanation.
Thanks!Nowit(kinda)worksandmostimportantlyIunderstoodthe
logic.
Itstillgivesmetheerrorintheconsole"cannotreadproperty
'fullName'ofundefined"ifIcall#{account.fullName}inthetemplate,
butdespitetheerrorthetemplaterendersfineandthefullnameis
displayed.Anyaccount.customDataItrytocall,though,isNOT
displayed.
ThecodeI'mdoingthesetestsonishere,ifyouhavetimetotakea
look.
https://bitbucket.org/hintclub...
Ialreadybotheredyoualot,sorry=(

Reply Share

Vandes>Vandes 4monthsago

Ok,solvedthisoneonmyown.
Forsomereasonitwasrenderingthetemplatetwotimes,firstwith
thecorrectusernamevariabletakenfromtheurl,andthenwithout
definingusername,thereforetheerror.
ByusingthegetCustomDatamethodpriortotherenderIsolvedthe
doublerenderingissueandalsothedisplayofcustomDataonthe
profilepage.I'llpastethefinalcodeincaseanyoneelsehasthe
sameproblem.
http://pastie.org/10125371

Reply Share

Vandes>RandallDegges 5monthsago

Noluckinincognitoeither.Justtriedthis:Editmyprofile>
changedtheStreetvalue>Save>Returntohome>Editmy
profile.TheStreetvalueisalwaystheonethatwastherewhenthe
serverwasstarted.IfIrestarttheserver,Iwillfindmymostrecent
edit.That'sverystrange,Ididthewholeprocessonadifferentlinux

edit.That'sverystrange,Ididthewholeprocessonadifferentlinux
installandtheresultisthesame...whatamIdoingwrong?:)
Hey,thanksalotforthesuggestions!

Reply Share

RandallDegges

Mod >Vandes

5monthsago

Hmm,notsurewhattosuggesttobehonest.
You'rewelcometoopenaticketwithsupport:
support@stormpath.comwecantrytodoascreensharesession
withya.That'saboutallIcanthinkof!

Reply Share

GaryHortenstine>RandallDegges 4monthsago

I'mseeingthesameexactbehaviorthatVandesdescribed.I'm
wonderingiftheremightbeanupdatetooneoftheothermodules
thatiscausingthistobeanissuerecently.Hereismy
package.json.
"dependencies":{
"bodyparser":"^1.12.0",
"csurf":"^1.8.0",
"express":"^4.11.2",
"expressstormpath":"^1.0.4",
"forms":"^1.1.1",
"jade":"^1.9.2",
"xtend":"^4.0.0"
}
1

Reply Share

GaryHortenstine>GaryHortenstine 4monthsago

Inaddition,IamalsoabletonavigatetotheprofilepageafterIhave
clicked"Logout".SoI'msittingonthewelcomepage,supposedly
notloggedin,butwhenIgototheURLaddressbarandappend
"/profile"totheend,ittakesmewithoutcomplaint.

Reply Share

Robert>GaryHortenstine 4monthsago

HiGary,
Wefiguredouttheissuehere!Ourexamplewasmissingalineof
code.Youwanttoputthislineinyourapp,rightabovewherewe
callreq.user.saveinprofile.js:
req.user.customData.save()
Thismakesthecalltosavetheuser'scustomdata.Whilethe
req.user.save()willdothesamething,itdoes'tinvalidatethecache

ofthecustomdataobject.
Hopethishelps!
Robert

Reply Share

Vandes>Robert 4monthsago

ThanksRobert,nowitworksgreat!=)

Reply Share

GaryHortenstine>Robert 4monthsago

Sweet!Thatgotit.
Thanks!!

Reply Share

GaryHortenstine>GaryHortenstine 4monthsago

Ohdoublesweet!!Thatalsotookcareoftheissueaboutnavigating
totheprofilepageafterloggingout!
Thisiscoolstuffwhenit'ssetupright!!!

Reply Share

GaryHortenstine>GaryHortenstine 4monthsago

Justaddingthatbyclosingthebrowserandreopening,Iwasthen
NOTabletomanuallynavigate.ItwouldseemtomethattheLogout
actionsshouldbeenoughtopreventthis,butthat'snothappening
fromwhereI'msitting.

Reply Share

ArjunGangisetty 5monthsago

Hi,
IusedthefollowingsnippetforimplementingFBlogininmyapp.jsfile.I'mgettingthe
followingerrorwhentryingtoruntheapplication.Cansomeone,pleaseguideme.
C:\Users\ArjunKumar\mywebapp\node_modules\expressstormpath\lib\helpers.js:576
thrownewError('ERROR:NoStormpathcredentialsspecified.')^Error:ERROR:No
Stormpathcredentialsspecified.atC:\Users\ArjunKumar\my
webapp\node_modules\expressstormpath\lib\helpers.
js:576:13
Hereisthegithublinkformycode:https://github.com/gangisettia...
ThankYou
ArjunGangisetty

Reply Share

ArjunGangisetty 5monthsago

Hi,
Imgettingthebelowerrorwhentryingtoaccesstheprofileroute.Ihavecheckedthe
dependenciesandprofilemethodinvocationinapp.js.Also,Ifollowedthethread
concerningthesameerrorandcouldn'tfigureoutproblemwithmycode.I'munsureof
what'scausingtheerror.Hereisthelinkofmysourcecode.Please,helpmeout.
https://github.com/gangisettia...
Error:misconfiguredcsrf
atgetsecret(C:\Users\ArjunKumar\mywebapp\node_modules\csurf\index.js:194:
11)atcsrf(C:\Users\ArjunKumar\mywebapp\node_modules\csurf\index.js:59:18)
atLayer.handle[ashandle_request](C:\Users\ArjunKumar\my
webapp\node_modules\express\lib\router\layer.js:82:5)
attrim_prefix(C:\Users\ArjunKumar\my
webapp\node_modules\express\lib\router\index.js:302:13)
atC:\Users\ArjunKumar\mywebapp\node_modules\express\lib\router\index.js:27
0:7atFunction.proto.process_params
(C:\Users\ArjunKumar\mywebapp\node_modules\express\lib\router\index.js:321:12)at
next(C:\Users\ArjunKumar\mywebapp\node_modules\express\lib\router\index.js:261:10)
atFunction.proto.handle
(C:\Users\ArjunKumar\mywebapp\node_modules\express\lib\router\index.js:166:3)
ThankYou
ArjunGangisetty

Reply Share

Robert>ArjunGangisetty 5monthsago

HiArjun!
Ifiguredouttheproblem,thisblogpostneedsanupdate.Inthemeantime,heres
whatyouneedtodo:
1)Theregistrationoftheprofilerouteshouldlooklikethis:
app.use('/profile',stormpath.loginRequired,require('./profile')())
2)Inprofile.js,modifythecsurf()setuptolooklikethis:
router.use(csurf({sessionKey:'stormpathSession'}))
3)Alsoinprofile.js,removeloginrequired(wemoveditinstep1),so
thislineshouldlooklikethisnowinprofile.js:
router.all('/',function(req,res){
Hopethishelps!Feelfreetoreachusonsupportifyouhaveanymorequestions!

Reply Share


ArjunGangisetty>Robert 5monthsago

HiRobert,
Ihavemadethechangesyoutold.Actually,thesessionlibrarieswere
missinginmyprojectsetupandyoursupportteamfixedthatproblem.
Now,I'mabletoruntheapplicationsmoothly.
Thanksverymuchforthehelp.
Regards
ArjunGangisetty

Reply Share

Ninz 5monthsago

Hi,
Firstofallthankyouforsharingthistutorial.
Ifollowedituntilthelastpartinprofile.js,howeverIhaveencounteredanissuesamewith
CharlesOppenheimerbelow,andIfollowedthefixesfromgithub.ButI'mstillgettingthe
samemisconfiguredcsrf.

Reply Share

Ninz>Ninz 5monthsago

Ops,mybad!Iforgottonpminstall.>.<

Reply Share

Robert 5monthsago

HiChandeep,
I'dverifythatyourStormpathAPIkeysandApplicationHrefarestillthecorrectones.If
yousillhaveproblems,feelfreetoreachusviasupport@stormpath.comsothatwecan
sharecodeandhelpyouout.Thanks!

Reply Share

Chandeep 5monthsago

Hi,
Istartedtheappanditworkedlikeacharmforthefirsttime,butwhenIrestartedthe
server,Igotsomeerrorsasbelow,can'tfigureoutwhy....pleasehelpme
/home/ckhamba/personal/miningglassdoor
information/src/FrontPanel/node_modules/express
stormpath/node_modules/stormpath/node_modules/request/index.js:50
opts=util._extend({},uri)
^
TypeError:Object#<object>hasnomethod'_extend'
atrequest(/home/ckhamba/personal/miningglassdoor

atrequest(/home/ckhamba/personal/miningglassdoor
information/src/FrontPanel/node_modules/express
stormpath/node_modules/stormpath/node_modules/request/index.js:50:17)
atRequestExecutor.executeRequest[asexecute](/home/ckhamba/personal/mining
glassdoorinformation/src/FrontPanel/node_modules/express
stormpath/node_modules/stormpath/lib/ds/RequestExecutor.js:88:3)
atdoRequest(/home/ckhamba/personal/miningglassdoor
information/src/FrontPanel/node_modules/express
seemore

Reply Share

nmtuan87 5monthsago

c:\Users\Tuan\Downloads\projectnodejs\mediacenterjsmaster\profile.js:48
router.use(csurf())
^
TypeError:Cannotreadproperty'use'ofundefined
atprofile(c:\Users\Tuan\Downloads\projectnodejs\mediacenterjsmaster\profile.js:48:11)
atObject.<anonymous>(c:\Users\Tuan\Downloads\projectnodejs\mediacenterjs
master\test1.js:27:40)
atModule._compile(module.js:460:26)
atObject.Module._extensions..js(module.js:478:10)
atModule.load(module.js:355:32)
atFunction.Module._load(module.js:310:12)
atFunction.Module.runMain(module.js:501:10)
atstartup(node.js:129:16)
atnode.js:814:3

Reply Share

Daniel>nmtuan87 2monthsago

Itisyouexpressversion,thisbecameimplementedfromv4

Reply Share

RandallDegges

Mod >nmtuan87

5monthsago

Itlookslikeyoudidn'tcreatethe`router`variable.

Reply Share

JooMartins 7monthsago

hi,Iamalsofacingthesameissuethenelen.WhenItrytoregisteranaccountiam
gettingthefollowingerror:"Oops!Weencounteredanunexpectederror.Pleasecontact

gettingthefollowingerror:"Oops!Weencounteredanunexpectederror.Pleasecontact
supportandexplainwhatyouweredoingatthetimethiserroroccurred."

Reply Share

RandallDegges

Mod >JooMartins

7monthsago

AfewthingsIwouldcheck:makesurethatyourStormpathAPIkeysand
StormpathApplicationhrefaresetupcorrectlyintheExpressapp,alsomakesure
thatyourStormpathApplicationismappedtoanenabledAccountStore.

Reply Share

Anil 8monthsago

Awesome!!Itworkedforme.Tryingtoworkon2ndtutorials,butfacingsomeproblems.
Whereineedtoaddthispartofcode,gettingconfused:
app.use(stormpath.init(app,{
enableFacebook:true,
social:{
facebook:{
appId:'xxx',
appSecret:'xxx',
},
},
}))
Ijusttriedbyaddingthatcodeintoapp.jsfile,gettingNostormpathcredentialsspecified

Reply Share

RandallDegges

Mod >Anil

8monthsago

Youleftoutafewsettingsfromthecodesnippet,youaremissingtheseones:
apiKeyFile:'/Users/robert/.stormpath/apiKey.properties',
application:'https://api.stormpath.com/v1/a...,
secretKey:'some_long_random_string',

Reply Share

Anil>RandallDegges 7monthsago

Thanksalotman...Itworkedforme...!!!!

Reply Share

elen 8monthsago

Hi,whenItrytoregisterIalwaysgetthefollowingmessage:
"Oops!Weencounteredanunexpectederror.Pleasecontactsupportand
explainwhatyouweredoingatthetimethiserroroccurred."
Idon'tknowwhyithappens.Ichecktheappwithmozillafirefox.HowcanIfixit?thanks

Reply Share

Robert>elen 8monthsago

Robert>elen 8monthsago

AfewthingsIwouldcheck:makesurethatyourStormpathAPIkeysand
StormpathApplicationHrefaresetupcorrectlyintheExpressapp,alsomakesure
thatyourStormpathApplicationismappedtoanenabledAccountStore

Reply Share

elen>Robert 8monthsago

howcanIcheckthese?thankyouinadvance

Reply Share

ClaireHunsaker

Mod >elen

8monthsago

(https://twitter.com/gostormpath) (https://github.com/stormpath)
(https://www.facebook.com/pages/Stormpath/259202314149649)
(https://plus.google.com/117311343501729372771)

About(/about)
Customers(/customers)
Blog(/blog)
Jobs(http://www.jobscore.com/jobs/stormpath)
Press&News(/press)
Contact(/contact)

Support(https://support.stormpath.com/home)
StatusReport(http://status.stormpath.com/)
Resources(/resources)
Compliance(/resources/compliance)
Security&Availability(/resources/securityand
availability)

Copyright2015Stormpath Allrightsreserved Privacypolicy(/privacy_policy)


Termsofservice(/terms_of_service)

You might also like