Flutter
...
Authentication
Current User
13 min
get current user on session introduction it would not be enjoyable if the user had to log in every time they open your app you can avoid this by using the cached current parseuser object whenever you use any signup or login methods, the user is cached locally you can manage this cache as a session, and automatically assume the user is logged in in this guide, you will learn how to use the flutter plugin for parse server to get current user on session using parseuser class for your flutter app goal get current user on session using parse for a flutter app prerequisites to complete this tutorial, you will need flutter version 2 2 x or later https //flutter dev/docs/get started/install android studio https //developer android com/studio or vs code installed (with plugins dart and flutter) a flutter app created and connected to back4app note follow the install parse sdk on flutter project to create an flutter project connected to back4app complete the previous guide so ou can have a better understanding of the parseuser parseuser class a device (not simulator) running android or ios understanding the get current user app to better understand the get current user on session process, we will create an app to signup, login e logout a user the application is similar to the previous guide, where we perform the signup, login, and logout as we’re going to use the same project in the following guides, you can find some not yet available functions we won’t explain the flutter application code once this guide’s primary focus is using the flutter with parse following the next steps, you will build a login e logout app at back4app database let’s get started! in the following steps, you will be able to build app a get current user 1 create the login/logout app template open your flutter project from the previous guide flutter plugin for parse server go to the main dart file, clean up all the code, and replace it with 1 import 'package\ flutter/material dart'; 2 import 'package\ parse server sdk flutter/parse server sdk dart'; 3 4 void main() async { 5 widgetsflutterbinding ensureinitialized(); 6 7 final keyapplicationid = 'your app id here'; 8 final keyclientkey = 'your client key here'; 9 final keyparseserverurl = 'https //parseapi back4app com'; 10 11 await parse() initialize(keyapplicationid, keyparseserverurl, 12 clientkey keyclientkey, 13 debug true); 14 15 runapp(myapp()); 16 } 17 18 class myapp extends statelesswidget { 19 future\<bool> hasuserlogged() async { 20 return future value(false); 21 } 22 23 @override 24 widget build(buildcontext context) { 25 return materialapp( 26 title 'flutter parse server', 27 theme themedata( 28 primaryswatch colors blue, 29 visualdensity visualdensity adaptiveplatformdensity, 30 ), 31 home futurebuilder\<bool>( 32 future hasuserlogged(), 33 builder (context, snapshot) { 34 switch (snapshot connectionstate) { 35 case connectionstate none 36 case connectionstate waiting 37 return scaffold( 38 body center( 39 child container( 40 width 100, 41 height 100, 42 child circularprogressindicator()), 43 ), 44 ); 45 default 46 if (snapshot hasdata && snapshot data!) { 47 return userpage(); 48 } else { 49 return loginpage(); 50 } 51 } 52 }), 53 ); 54 } 55 } 56 57 class loginpage extends statefulwidget { 58 @override 59 loginpagestate createstate() => loginpagestate(); 60 } 61 62 class loginpagestate extends state\<loginpage> { 63 final controllerusername = texteditingcontroller(); 64 final controllerpassword = texteditingcontroller(); 65 bool isloggedin = false; 66 67 @override 68 widget build(buildcontext context) { 69 return scaffold( 70 appbar appbar( 71 title const text('flutter parse server'), 72 ), 73 body center( 74 child singlechildscrollview( 75 padding const edgeinsets all(8), 76 child column( 77 crossaxisalignment crossaxisalignment stretch, 78 children \[ 79 container( 80 height 200, 81 child image network( 82 'https //blog back4app com/wp content/uploads/2017/11/logo b4a 1 768x175 1 png'), 83 ), 84 center( 85 child const text('flutter on back4app', 86 style 87 textstyle(fontsize 18, fontweight fontweight bold)), 88 ), 89 sizedbox( 90 height 16, 91 ), 92 textfield( 93 controller controllerusername, 94 enabled !isloggedin, 95 keyboardtype textinputtype text, 96 textcapitalization textcapitalization none, 97 autocorrect false, 98 decoration inputdecoration( 99 border outlineinputborder( 100 borderside borderside(color colors black)), 101 labeltext 'username'), 102 ), 103 sizedbox( 104 height 8, 105 ), 106 textfield( 107 controller controllerpassword, 108 enabled !isloggedin, 109 obscuretext true, 110 keyboardtype textinputtype text, 111 textcapitalization textcapitalization none, 112 autocorrect false, 113 decoration inputdecoration( 114 border outlineinputborder( 115 borderside borderside(color colors black)), 116 labeltext 'password'), 117 ), 118 sizedbox( 119 height 16, 120 ), 121 container( 122 height 50, 123 child elevatedbutton( 124 child const text('login'), 125 onpressed isloggedin ? null () => douserlogin(), 126 ), 127 ), 128 sizedbox( 129 height 16, 130 ), 131 container( 132 height 50, 133 child elevatedbutton( 134 child const text('sign up'), 135 onpressed () => navigatetosignup(), 136 ), 137 ), 138 sizedbox( 139 height 16, 140 ), 141 container( 142 height 50, 143 child elevatedbutton( 144 child const text('reset password'), 145 onpressed () => navigatetoresetpassword(), 146 ), 147 ) 148 ), 149 ), 150 ), 151 )); 152 } 153 154 void douserlogin() async { 155 final username = controllerusername text trim(); 156 final password = controllerpassword text trim(); 157 158 final user = parseuser(username, password, null); 159 160 var response = await user login(); 161 162 if (response success) { 163 navigatetouser(); 164 } else { 165 message showerror(context context, message response error! message); 166 } 167 } 168 169 void navigatetouser() { 170 navigator pushandremoveuntil( 171 context, 172 materialpageroute(builder (context) => userpage()), 173 (route\<dynamic> route) => false, 174 ); 175 } 176 177 void navigatetosignup() { 178 navigator push( 179 context, 180 materialpageroute(builder (context) => signuppage()), 181 ); 182 } 183 184 void navigatetoresetpassword() { 185 navigator push( 186 context, 187 materialpageroute(builder (context) => resetpasswordpage()), 188 ); 189 } 190 } 191 192 class signuppage extends statefulwidget { 193 @override 194 signuppagestate createstate() => signuppagestate(); 195 } 196 197 class signuppagestate extends state\<signuppage> { 198 final controllerusername = texteditingcontroller(); 199 final controllerpassword = texteditingcontroller(); 200 final controlleremail = texteditingcontroller(); 201 202 @override 203 widget build(buildcontext context) { 204 return scaffold( 205 appbar appbar( 206 title const text('flutter sign up'), 207 ), 208 body center( 209 child singlechildscrollview( 210 padding const edgeinsets all(8), 211 child column( 212 crossaxisalignment crossaxisalignment stretch, 213 children \[ 214 container( 215 height 200, 216 child image network( 217 'https //blog back4app com/wp content/uploads/2017/11/logo b4a 1 768x175 1 png'), 218 ), 219 center( 220 child const text('flutter on back4app', 221 style 222 textstyle(fontsize 18, fontweight fontweight bold)), 223 ), 224 sizedbox( 225 height 16, 226 ), 227 center( 228 child const text('user registration', 229 style textstyle(fontsize 16)), 230 ), 231 sizedbox( 232 height 16, 233 ), 234 textfield( 235 controller controllerusername, 236 keyboardtype textinputtype text, 237 textcapitalization textcapitalization none, 238 autocorrect false, 239 decoration inputdecoration( 240 border outlineinputborder( 241 borderside borderside(color colors black)), 242 labeltext 'username'), 243 ), 244 sizedbox( 245 height 8, 246 ), 247 textfield( 248 controller controlleremail, 249 keyboardtype textinputtype emailaddress, 250 textcapitalization textcapitalization none, 251 autocorrect false, 252 decoration inputdecoration( 253 border outlineinputborder( 254 borderside borderside(color colors black)), 255 labeltext 'e mail'), 256 ), 257 sizedbox( 258 height 8, 259 ), 260 textfield( 261 controller controllerpassword, 262 obscuretext true, 263 keyboardtype textinputtype text, 264 textcapitalization textcapitalization none, 265 autocorrect false, 266 decoration inputdecoration( 267 border outlineinputborder( 268 borderside borderside(color colors black)), 269 labeltext 'password'), 270 ), 271 sizedbox( 272 height 8, 273 ), 274 container( 275 height 50, 276 child elevatedbutton( 277 child const text('sign up'), 278 onpressed () => douserregistration(), 279 ), 280 ) 281 ], 282 ), 283 ), 284 )); 285 } 286 287 void douserregistration() async { 288 final username = controllerusername text trim(); 289 final email = controlleremail text trim(); 290 final password = controllerpassword text trim(); 291 292 final user = parseuser createuser(username, password, email); 293 294 var response = await user signup(); 295 296 if (response success) { 297 message showsuccess( 298 context context, 299 message 'user was successfully created!', 300 onpressed () async { 301 navigator pushandremoveuntil( 302 context, 303 materialpageroute(builder (context) => userpage()), 304 (route\<dynamic> route) => false, 305 ); 306 }); 307 } else { 308 message showerror(context context, message response error! message); 309 } 310 } 311 } 312 313 class userpage extends statelesswidget { 314 parseuser? currentuser; 315 316 future\<parseuser?> getuser() async { 317 } 318 319 @override 320 widget build(buildcontext context) { 321 void douserlogout() async { 322 var response = await currentuser! logout(); 323 if (response success) { 324 message showsuccess( 325 context context, 326 message 'user was successfully logout!', 327 onpressed () { 328 navigator pushandremoveuntil( 329 context, 330 materialpageroute(builder (context) => loginpage()), 331 (route\<dynamic> route) => false, 332 ); 333 }); 334 } else { 335 message showerror(context context, message response error! message); 336 } 337 } 338 339 return scaffold( 340 appbar appbar( 341 title text('user logged in current user'), 342 ), 343 body futurebuilder\<parseuser?>( 344 future getuser(), 345 builder (context, snapshot) { 346 switch (snapshot connectionstate) { 347 case connectionstate none 348 case connectionstate waiting 349 return center( 350 child container( 351 width 100, 352 height 100, 353 child circularprogressindicator()), 354 ); 355 default 356 return padding( 357 padding const edgeinsets all(8 0), 358 child column( 359 crossaxisalignment crossaxisalignment stretch, 360 mainaxisalignment mainaxisalignment center, 361 children \[ 362 center( 363 child text('hello, ${snapshot data! username}')), 364 sizedbox( 365 height 16, 366 ), 367 container( 368 height 50, 369 child elevatedbutton( 370 child const text('logout'), 371 onpressed () => douserlogout(), 372 ), 373 ), 374 ], 375 ), 376 ); 377 } 378 })); 379 } 380 } 381 382 class resetpasswordpage extends statefulwidget { 383 @override 384 resetpasswordpagestate createstate() => resetpasswordpagestate(); 385 } 386 387 class resetpasswordpagestate extends state\<resetpasswordpage> { 388 final controlleremail = texteditingcontroller(); 389 390 @override 391 widget build(buildcontext context) { 392 return scaffold( 393 appbar appbar( 394 title text('reset password'), 395 ), 396 body singlechildscrollview( 397 padding const edgeinsets all(8), 398 child column( 399 crossaxisalignment crossaxisalignment stretch, 400 children \[ 401 textfield( 402 controller controlleremail, 403 keyboardtype textinputtype emailaddress, 404 textcapitalization textcapitalization none, 405 autocorrect false, 406 decoration inputdecoration( 407 border outlineinputborder( 408 borderside borderside(color colors black)), 409 labeltext 'e mail'), 410 ), 411 sizedbox( 412 height 8, 413 ), 414 container( 415 height 50, 416 child elevatedbutton( 417 child const text('reset password'), 418 onpressed () => douserresetpassword(), 419 ), 420 ) 421 ], 422 ), 423 )); 424 } 425 426 void douserresetpassword() async {} 427 } 428 429 class message { 430 static void showsuccess( 431 {required buildcontext context, 432 required string message, 433 voidcallback? onpressed}) { 434 showdialog( 435 context context, 436 builder (buildcontext context) { 437 return alertdialog( 438 title const text("success!"), 439 content text(message), 440 actions \<widget>\[ 441 new elevatedbutton( 442 child const text("ok"), 443 onpressed () { 444 navigator of(context) pop(); 445 if (onpressed != null) { 446 onpressed(); 447 } 448 }, 449 ), 450 ], 451 ); 452 }, 453 ); 454 } 455 456 static void showerror( 457 {required buildcontext context, 458 required string message, 459 voidcallback? onpressed}) { 460 showdialog( 461 context context, 462 builder (buildcontext context) { 463 return alertdialog( 464 title const text("error!"), 465 content text(message), 466 actions \<widget>\[ 467 new elevatedbutton( 468 child const text("ok"), 469 onpressed () { 470 navigator of(context) pop(); 471 if (onpressed != null) { 472 onpressed(); 473 } 474 }, 475 ), 476 ], 477 ); 478 }, 479 ); 480 } 481 } 482 when debug debug parameter in function parse() initialize parse() initialize is true true , allows displaying parse api calls on the console this configuration can help you debug the code it is prudent to disable debug in the release version 2 connect template to back4app project find your application id and client key credentials navigating to your app dashboard at back4app website https //www back4app com/ update your code in main dart main dart with the values of your project’s applicationid and clientkey in back4app keyapplicationid = app id keyclientkey = client key run the project, and the app will load as shown in the image 3 code for get current user on session the user login or signup function creates a session session object, which points to the user user logged in and stores in your local storage a valid user session calls to methods currentuser currentuser will successfully retrieve your parseuser parseuser data and sessiontoken sessiontoken for session session object search for the function hasuserlogged hasuserlogged in the file main dart main dart replace the code inside hasuserlogged hasuserlogged with 1 parseuser? currentuser = await parseuser currentuser() as parseuser?; 2 if (currentuser == null) { 3 return false; 4 } 5 //checks whether the user's session token is valid 6 final parseresponse? parseresponse = 7 await parseuser getcurrentuserfromserver(currentuser sessiontoken!); 8 9 if (parseresponse? success == null || !parseresponse! success) { 10 //invalid session logout 11 await currentuser logout(); 12 return false; 13 } else { 14 return true; 15 } to build this function, follow these steps call the parseuser currentuser() parseuser currentuser() function, which will return a parseuser parseuser object from local storage if parseuser parseuser is null, we do not have any users with an active session in the app if parseuser parseuser is not null, we have a user with an active session in our app the user’s session needs to be validated on the parse server, as it has a lifetime if the token is not valid, it is necessary to call the logout function to clear the current session and the user needs to log in again the complete function should look like this 1 future\<bool> hasuserlogged() async { 2 parseuser? currentuser = await parseuser currentuser() as parseuser?; 3 if (currentuser == null) { 4 return false; 5 } 6 //checks whether the user's session token is valid 7 final parseresponse? parseresponse = 8 await parseuser getcurrentuserfromserver(currentuser sessiontoken!); 9 10 if (parseresponse? success == null || !parseresponse! success) { 11 //invalid session logout 12 await currentuser logout(); 13 return false; 14 } else { 15 return true; 16 } 17 } look for the function getuser getuser in the file main dart main dart replace the code inside getuser getuser with 1 currentuser = await parseuser currentuser() as parseuser?; 2 return currentuser; to build this function, follow these steps call the parseuser currentuser() parseuser currentuser() function, which will return a parseuser parseuser object from local storage the complete function should look like this 1 future\<parseuser> getuser() async { 2 currentuser = await parseuser currentuser() as parseuser?; 3 return currentuser; 4 } to test it, click on the run run button in android studio/vscode signup or login and the next screen will display the username of the logged in user quit the application and run again if a valid user session is identified, the screen with the user’s username will be displayed it’s done! at the end of this guide, you can get current user on session of your app using parse server core features through back4app!