[{"data":1,"prerenderedAt":2207},["ShallowReactive",2],{"navigation":3,"\u002Fbooki-documentation\u002Fguides\u002Fguides-auth-flow":303,"\u002Fbooki-documentation\u002Fguides\u002Fguides-auth-flow-surround":2202},[4,55,105],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":54},"Nuxt Guide","i-lucide-layout","\u002Fnuxt-guide","1.nuxt-guide",[10,14,19,24,29,34,39,44,49],{"title":11,"path":12,"stem":13,"icon":6},"Overview","\u002Fnuxt-guide\u002Foverview","1.nuxt-guide\u002F1.overview",{"title":15,"path":16,"stem":17,"icon":18},"Folder Structure","\u002Fnuxt-guide\u002Ffolder-structure","1.nuxt-guide\u002F2.folder-structure","i-lucide-folder-tree",{"title":20,"path":21,"stem":22,"icon":23},"Components","\u002Fnuxt-guide\u002Fcomponents","1.nuxt-guide\u002F3.components","i-lucide-component",{"title":25,"path":26,"stem":27,"icon":28},"Composables","\u002Fnuxt-guide\u002Fcomposables","1.nuxt-guide\u002F4.composables","i-lucide-puzzle",{"title":30,"path":31,"stem":32,"icon":33},"Pages & Routing","\u002Fnuxt-guide\u002Fpages-routing","1.nuxt-guide\u002F5.pages-routing","i-lucide-file-text",{"title":35,"path":36,"stem":37,"icon":38},"Middleware","\u002Fnuxt-guide\u002Fmiddleware","1.nuxt-guide\u002F6.middleware","i-lucide-shield-check",{"title":40,"path":41,"stem":42,"icon":43},"Plugins","\u002Fnuxt-guide\u002Fplugins","1.nuxt-guide\u002F7.plugins","i-lucide-plug",{"title":45,"path":46,"stem":47,"icon":48},"State Management","\u002Fnuxt-guide\u002Fstate-management","1.nuxt-guide\u002F8.state-management","i-lucide-database",{"title":50,"path":51,"stem":52,"icon":53},"TypeScript","\u002Fnuxt-guide\u002Ftypescript","1.nuxt-guide\u002F9.typescript","i-lucide-braces",false,{"title":56,"icon":57,"path":58,"stem":59,"children":60,"page":54},"Node \u002F Express Guide","i-lucide-server","\u002Fnode-express-guide","2.node-express-guide",[61,64,69,72,77,82,86,91,96,100],{"title":11,"path":62,"stem":63,"icon":57},"\u002Fnode-express-guide\u002Foverview","2.node-express-guide\u002F1.overview",{"title":65,"path":66,"stem":67,"icon":68},"Error Handling","\u002Fnode-express-guide\u002Ferror-handling","2.node-express-guide\u002F10.error-handling","i-lucide-alert-triangle",{"title":15,"path":70,"stem":71,"icon":18},"\u002Fnode-express-guide\u002Ffolder-structure","2.node-express-guide\u002F2.folder-structure",{"title":73,"path":74,"stem":75,"icon":76},"Controllers","\u002Fnode-express-guide\u002Fcontrollers","2.node-express-guide\u002F3.controllers","i-lucide-cpu",{"title":78,"path":79,"stem":80,"icon":81},"Services","\u002Fnode-express-guide\u002Fservices","2.node-express-guide\u002F4.services","i-lucide-workflow",{"title":83,"path":84,"stem":85,"icon":48},"Repositories","\u002Fnode-express-guide\u002Frepositories","2.node-express-guide\u002F5.repositories",{"title":87,"path":88,"stem":89,"icon":90},"Models","\u002Fnode-express-guide\u002Fmodels","2.node-express-guide\u002F6.models","i-lucide-boxes",{"title":92,"path":93,"stem":94,"icon":95},"Routes","\u002Fnode-express-guide\u002Froutes","2.node-express-guide\u002F7.routes","i-lucide-route",{"title":35,"path":97,"stem":98,"icon":99},"\u002Fnode-express-guide\u002Fmiddleware","2.node-express-guide\u002F8.middleware","i-lucide-shield",{"title":101,"path":102,"stem":103,"icon":104},"Validation","\u002Fnode-express-guide\u002Fvalidation","2.node-express-guide\u002F9.validation","i-lucide-check-circle",{"title":106,"icon":107,"path":108,"stem":109,"children":110,"page":54},"Booki Documentation","i-lucide-book-open","\u002Fbooki-documentation","3.booki-documentation",[111,115,120,125,130,229,244,257],{"title":112,"path":113,"stem":114,"icon":107},"Project Overview","\u002Fbooki-documentation\u002Foverview","3.booki-documentation\u002F1.overview",{"title":116,"path":117,"stem":118,"icon":119},"Installation","\u002Fbooki-documentation\u002F1.installation","3.booki-documentation\u002F2.1.installation","i-lucide-download",{"title":121,"path":122,"stem":123,"icon":124},"Development Overview","\u002Fbooki-documentation\u002F2.architecture","3.booki-documentation\u002F2.2.architecture","i-lucide-layers",{"title":126,"path":127,"stem":128,"icon":129},"Local Development","\u002Fbooki-documentation\u002F3.local-development","3.booki-documentation\u002F2.3.local-development","i-lucide-monitor",{"title":131,"icon":57,"path":132,"stem":133,"children":134,"page":54},"API","\u002Fbooki-documentation\u002Fapi","3.booki-documentation\u002F3.api",[135,139,144,149,154,159,163,168,173,178,183,188,192,197,202,206,211,216,220,224],{"title":136,"path":137,"stem":138,"icon":57},"Booki API Reference","\u002Fbooki-documentation\u002Fapi\u002Fbooki-api","3.booki-documentation\u002F3.api\u002F1.booki-api",{"title":140,"path":141,"stem":142,"icon":143},"Auth - Login & Refresh","\u002Fbooki-documentation\u002Fapi\u002Fauth","3.booki-documentation\u002F3.api\u002F2.auth","i-lucide-key",{"title":145,"path":146,"stem":147,"icon":148},"Auth - Customer Registration","\u002Fbooki-documentation\u002Fapi\u002Fauth-customer-register","3.booki-documentation\u002F3.api\u002F2.auth-customer-register","i-lucide-user-check",{"title":150,"path":151,"stem":152,"icon":153},"Auth - Owner Registration","\u002Fbooki-documentation\u002Fapi\u002Fauth-owner-register","3.booki-documentation\u002F3.api\u002F2.auth-owner-register","i-lucide-user-plus",{"title":155,"path":156,"stem":157,"icon":158},"Bookings","\u002Fbooki-documentation\u002Fapi\u002Fbookings","3.booki-documentation\u002F3.api\u002F3.bookings","i-lucide-calendar-check",{"title":160,"path":161,"stem":162,"icon":158},"Bookings - Authenticated","\u002Fbooki-documentation\u002Fapi\u002Fbookings-auth","3.booki-documentation\u002F3.api\u002F3.bookings-auth",{"title":164,"path":165,"stem":166,"icon":167},"Bookings - Public & Guest","\u002Fbooki-documentation\u002Fapi\u002Fbookings-public","3.booki-documentation\u002F3.api\u002F3.bookings-public","i-lucide-calendar-plus",{"title":169,"path":170,"stem":171,"icon":172},"Booking Services","\u002Fbooki-documentation\u002Fapi\u002Fbooking-services","3.booki-documentation\u002F3.api\u002F4.booking-services","i-lucide-box",{"title":174,"path":175,"stem":176,"icon":177},"Organizations - Branches","\u002Fbooki-documentation\u002Fapi\u002Fbranches","3.booki-documentation\u002F3.api\u002F5.branches","i-lucide-git-branch",{"title":179,"path":180,"stem":181,"icon":182},"Organizations - Business Hours","\u002Fbooki-documentation\u002Fapi\u002Fbusiness-hours","3.booki-documentation\u002F3.api\u002F5.business-hours","i-lucide-clock",{"title":184,"path":185,"stem":186,"icon":187},"Organizations - Base","\u002Fbooki-documentation\u002Fapi\u002Forganizations","3.booki-documentation\u002F3.api\u002F5.organizations","i-lucide-building-2",{"title":189,"path":190,"stem":191,"icon":172},"Organizations - Packages","\u002Fbooki-documentation\u002Fapi\u002Fpackages","3.booki-documentation\u002F3.api\u002F5.packages",{"title":193,"path":194,"stem":195,"icon":196},"Organizations - Payments & Integrations","\u002Fbooki-documentation\u002Fapi\u002Fpayments","3.booki-documentation\u002F3.api\u002F5.payments","i-lucide-credit-card",{"title":198,"path":199,"stem":200,"icon":201},"Users - Profile & Settings","\u002Fbooki-documentation\u002Fapi\u002Fusers","3.booki-documentation\u002F3.api\u002F6.users","i-lucide-user",{"title":203,"path":204,"stem":205,"icon":196},"Maya Payments","\u002Fbooki-documentation\u002Fapi\u002Fmaya","3.booki-documentation\u002F3.api\u002F7.maya",{"title":207,"path":208,"stem":209,"icon":210},"Owner - Booking Management","\u002Fbooki-documentation\u002Fapi\u002Fowner-bookings","3.booki-documentation\u002F3.api\u002F7.owner-bookings","i-lucide-calendar",{"title":212,"path":213,"stem":214,"icon":215},"Owner - Customer Management","\u002Fbooki-documentation\u002Fapi\u002Fowner-customers","3.booki-documentation\u002F3.api\u002F7.owner-customers","i-lucide-users",{"title":217,"path":218,"stem":219,"icon":196},"Admin - Billing & Subscriptions","\u002Fbooki-documentation\u002Fapi\u002Fadmin-billing","3.booki-documentation\u002F3.api\u002F8.admin-billing",{"title":221,"path":222,"stem":223,"icon":187},"Admin - Organizations Management","\u002Fbooki-documentation\u002Fapi\u002Fadmin-organizations","3.booki-documentation\u002F3.api\u002F8.admin-organizations",{"title":225,"path":226,"stem":227,"icon":228},"Admin - User Management","\u002Fbooki-documentation\u002Fapi\u002Fadmin-users","3.booki-documentation\u002F3.api\u002F8.admin-users","i-lucide-shield-admin",{"title":230,"icon":231,"path":232,"stem":233,"children":234,"page":54},"Shared","i-lucide-package","\u002Fbooki-documentation\u002Fshared","3.booki-documentation\u002F4.shared",[235,240],{"title":236,"path":237,"stem":238,"icon":239},"codi-node-utils","\u002Fbooki-documentation\u002Fshared\u002Fcodi-node-utils","3.booki-documentation\u002F4.shared\u002F1.codi-node-utils","i-lucide-wrench",{"title":241,"path":242,"stem":243,"icon":124},"codi-layer","\u002Fbooki-documentation\u002Fshared\u002Fcodi-layer","3.booki-documentation\u002F4.shared\u002F2.codi-layer",{"title":245,"path":246,"stem":247,"children":248,"page":54},"Flowcharts","\u002Fbooki-documentation\u002Fflowcharts","3.booki-documentation\u002F5.flowcharts",[249,253],{"title":250,"path":251,"stem":252,"icon":158},"Owner Booking Management Flow","\u002Fbooki-documentation\u002Fflowcharts\u002Fowner-booking-management","3.booki-documentation\u002F5.flowcharts\u002F1.owner-booking-management",{"title":254,"path":255,"stem":256,"icon":167},"Customer Booking Flow","\u002Fbooki-documentation\u002Fflowcharts\u002Fcustomer-booking-flow","3.booki-documentation\u002F5.flowcharts\u002F2.customer-booking-flow",{"title":258,"path":259,"stem":260,"children":261,"page":54},"Guides","\u002Fbooki-documentation\u002Fguides","3.booki-documentation\u002Fguides",[262,267,271,275,280,285,290,294,298],{"title":263,"path":264,"stem":265,"icon":266},"Guide - Authentication Flow & Sessions","\u002Fbooki-documentation\u002Fguides\u002Fguides-auth-flow","3.booki-documentation\u002Fguides\u002Fguides-auth-flow","i-lucide-lock",{"title":268,"path":269,"stem":270,"icon":177},"Guide - Branch Management","\u002Fbooki-documentation\u002Fguides\u002Fguides-branch-management","3.booki-documentation\u002Fguides\u002Fguides-branch-management",{"title":272,"path":273,"stem":274,"icon":196},"Guide - Customer Payment Methods","\u002Fbooki-documentation\u002Fguides\u002Fguides-customer-payments","3.booki-documentation\u002Fguides\u002Fguides-customer-payments",{"title":276,"path":277,"stem":278,"icon":279},"Guide - Environment Setup","\u002Fbooki-documentation\u002Fguides\u002Fguides-environment-setup","3.booki-documentation\u002Fguides\u002Fguides-environment-setup","i-lucide-settings",{"title":281,"path":282,"stem":283,"icon":284},"Guide - Common Error Responses","\u002Fbooki-documentation\u002Fguides\u002Fguides-errors","3.booki-documentation\u002Fguides\u002Fguides-errors","i-lucide-alert-circle",{"title":286,"path":287,"stem":288,"icon":289},"Guide - Gmail SMTP Setup","\u002Fbooki-documentation\u002Fguides\u002Fguides-gmail-setup","3.booki-documentation\u002Fguides\u002Fguides-gmail-setup","i-lucide-mail",{"title":291,"path":292,"stem":293,"icon":124},"Guide - Multi-Tenancy & Tenant Slug Resolution","\u002Fbooki-documentation\u002Fguides\u002Fguides-multi-tenancy","3.booki-documentation\u002Fguides\u002Fguides-multi-tenancy",{"title":295,"path":296,"stem":297,"icon":48},"Guide - Redis Caching","\u002Fbooki-documentation\u002Fguides\u002Fguides-redis","3.booki-documentation\u002Fguides\u002Fguides-redis",{"title":299,"path":300,"stem":301,"icon":302},"Guide - Subscription Billing","\u002Fbooki-documentation\u002Fguides\u002Fguides-subscription-billing","3.booki-documentation\u002Fguides\u002Fguides-subscription-billing","i-lucide-receipt",{"id":304,"title":263,"body":305,"description":2195,"extension":2196,"links":2197,"meta":2198,"navigation":2199,"path":264,"seo":2200,"stem":265,"__hash__":2201},"docs\u002F3.booki-documentation\u002Fguides\u002Fguides-auth-flow.md",{"type":306,"value":307,"toc":2153},"minimark",[308,317,320,325,328,360,362,366,371,388,536,540,554,648,650,654,662,664,668,676,681,749,754,825,830,846,848,852,856,866,896,901,923,925,929,932,936,942,950,954,995,999,1047,1051,1065,1067,1071,1077,1079,1083,1087,1185,1189,1253,1257,1263,1291,1296,1342,1344,1348,1352,1378,1382,1402,1404,1408,1416,1420,1449,1453,1484,1488,1499,1501,1505,1508,1512,1576,1580,1654,1658,1754,1756,1760,1765,1940,1945,1980,1982,1986,2074,2079,2110,2115,2129,2131,2135,2149],[309,310,311,312,316],"p",{},"Booki uses ",[313,314,315],"strong",{},"JWT-based authentication with Bearer tokens"," for secure, stateless session management. This guide explains the complete authentication lifecycle.",[318,319],"hr",{},[321,322,324],"h2",{"id":323},"authentication-architecture","Authentication Architecture",[309,326,327],{},"The Booki API uses:",[309,329,330,331,334,335,338,339,342,343,347,348,338,350,353,354,338,356,359],{},"✅ ",[313,332,333],{},"JWT Tokens"," — Stateless credentials (no session database needed)",[336,337],"br",{},"\n✅ ",[313,340,341],{},"Authorization Header"," — ",[344,345,346],"code",{},"Bearer \u003Ctoken>"," sent by frontend plugin on every request",[336,349],{},[313,351,352],{},"Refresh Tokens"," — Long-lived tokens for session renewal",[336,355],{},[313,357,358],{},"Dual Token Pattern"," — Short-lived access + long-lived refresh returned in response body",[318,361],{},[321,363,365],{"id":364},"token-concepts","Token Concepts",[367,368,370],"h3",{"id":369},"access-token","Access Token",[309,372,373,376,377,379,382,383,385],{},[313,374,375],{},"Purpose:"," Proves user identity to the API",[336,378],{},[313,380,381],{},"Lifetime:"," 15 minutes (900 seconds)",[336,384],{},[313,386,387],{},"Payload contains:",[389,390,395],"pre",{"className":391,"code":392,"language":393,"meta":394,"style":394},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"user\": \"507f1f77bcf86cd799439011\",\n  \"organizationId\": \"507f191e810c19729de860ea\",\n  \"role\": \"owner\",\n  \"jti\": \"uuid-for-revocation\",\n  \"iat\": 1712332080,\n  \"exp\": 1712332980\n}\n","json","",[344,396,397,406,434,455,476,497,515,530],{"__ignoreMap":394},[398,399,402],"span",{"class":400,"line":401},"line",1,[398,403,405],{"class":404},"sMK4o","{\n",[398,407,409,412,416,419,422,425,429,431],{"class":400,"line":408},2,[398,410,411],{"class":404},"  \"",[398,413,415],{"class":414},"spNyl","user",[398,417,418],{"class":404},"\"",[398,420,421],{"class":404},":",[398,423,424],{"class":404}," \"",[398,426,428],{"class":427},"sfazB","507f1f77bcf86cd799439011",[398,430,418],{"class":404},[398,432,433],{"class":404},",\n",[398,435,437,439,442,444,446,448,451,453],{"class":400,"line":436},3,[398,438,411],{"class":404},[398,440,441],{"class":414},"organizationId",[398,443,418],{"class":404},[398,445,421],{"class":404},[398,447,424],{"class":404},[398,449,450],{"class":427},"507f191e810c19729de860ea",[398,452,418],{"class":404},[398,454,433],{"class":404},[398,456,458,460,463,465,467,469,472,474],{"class":400,"line":457},4,[398,459,411],{"class":404},[398,461,462],{"class":414},"role",[398,464,418],{"class":404},[398,466,421],{"class":404},[398,468,424],{"class":404},[398,470,471],{"class":427},"owner",[398,473,418],{"class":404},[398,475,433],{"class":404},[398,477,479,481,484,486,488,490,493,495],{"class":400,"line":478},5,[398,480,411],{"class":404},[398,482,483],{"class":414},"jti",[398,485,418],{"class":404},[398,487,421],{"class":404},[398,489,424],{"class":404},[398,491,492],{"class":427},"uuid-for-revocation",[398,494,418],{"class":404},[398,496,433],{"class":404},[398,498,500,502,505,507,509,513],{"class":400,"line":499},6,[398,501,411],{"class":404},[398,503,504],{"class":414},"iat",[398,506,418],{"class":404},[398,508,421],{"class":404},[398,510,512],{"class":511},"sbssI"," 1712332080",[398,514,433],{"class":404},[398,516,518,520,523,525,527],{"class":400,"line":517},7,[398,519,411],{"class":404},[398,521,522],{"class":414},"exp",[398,524,418],{"class":404},[398,526,421],{"class":404},[398,528,529],{"class":511}," 1712332980\n",[398,531,533],{"class":400,"line":532},8,[398,534,535],{"class":404},"}\n",[367,537,539],{"id":538},"refresh-token","Refresh Token",[309,541,542,544,545,547,549,550,552],{},[313,543,375],{}," Obtain new access token without re-entering credentials",[336,546],{},[313,548,381],{}," 7 days (expires, then user must login again)",[336,551],{},[313,553,387],{},[389,555,557],{"className":391,"code":556,"language":393,"meta":394,"style":394},"{\n  \"user\": \"507f1f77bcf86cd799439011\",\n  \"organizationId\": \"507f191e810c19729de860ea\",\n  \"role\": \"owner\",\n  \"iat\": 1712332080,\n  \"exp\": 1712937680\n}\n",[344,558,559,563,581,599,617,631,644],{"__ignoreMap":394},[398,560,561],{"class":400,"line":401},[398,562,405],{"class":404},[398,564,565,567,569,571,573,575,577,579],{"class":400,"line":408},[398,566,411],{"class":404},[398,568,415],{"class":414},[398,570,418],{"class":404},[398,572,421],{"class":404},[398,574,424],{"class":404},[398,576,428],{"class":427},[398,578,418],{"class":404},[398,580,433],{"class":404},[398,582,583,585,587,589,591,593,595,597],{"class":400,"line":436},[398,584,411],{"class":404},[398,586,441],{"class":414},[398,588,418],{"class":404},[398,590,421],{"class":404},[398,592,424],{"class":404},[398,594,450],{"class":427},[398,596,418],{"class":404},[398,598,433],{"class":404},[398,600,601,603,605,607,609,611,613,615],{"class":400,"line":457},[398,602,411],{"class":404},[398,604,462],{"class":414},[398,606,418],{"class":404},[398,608,421],{"class":404},[398,610,424],{"class":404},[398,612,471],{"class":427},[398,614,418],{"class":404},[398,616,433],{"class":404},[398,618,619,621,623,625,627,629],{"class":400,"line":478},[398,620,411],{"class":404},[398,622,504],{"class":414},[398,624,418],{"class":404},[398,626,421],{"class":404},[398,628,512],{"class":511},[398,630,433],{"class":404},[398,632,633,635,637,639,641],{"class":400,"line":499},[398,634,411],{"class":404},[398,636,522],{"class":414},[398,638,418],{"class":404},[398,640,421],{"class":404},[398,642,643],{"class":511}," 1712937680\n",[398,645,646],{"class":400,"line":517},[398,647,535],{"class":404},[318,649],{},[321,651,653],{"id":652},"complete-login-flow","Complete Login Flow",[389,655,660],{"className":656,"code":658,"language":659},[657],"language-text","┌─────────────────────────────────────────────┐\n│  1. User enters credentials                 │\n│     Email: jane@example.com                 │\n│     Password: SecureP@ss123                 │\n└──────────────┬──────────────────────────────┘\n               │\n               ↓\n┌──────────────────────────────────────────────┐\n│  2. POST \u002Fapi\u002Fauth\u002Flogin                    │\n│     Request body contains credentials       │\n└──────────────┬──────────────────────────────┘\n               │\n               ↓\n┌──────────────────────────────────────────────┐\n│  3. Server validates credentials            │\n│     - Lookup user by email                  │\n│     - Hash incoming password                │\n│     - Compare with stored hash              │\n│     - If mismatch → 401 Unauthorized        │\n└──────────────┬──────────────────────────────┘\n               │\n               ↓ (if valid)\n┌──────────────────────────────────────────────┐\n│  4. Generate JWT tokens                     │\n│     - accessToken (15 min lifetime)        │\n│     - refreshToken (7 day lifetime)        │\n└──────────────┬──────────────────────────────┘\n               │\n               ↓\n┌──────────────────────────────────────────────┐\n│  5. Set HttpOnly cookies in response        │\n│     Set-Cookie: access_token=jwt; HttpOnly  │\n│     Set-Cookie: refresh_token=jwt; HttpOnly │\n│     Set-Cookie: Path=\u002F; Secure              │\n└──────────────┬──────────────────────────────┘\n               │\n               ↓\n┌──────────────────────────────────────────────┐\n│  6. Browser automatically stores cookies    │\n│     (JavaScript cannot access them)         │\n└──────────────┬──────────────────────────────┘\n               │\n               ↓\n┌──────────────────────────────────────────────┐\n│  7. Response to client                      │\n│     {                                       │\n│       \"user\": { profile data },            │\n│       \"expiresIn\": 900                      │\n│     }                                       │\n└──────────────┴──────────────────────────────┘\n","text",[344,661,658],{"__ignoreMap":394},[318,663],{},[321,665,667],{"id":666},"step-by-step-login","Step-by-Step Login",[367,669,671,672,675],{"id":670},"_1-post-apiauthlogin-initial-login","1. POST ",[344,673,674],{},"\u002Fapi\u002Fauth\u002Flogin"," — Initial Login",[309,677,678],{},[313,679,680],{},"Request:",[389,682,686],{"className":683,"code":684,"language":685,"meta":394,"style":394},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","curl -X POST https:\u002F\u002Fapi.booki.app\u002Fapi\u002Fauth\u002Flogin \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"email\": \"jane@example.com\",\n    \"password\": \"SecureP@ss123\"\n  }'\n","bash",[344,687,688,707,721,731,736,741],{"__ignoreMap":394},[398,689,690,694,697,700,703],{"class":400,"line":401},[398,691,693],{"class":692},"sBMFI","curl",[398,695,696],{"class":427}," -X",[398,698,699],{"class":427}," POST",[398,701,702],{"class":427}," https:\u002F\u002Fapi.booki.app\u002Fapi\u002Fauth\u002Flogin",[398,704,706],{"class":705},"sTEyZ"," \\\n",[398,708,709,712,714,717,719],{"class":400,"line":408},[398,710,711],{"class":427},"  -H",[398,713,424],{"class":404},[398,715,716],{"class":427},"Content-Type: application\u002Fjson",[398,718,418],{"class":404},[398,720,706],{"class":705},[398,722,723,726,729],{"class":400,"line":436},[398,724,725],{"class":427},"  -d",[398,727,728],{"class":404}," '",[398,730,405],{"class":427},[398,732,733],{"class":400,"line":457},[398,734,735],{"class":427},"    \"email\": \"jane@example.com\",\n",[398,737,738],{"class":400,"line":478},[398,739,740],{"class":427},"    \"password\": \"SecureP@ss123\"\n",[398,742,743,746],{"class":400,"line":499},[398,744,745],{"class":427},"  }",[398,747,748],{"class":404},"'\n",[309,750,751],{},[313,752,753],{},"Response (200 OK):",[389,755,757],{"className":391,"code":756,"language":393,"meta":394,"style":394},"{\n  \"accessToken\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\n  \"refreshToken\": \"abc123def456...\",\n  \"_id\": \"507f1f77bcf86cd799439011\"\n}\n",[344,758,759,763,783,803,821],{"__ignoreMap":394},[398,760,761],{"class":400,"line":401},[398,762,405],{"class":404},[398,764,765,767,770,772,774,776,779,781],{"class":400,"line":408},[398,766,411],{"class":404},[398,768,769],{"class":414},"accessToken",[398,771,418],{"class":404},[398,773,421],{"class":404},[398,775,424],{"class":404},[398,777,778],{"class":427},"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",[398,780,418],{"class":404},[398,782,433],{"class":404},[398,784,785,787,790,792,794,796,799,801],{"class":400,"line":436},[398,786,411],{"class":404},[398,788,789],{"class":414},"refreshToken",[398,791,418],{"class":404},[398,793,421],{"class":404},[398,795,424],{"class":404},[398,797,798],{"class":427},"abc123def456...",[398,800,418],{"class":404},[398,802,433],{"class":404},[398,804,805,807,810,812,814,816,818],{"class":400,"line":457},[398,806,411],{"class":404},[398,808,809],{"class":414},"_id",[398,811,418],{"class":404},[398,813,421],{"class":404},[398,815,424],{"class":404},[398,817,428],{"class":427},[398,819,820],{"class":404},"\"\n",[398,822,823],{"class":400,"line":478},[398,824,535],{"class":404},[309,826,827],{},[313,828,829],{},"What happened:",[831,832,833,837,843],"ul",{},[834,835,836],"li",{},"✅ Frontend plugin received and stored both tokens",[834,838,839,840],{},"✅ All future requests include ",[344,841,842],{},"Authorization: Bearer \u003CaccessToken>",[834,844,845],{},"✅ Access token valid for configured expiry",[318,847],{},[321,849,851],{"id":850},"authenticated-requests","Authenticated Requests",[367,853,855],{"id":854},"using-authorization-header","Using Authorization Header",[309,857,858,859,861,862,865],{},"After login, include the ",[344,860,769],{}," in the ",[344,863,864],{},"Authorization"," header:",[389,867,869],{"className":683,"code":868,"language":685,"meta":394,"style":394},"curl -X GET https:\u002F\u002Fapi.booki.app\u002Fapi\u002Fauth\u002Fuser \\\n  -H \"Authorization: Bearer eyJhbGc...\"\n",[344,870,871,885],{"__ignoreMap":394},[398,872,873,875,877,880,883],{"class":400,"line":401},[398,874,693],{"class":692},[398,876,696],{"class":427},[398,878,879],{"class":427}," GET",[398,881,882],{"class":427}," https:\u002F\u002Fapi.booki.app\u002Fapi\u002Fauth\u002Fuser",[398,884,706],{"class":705},[398,886,887,889,891,894],{"class":400,"line":408},[398,888,711],{"class":427},[398,890,424],{"class":404},[398,892,893],{"class":427},"Authorization: Bearer eyJhbGc...",[398,895,820],{"class":404},[309,897,898],{},[313,899,900],{},"Server validates:",[902,903,904,911,914,917,920],"ol",{},[834,905,906,907,910],{},"Extract token from ",[344,908,909],{},"Authorization: Bearer \u003Ctoken>"," header",[834,912,913],{},"Verify JWT signature",[834,915,916],{},"Check expiration (not expired)",[834,918,919],{},"Check JTI is not revoked in Redis",[834,921,922],{},"Return user data or 401 if invalid",[318,924],{},[321,926,928],{"id":927},"token-refresh-flow","Token Refresh Flow",[309,930,931],{},"When access token expires (15 minutes), client doesn't re-login. Instead:",[367,933,935],{"id":934},"automatic-token-refresh","Automatic Token Refresh",[389,937,940],{"className":938,"code":939,"language":659},[657],"Time: 0:00   Login\n├─ Access token expires in 900 seconds (15 min)\n├─ Refresh token valid for 7 days\n│\nTime: 14:50  (Before expiry)\n├─ Browser detects token nearly expired\n├─ Auto-calls POST \u002Fapi\u002Fauth\u002Frefresh\n│\nTime: 14:51  POST \u002Fapi\u002Fauth\u002Frefresh\n├─ Server validates refresh_token\n├─ Issues new access_token (fresh 15 min)\n├─ Returns new tokens in JSON response body\n│\nTime: 14:52  User resumes using API\n└─ New access_token in all requests\n",[344,941,939],{"__ignoreMap":394},[367,943,945,946,949],{"id":944},"_2-post-apiauthrefresh-get-new-access-token","2. POST ",[344,947,948],{},"\u002Fapi\u002Fauth\u002Frefresh"," — Get New Access Token",[309,951,952],{},[313,953,680],{},[389,955,957],{"className":683,"code":956,"language":685,"meta":394,"style":394},"curl -X POST https:\u002F\u002Fapi.booki.app\u002Fapi\u002Fauth\u002Frefresh \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"token\": \"abc123def456...\"}'\n",[344,958,959,972,984],{"__ignoreMap":394},[398,960,961,963,965,967,970],{"class":400,"line":401},[398,962,693],{"class":692},[398,964,696],{"class":427},[398,966,699],{"class":427},[398,968,969],{"class":427}," https:\u002F\u002Fapi.booki.app\u002Fapi\u002Fauth\u002Frefresh",[398,971,706],{"class":705},[398,973,974,976,978,980,982],{"class":400,"line":408},[398,975,711],{"class":427},[398,977,424],{"class":404},[398,979,716],{"class":427},[398,981,418],{"class":404},[398,983,706],{"class":705},[398,985,986,988,990,993],{"class":400,"line":436},[398,987,725],{"class":427},[398,989,728],{"class":404},[398,991,992],{"class":427},"{\"token\": \"abc123def456...\"}",[398,994,748],{"class":404},[309,996,997],{},[313,998,753],{},[389,1000,1002],{"className":391,"code":1001,"language":393,"meta":394,"style":394},"{\n  \"accessToken\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\n  \"refreshToken\": \"newRefreshToken123...\"\n}\n",[344,1003,1004,1008,1026,1043],{"__ignoreMap":394},[398,1005,1006],{"class":400,"line":401},[398,1007,405],{"class":404},[398,1009,1010,1012,1014,1016,1018,1020,1022,1024],{"class":400,"line":408},[398,1011,411],{"class":404},[398,1013,769],{"class":414},[398,1015,418],{"class":404},[398,1017,421],{"class":404},[398,1019,424],{"class":404},[398,1021,778],{"class":427},[398,1023,418],{"class":404},[398,1025,433],{"class":404},[398,1027,1028,1030,1032,1034,1036,1038,1041],{"class":400,"line":436},[398,1029,411],{"class":404},[398,1031,789],{"class":414},[398,1033,418],{"class":404},[398,1035,421],{"class":404},[398,1037,424],{"class":404},[398,1039,1040],{"class":427},"newRefreshToken123...",[398,1042,820],{"class":404},[398,1044,1045],{"class":400,"line":457},[398,1046,535],{"class":404},[309,1048,1049],{},[313,1050,829],{},[831,1052,1053,1056,1059,1062],{},[834,1054,1055],{},"✅ Old access token discarded",[834,1057,1058],{},"✅ New access token issued",[834,1060,1061],{},"✅ User seamlessly continues (no re-login needed)",[834,1063,1064],{},"✅ Refresh token stays valid for remaining days",[318,1066],{},[321,1068,1070],{"id":1069},"session-lifespan-timeline","Session Lifespan Timeline",[389,1072,1075],{"className":1073,"code":1074,"language":659},[657],"LOGIN (0:00)\n├─ access_token = 15 minutes\n├─ refresh_token = 7 days\n├─ User active\n│\n4:50 (access token expires)\n├─ Auto-refresh triggers\n├─ New access_token issued\n├─ Session continues\n│\nDay 3 (refresh token expiring soon)\n├─ Backgrnd refresh extends refresh_token\n├─ User unaware of renewal\n│\nDay 7 (refresh token expires)\n├─ User returns to app\n├─ refresh_token no longer valid\n├─ Request returns 401\n├─ Browser redirects to \u002Flogin\n├─ User must re-enter credentials\n└─ New 7-day session starts\n",[344,1076,1074],{"__ignoreMap":394},[318,1078],{},[321,1080,1082],{"id":1081},"error-scenarios-recovery","Error Scenarios & Recovery",[367,1084,1086],{"id":1085},"scenario-1-access-token-expired-refresh-valid","Scenario 1: Access Token Expired, Refresh Valid",[389,1088,1092],{"className":1089,"code":1090,"language":1091,"meta":394,"style":394},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F Frontend attempt\nGET \u002Fapi\u002Fbookings (with expired access_token)\n\n\u002F\u002F Server response\n401 Unauthorized: \"Token expired\"\n\n\u002F\u002F Frontend action\nPOST \u002Fapi\u002Fauth\u002Frefresh (with valid refresh_token)\n\n\u002F\u002F Server returns\n200 OK with new access_token\n\n\u002F\u002F Frontend retry\nGET \u002Fapi\u002Fbookings (with new access_token)\n\n\u002F\u002F Success\n200 OK: Bookings returned\n","javascript",[344,1093,1094,1099,1104,1110,1115,1120,1124,1129,1134,1139,1145,1151,1156,1162,1168,1173,1179],{"__ignoreMap":394},[398,1095,1096],{"class":400,"line":401},[398,1097,1098],{},"\u002F\u002F Frontend attempt\n",[398,1100,1101],{"class":400,"line":408},[398,1102,1103],{},"GET \u002Fapi\u002Fbookings (with expired access_token)\n",[398,1105,1106],{"class":400,"line":436},[398,1107,1109],{"emptyLinePlaceholder":1108},true,"\n",[398,1111,1112],{"class":400,"line":457},[398,1113,1114],{},"\u002F\u002F Server response\n",[398,1116,1117],{"class":400,"line":478},[398,1118,1119],{},"401 Unauthorized: \"Token expired\"\n",[398,1121,1122],{"class":400,"line":499},[398,1123,1109],{"emptyLinePlaceholder":1108},[398,1125,1126],{"class":400,"line":517},[398,1127,1128],{},"\u002F\u002F Frontend action\n",[398,1130,1131],{"class":400,"line":532},[398,1132,1133],{},"POST \u002Fapi\u002Fauth\u002Frefresh (with valid refresh_token)\n",[398,1135,1137],{"class":400,"line":1136},9,[398,1138,1109],{"emptyLinePlaceholder":1108},[398,1140,1142],{"class":400,"line":1141},10,[398,1143,1144],{},"\u002F\u002F Server returns\n",[398,1146,1148],{"class":400,"line":1147},11,[398,1149,1150],{},"200 OK with new access_token\n",[398,1152,1154],{"class":400,"line":1153},12,[398,1155,1109],{"emptyLinePlaceholder":1108},[398,1157,1159],{"class":400,"line":1158},13,[398,1160,1161],{},"\u002F\u002F Frontend retry\n",[398,1163,1165],{"class":400,"line":1164},14,[398,1166,1167],{},"GET \u002Fapi\u002Fbookings (with new access_token)\n",[398,1169,1171],{"class":400,"line":1170},15,[398,1172,1109],{"emptyLinePlaceholder":1108},[398,1174,1176],{"class":400,"line":1175},16,[398,1177,1178],{},"\u002F\u002F Success\n",[398,1180,1182],{"class":400,"line":1181},17,[398,1183,1184],{},"200 OK: Bookings returned\n",[367,1186,1188],{"id":1187},"scenario-2-both-tokens-expired-or-invalid","Scenario 2: Both Tokens Expired or Invalid",[389,1190,1192],{"className":1089,"code":1191,"language":1091,"meta":394,"style":394},"\u002F\u002F User hasn't used app for 8 days\n\u002F\u002F Both access_token AND refresh_token expired\n\nGET \u002Fapi\u002Fbookings (with expired access_token)\n\n\u002F\u002F Server response\n401 Unauthorized: Session expired\n\n\u002F\u002F Frontend action (required)\nRedirect to \u002Flogin\n\n\u002F\u002F User must re-enter credentials\nPOST \u002Fapi\u002Fauth\u002Flogin\n",[344,1193,1194,1199,1204,1208,1212,1216,1220,1225,1229,1234,1239,1243,1248],{"__ignoreMap":394},[398,1195,1196],{"class":400,"line":401},[398,1197,1198],{},"\u002F\u002F User hasn't used app for 8 days\n",[398,1200,1201],{"class":400,"line":408},[398,1202,1203],{},"\u002F\u002F Both access_token AND refresh_token expired\n",[398,1205,1206],{"class":400,"line":436},[398,1207,1109],{"emptyLinePlaceholder":1108},[398,1209,1210],{"class":400,"line":457},[398,1211,1103],{},[398,1213,1214],{"class":400,"line":478},[398,1215,1109],{"emptyLinePlaceholder":1108},[398,1217,1218],{"class":400,"line":499},[398,1219,1114],{},[398,1221,1222],{"class":400,"line":517},[398,1223,1224],{},"401 Unauthorized: Session expired\n",[398,1226,1227],{"class":400,"line":532},[398,1228,1109],{"emptyLinePlaceholder":1108},[398,1230,1231],{"class":400,"line":1136},[398,1232,1233],{},"\u002F\u002F Frontend action (required)\n",[398,1235,1236],{"class":400,"line":1141},[398,1237,1238],{},"Redirect to \u002Flogin\n",[398,1240,1241],{"class":400,"line":1147},[398,1242,1109],{"emptyLinePlaceholder":1108},[398,1244,1245],{"class":400,"line":1153},[398,1246,1247],{},"\u002F\u002F User must re-enter credentials\n",[398,1249,1250],{"class":400,"line":1158},[398,1251,1252],{},"POST \u002Fapi\u002Fauth\u002Flogin\n",[367,1254,1256],{"id":1255},"scenario-3-no-token-present","Scenario 3: No Token Present",[309,1258,1259,1260,1262],{},"If no ",[344,1261,864],{}," header is present, the request will fail:",[389,1264,1266],{"className":683,"code":1265,"language":685,"meta":394,"style":394},"curl -X GET https:\u002F\u002Fapi.booki.app\u002Fapi\u002Fbookings \\\n  -H \"Authorization: Bearer eyJhbGc...\"\n",[344,1267,1268,1281],{"__ignoreMap":394},[398,1269,1270,1272,1274,1276,1279],{"class":400,"line":401},[398,1271,693],{"class":692},[398,1273,696],{"class":427},[398,1275,879],{"class":427},[398,1277,1278],{"class":427}," https:\u002F\u002Fapi.booki.app\u002Fapi\u002Fbookings",[398,1280,706],{"class":705},[398,1282,1283,1285,1287,1289],{"class":400,"line":408},[398,1284,711],{"class":427},[398,1286,424],{"class":404},[398,1288,893],{"class":427},[398,1290,820],{"class":404},[309,1292,1293],{},[313,1294,1295],{},"On token expiration:",[389,1297,1299],{"className":683,"code":1298,"language":685,"meta":394,"style":394},"# Frontend detects 401 response\nPOST \u002Fapi\u002Fauth\u002Frefresh \\\n  -H \"Authorization: Bearer REFRESH_TOKEN\"\n\n# Get new access_token from response\n# Use for next request\n",[344,1300,1301,1307,1317,1328,1332,1337],{"__ignoreMap":394},[398,1302,1303],{"class":400,"line":401},[398,1304,1306],{"class":1305},"sHwdD","# Frontend detects 401 response\n",[398,1308,1309,1312,1315],{"class":400,"line":408},[398,1310,1311],{"class":692},"POST",[398,1313,1314],{"class":427}," \u002Fapi\u002Fauth\u002Frefresh",[398,1316,706],{"class":705},[398,1318,1319,1321,1323,1326],{"class":400,"line":436},[398,1320,711],{"class":427},[398,1322,424],{"class":404},[398,1324,1325],{"class":427},"Authorization: Bearer REFRESH_TOKEN",[398,1327,820],{"class":404},[398,1329,1330],{"class":400,"line":457},[398,1331,1109],{"emptyLinePlaceholder":1108},[398,1333,1334],{"class":400,"line":478},[398,1335,1336],{"class":1305},"# Get new access_token from response\n",[398,1338,1339],{"class":400,"line":499},[398,1340,1341],{"class":1305},"# Use for next request\n",[318,1343],{},[321,1345,1347],{"id":1346},"security-best-practices","Security Best Practices",[367,1349,1351],{"id":1350},"do","✅ DO",[831,1353,1354,1357,1366,1369,1372,1375],{},[834,1355,1356],{},"✅ Use HTTPS always (never HTTP)",[834,1358,1359,1360,1362,1363,910],{},"✅ Send ",[344,1361,769],{}," via ",[344,1364,1365],{},"Authorization: Bearer",[834,1367,1368],{},"✅ Implement token refresh before expiry",[834,1370,1371],{},"✅ Blacklist tokens on logout (JTI revocation)",[834,1373,1374],{},"✅ Validate tokens server-side",[834,1376,1377],{},"✅ Log failed auth attempts",[367,1379,1381],{"id":1380},"dont","❌ DON'T",[831,1383,1384,1387,1390,1393,1396,1399],{},[834,1385,1386],{},"❌ Store tokens in localStorage (XSS vulnerable)",[834,1388,1389],{},"❌ Share tokens in URLs or query params",[834,1391,1392],{},"❌ Log tokens to console in production",[834,1394,1395],{},"❌ Send tokens over HTTP (unencrypted)",[834,1397,1398],{},"❌ Trust expired tokens",[834,1400,1401],{},"❌ Skip HTTPS validation",[318,1403],{},[321,1405,1407],{"id":1406},"logout-flow","Logout Flow",[367,1409,1411,1412,1415],{"id":1410},"_1-delete-apiauthlogout-invalidate-session","1. DELETE ",[344,1413,1414],{},"\u002Fapi\u002Fauth\u002Flogout"," — Invalidate Session",[309,1417,1418],{},[313,1419,680],{},[389,1421,1423],{"className":683,"code":1422,"language":685,"meta":394,"style":394},"curl -X DELETE https:\u002F\u002Fapi.booki.app\u002Fapi\u002Fauth\u002Flogout \\\n  -H \"Authorization: Bearer eyJhbGc...\"\n",[344,1424,1425,1439],{"__ignoreMap":394},[398,1426,1427,1429,1431,1434,1437],{"class":400,"line":401},[398,1428,693],{"class":692},[398,1430,696],{"class":427},[398,1432,1433],{"class":427}," DELETE",[398,1435,1436],{"class":427}," https:\u002F\u002Fapi.booki.app\u002Fapi\u002Fauth\u002Flogout",[398,1438,706],{"class":705},[398,1440,1441,1443,1445,1447],{"class":400,"line":408},[398,1442,711],{"class":427},[398,1444,424],{"class":404},[398,1446,893],{"class":427},[398,1448,820],{"class":404},[309,1450,1451],{},[313,1452,753],{},[389,1454,1456],{"className":391,"code":1455,"language":393,"meta":394,"style":394},"{\n  \"message\": \"Logged out successfully.\"\n}\n",[344,1457,1458,1462,1480],{"__ignoreMap":394},[398,1459,1460],{"class":400,"line":401},[398,1461,405],{"class":404},[398,1463,1464,1466,1469,1471,1473,1475,1478],{"class":400,"line":408},[398,1465,411],{"class":404},[398,1467,1468],{"class":414},"message",[398,1470,418],{"class":404},[398,1472,421],{"class":404},[398,1474,424],{"class":404},[398,1476,1477],{"class":427},"Logged out successfully.",[398,1479,820],{"class":404},[398,1481,1482],{"class":400,"line":436},[398,1483,535],{"class":404},[309,1485,1486],{},[313,1487,829],{},[831,1489,1490,1493,1496],{},[834,1491,1492],{},"✅ Access token JTI blacklisted in Redis",[834,1494,1495],{},"✅ All future requests with this token return 401",[834,1497,1498],{},"✅ Session ended",[318,1500],{},[321,1502,1504],{"id":1503},"owner-registration-multi-step-with-tokens","Owner Registration (Multi-Step) with Tokens",[309,1506,1507],{},"Owner registration is different — uses OTP flow:",[367,1509,1511],{"id":1510},"step-1-request-otp","Step 1: Request OTP",[389,1513,1515],{"className":683,"code":1514,"language":685,"meta":394,"style":394},"POST \u002Fapi\u002Fauth\u002Fregister\u002Fowner\u002Fotp\n{\n  \"email\": \"jane@example.com\"\n}\n\n# Response\n{ \"message\": \"Owner email OTP sent successfully. Kindly check your email for the OTP.\" }\n",[344,1516,1517,1524,1528,1543,1547,1551,1556],{"__ignoreMap":394},[398,1518,1519,1521],{"class":400,"line":401},[398,1520,1311],{"class":692},[398,1522,1523],{"class":427}," \u002Fapi\u002Fauth\u002Fregister\u002Fowner\u002Fotp\n",[398,1525,1526],{"class":400,"line":408},[398,1527,405],{"class":404},[398,1529,1530,1533,1536,1538,1541],{"class":400,"line":436},[398,1531,1532],{"class":692},"  \"email\"",[398,1534,421],{"class":1535},"s2Zo4",[398,1537,424],{"class":404},[398,1539,1540],{"class":427},"jane@example.com",[398,1542,820],{"class":404},[398,1544,1545],{"class":400,"line":457},[398,1546,535],{"class":404},[398,1548,1549],{"class":400,"line":478},[398,1550,1109],{"emptyLinePlaceholder":1108},[398,1552,1553],{"class":400,"line":499},[398,1554,1555],{"class":1305},"# Response\n",[398,1557,1558,1561,1564,1566,1568,1571,1573],{"class":400,"line":517},[398,1559,1560],{"class":404},"{",[398,1562,1563],{"class":692}," \"message\"",[398,1565,421],{"class":1535},[398,1567,424],{"class":404},[398,1569,1570],{"class":427},"Owner email OTP sent successfully. Kindly check your email for the OTP.",[398,1572,418],{"class":404},[398,1574,1575],{"class":427}," }\n",[367,1577,1579],{"id":1578},"step-2-verify-otp","Step 2: Verify OTP",[389,1581,1583],{"className":683,"code":1582,"language":685,"meta":394,"style":394},"POST \u002Fapi\u002Fauth\u002Fregister\u002Fowner\u002Fotp\u002Fverify\n{\n  \"otp\": \"123456\"\n}\n\n# Response\n{ \"message\": \"OTP verified successfully.\", \"valid\": true }\n",[344,1584,1585,1592,1596,1610,1614,1618,1622],{"__ignoreMap":394},[398,1586,1587,1589],{"class":400,"line":401},[398,1588,1311],{"class":692},[398,1590,1591],{"class":427}," \u002Fapi\u002Fauth\u002Fregister\u002Fowner\u002Fotp\u002Fverify\n",[398,1593,1594],{"class":400,"line":408},[398,1595,405],{"class":404},[398,1597,1598,1601,1603,1605,1608],{"class":400,"line":436},[398,1599,1600],{"class":692},"  \"otp\"",[398,1602,421],{"class":1535},[398,1604,424],{"class":404},[398,1606,1607],{"class":427},"123456",[398,1609,820],{"class":404},[398,1611,1612],{"class":400,"line":457},[398,1613,535],{"class":404},[398,1615,1616],{"class":400,"line":478},[398,1617,1109],{"emptyLinePlaceholder":1108},[398,1619,1620],{"class":400,"line":499},[398,1621,1555],{"class":1305},[398,1623,1624,1626,1628,1630,1632,1635,1637,1640,1642,1645,1647,1649,1652],{"class":400,"line":517},[398,1625,1560],{"class":404},[398,1627,1563],{"class":692},[398,1629,421],{"class":1535},[398,1631,424],{"class":404},[398,1633,1634],{"class":427},"OTP verified successfully.",[398,1636,418],{"class":404},[398,1638,1639],{"class":427},",",[398,1641,424],{"class":404},[398,1643,1644],{"class":427},"valid",[398,1646,418],{"class":404},[398,1648,421],{"class":427},[398,1650,1651],{"class":404}," true",[398,1653,1575],{"class":427},[367,1655,1657],{"id":1656},"step-3-create-account","Step 3: Create Account",[389,1659,1661],{"className":683,"code":1660,"language":685,"meta":394,"style":394},"POST \u002Fapi\u002Fauth\u002Fregister\u002Fowner\n{\n  \"otp\": \"123456\",\n  \"password\": \"SecureP@ss123\",\n  \"ownerDetails\": {...},\n  \"businessDetails\": {...}\n}\n\n# Response (201 Created)\n{ \"message\": \"Business owner added successfully.\" }\n",[344,1662,1663,1670,1674,1688,1704,1714,1724,1728,1732,1737],{"__ignoreMap":394},[398,1664,1665,1667],{"class":400,"line":401},[398,1666,1311],{"class":692},[398,1668,1669],{"class":427}," \u002Fapi\u002Fauth\u002Fregister\u002Fowner\n",[398,1671,1672],{"class":400,"line":408},[398,1673,405],{"class":404},[398,1675,1676,1678,1680,1682,1684,1686],{"class":400,"line":436},[398,1677,1600],{"class":692},[398,1679,421],{"class":1535},[398,1681,424],{"class":404},[398,1683,1607],{"class":427},[398,1685,418],{"class":404},[398,1687,433],{"class":427},[398,1689,1690,1693,1695,1697,1700,1702],{"class":400,"line":457},[398,1691,1692],{"class":692},"  \"password\"",[398,1694,421],{"class":1535},[398,1696,424],{"class":404},[398,1698,1699],{"class":427},"SecureP@ss123",[398,1701,418],{"class":404},[398,1703,433],{"class":427},[398,1705,1706,1709,1711],{"class":400,"line":478},[398,1707,1708],{"class":692},"  \"ownerDetails\"",[398,1710,421],{"class":1535},[398,1712,1713],{"class":427}," {...},\n",[398,1715,1716,1719,1721],{"class":400,"line":499},[398,1717,1718],{"class":692},"  \"businessDetails\"",[398,1720,421],{"class":1535},[398,1722,1723],{"class":427}," {...}\n",[398,1725,1726],{"class":400,"line":517},[398,1727,535],{"class":404},[398,1729,1730],{"class":400,"line":532},[398,1731,1109],{"emptyLinePlaceholder":1108},[398,1733,1734],{"class":400,"line":1136},[398,1735,1736],{"class":1305},"# Response (201 Created)\n",[398,1738,1739,1741,1743,1745,1747,1750,1752],{"class":400,"line":1141},[398,1740,1560],{"class":404},[398,1742,1563],{"class":692},[398,1744,421],{"class":1535},[398,1746,424],{"class":404},[398,1748,1749],{"class":427},"Business owner added successfully.",[398,1751,418],{"class":404},[398,1753,1575],{"class":427},[318,1755],{},[321,1757,1759],{"id":1758},"jwt-payload-structure","JWT Payload Structure",[309,1761,1762],{},[313,1763,1764],{},"Decoded access_token:",[389,1766,1768],{"className":391,"code":1767,"language":393,"meta":394,"style":394},"{\n  \"iss\": \"booki-api\",\n  \"sub\": \"507f1f77bcf86cd799439011\",\n  \"userId\": \"507f1f77bcf86cd799439011\",\n  \"organizationId\": \"507f191e810c19729de860ea\",\n  \"userType\": \"OWNER\",\n  \"email\": \"jane@example.com\",\n  \"iat\": 1712332080,\n  \"exp\": 1712332980,\n  \"aud\": \"booki-customers\"\n}\n",[344,1769,1770,1774,1794,1813,1832,1850,1870,1889,1903,1918,1936],{"__ignoreMap":394},[398,1771,1772],{"class":400,"line":401},[398,1773,405],{"class":404},[398,1775,1776,1778,1781,1783,1785,1787,1790,1792],{"class":400,"line":408},[398,1777,411],{"class":404},[398,1779,1780],{"class":414},"iss",[398,1782,418],{"class":404},[398,1784,421],{"class":404},[398,1786,424],{"class":404},[398,1788,1789],{"class":427},"booki-api",[398,1791,418],{"class":404},[398,1793,433],{"class":404},[398,1795,1796,1798,1801,1803,1805,1807,1809,1811],{"class":400,"line":436},[398,1797,411],{"class":404},[398,1799,1800],{"class":414},"sub",[398,1802,418],{"class":404},[398,1804,421],{"class":404},[398,1806,424],{"class":404},[398,1808,428],{"class":427},[398,1810,418],{"class":404},[398,1812,433],{"class":404},[398,1814,1815,1817,1820,1822,1824,1826,1828,1830],{"class":400,"line":457},[398,1816,411],{"class":404},[398,1818,1819],{"class":414},"userId",[398,1821,418],{"class":404},[398,1823,421],{"class":404},[398,1825,424],{"class":404},[398,1827,428],{"class":427},[398,1829,418],{"class":404},[398,1831,433],{"class":404},[398,1833,1834,1836,1838,1840,1842,1844,1846,1848],{"class":400,"line":478},[398,1835,411],{"class":404},[398,1837,441],{"class":414},[398,1839,418],{"class":404},[398,1841,421],{"class":404},[398,1843,424],{"class":404},[398,1845,450],{"class":427},[398,1847,418],{"class":404},[398,1849,433],{"class":404},[398,1851,1852,1854,1857,1859,1861,1863,1866,1868],{"class":400,"line":499},[398,1853,411],{"class":404},[398,1855,1856],{"class":414},"userType",[398,1858,418],{"class":404},[398,1860,421],{"class":404},[398,1862,424],{"class":404},[398,1864,1865],{"class":427},"OWNER",[398,1867,418],{"class":404},[398,1869,433],{"class":404},[398,1871,1872,1874,1877,1879,1881,1883,1885,1887],{"class":400,"line":517},[398,1873,411],{"class":404},[398,1875,1876],{"class":414},"email",[398,1878,418],{"class":404},[398,1880,421],{"class":404},[398,1882,424],{"class":404},[398,1884,1540],{"class":427},[398,1886,418],{"class":404},[398,1888,433],{"class":404},[398,1890,1891,1893,1895,1897,1899,1901],{"class":400,"line":532},[398,1892,411],{"class":404},[398,1894,504],{"class":414},[398,1896,418],{"class":404},[398,1898,421],{"class":404},[398,1900,512],{"class":511},[398,1902,433],{"class":404},[398,1904,1905,1907,1909,1911,1913,1916],{"class":400,"line":1136},[398,1906,411],{"class":404},[398,1908,522],{"class":414},[398,1910,418],{"class":404},[398,1912,421],{"class":404},[398,1914,1915],{"class":511}," 1712332980",[398,1917,433],{"class":404},[398,1919,1920,1922,1925,1927,1929,1931,1934],{"class":400,"line":1141},[398,1921,411],{"class":404},[398,1923,1924],{"class":414},"aud",[398,1926,418],{"class":404},[398,1928,421],{"class":404},[398,1930,424],{"class":404},[398,1932,1933],{"class":427},"booki-customers",[398,1935,820],{"class":404},[398,1937,1938],{"class":400,"line":1147},[398,1939,535],{"class":404},[309,1941,1942],{},[313,1943,1944],{},"Field meanings:",[831,1946,1947,1952,1960,1965,1970,1975],{},[834,1948,1949,1951],{},[344,1950,1780],{}," (issuer): API that created token",[834,1953,1954,1956,1957,1959],{},[344,1955,1800],{}," \u002F ",[344,1958,1819],{},": Who this token belongs to",[834,1961,1962,1964],{},[344,1963,441],{},": Tenant scope",[834,1966,1967,1969],{},[344,1968,1856],{},": Role (OWNER, CUSTOMER, etc.)",[834,1971,1972,1974],{},[344,1973,504],{}," (issued at): When token was created",[834,1976,1977,1979],{},[344,1978,522],{}," (expiration): When token becomes invalid (Unix timestamp)",[318,1981],{},[321,1983,1985],{"id":1984},"summary","Summary",[1987,1988,1989,2005],"table",{},[1990,1991,1992],"thead",{},[1993,1994,1995,1999,2002],"tr",{},[1996,1997,1998],"th",{},"Concept",[1996,2000,2001],{},"Value",[1996,2003,2004],{},"Notes",[2006,2007,2008,2020,2031,2042,2053,2063],"tbody",{},[1993,2009,2010,2014,2017],{},[2011,2012,2013],"td",{},"Access Token Lifetime",[2011,2015,2016],{},"15 minutes",[2011,2018,2019],{},"Auto-refresh before expiry",[1993,2021,2022,2025,2028],{},[2011,2023,2024],{},"Refresh Token Lifetime",[2011,2026,2027],{},"7 days",[2011,2029,2030],{},"After expiry, user must re-login",[1993,2032,2033,2036,2039],{},[2011,2034,2035],{},"Cookie Type",[2011,2037,2038],{},"HttpOnly",[2011,2040,2041],{},"Not accessible to JavaScript",[1993,2043,2044,2047,2050],{},[2011,2045,2046],{},"Transport",[2011,2048,2049],{},"HTTPS only",[2011,2051,2052],{},"Encrypts tokens in transit",[1993,2054,2055,2057,2060],{},[2011,2056,101],{},[2011,2058,2059],{},"JWT signature + expiry",[2011,2061,2062],{},"Server-side only",[1993,2064,2065,2068,2071],{},[2011,2066,2067],{},"Session Database",[2011,2069,2070],{},"None",[2011,2072,2073],{},"Stateless (JWT)",[309,2075,2076],{},[313,2077,2078],{},"Authentication Flow:",[902,2080,2081,2087,2092,2098,2104],{},[834,2082,2083,2086],{},[313,2084,2085],{},"Login"," — POST \u002Fapi\u002Fauth\u002Flogin → Get tokens in cookies",[834,2088,2089,2091],{},[313,2090,851],{}," — Cookies auto-included → API validates JWT",[834,2093,2094,2097],{},[313,2095,2096],{},"Before Expiry"," — POST \u002Fapi\u002Fauth\u002Frefresh → Get new access token",[834,2099,2100,2103],{},[313,2101,2102],{},"After 7 Days"," — Refresh token expires → User re-logs in",[834,2105,2106,2109],{},[313,2107,2108],{},"Logout"," — GET \u002Fapi\u002Fauth\u002Flogout → Cookies cleared",[309,2111,2112],{},[313,2113,2114],{},"It just works:",[831,2116,2117,2120,2123,2126],{},[834,2118,2119],{},"🍪 Cookies handled automatically by browser",[834,2121,2122],{},"🔄 Token refresh happens in background",[834,2124,2125],{},"🔒 No tokens exposed to JavaScript",[834,2127,2128],{},"📱 Mobile apps manually manage tokens (Authorization header)",[318,2130],{},[321,2132,2134],{"id":2133},"related","Related",[831,2136,2137,2143],{},[834,2138,2139],{},[2140,2141,140],"a",{"href":2142},"..\u002Fapi\u002Fauth",[834,2144,2145],{},[2140,2146,2148],{"href":2147},".\u002Fguides-errors","Common Error Responses",[2150,2151,2152],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}",{"title":394,"searchDepth":401,"depth":408,"links":2154},[2155,2156,2160,2161,2165,2168,2173,2174,2179,2183,2187,2192,2193,2194],{"id":323,"depth":408,"text":324},{"id":364,"depth":408,"text":365,"children":2157},[2158,2159],{"id":369,"depth":436,"text":370},{"id":538,"depth":436,"text":539},{"id":652,"depth":408,"text":653},{"id":666,"depth":408,"text":667,"children":2162},[2163],{"id":670,"depth":436,"text":2164},"1. POST \u002Fapi\u002Fauth\u002Flogin — Initial Login",{"id":850,"depth":408,"text":851,"children":2166},[2167],{"id":854,"depth":436,"text":855},{"id":927,"depth":408,"text":928,"children":2169},[2170,2171],{"id":934,"depth":436,"text":935},{"id":944,"depth":436,"text":2172},"2. POST \u002Fapi\u002Fauth\u002Frefresh — Get New Access Token",{"id":1069,"depth":408,"text":1070},{"id":1081,"depth":408,"text":1082,"children":2175},[2176,2177,2178],{"id":1085,"depth":436,"text":1086},{"id":1187,"depth":436,"text":1188},{"id":1255,"depth":436,"text":1256},{"id":1346,"depth":408,"text":1347,"children":2180},[2181,2182],{"id":1350,"depth":436,"text":1351},{"id":1380,"depth":436,"text":1381},{"id":1406,"depth":408,"text":1407,"children":2184},[2185],{"id":1410,"depth":436,"text":2186},"1. DELETE \u002Fapi\u002Fauth\u002Flogout — Invalidate Session",{"id":1503,"depth":408,"text":1504,"children":2188},[2189,2190,2191],{"id":1510,"depth":436,"text":1511},{"id":1578,"depth":436,"text":1579},{"id":1656,"depth":436,"text":1657},{"id":1758,"depth":408,"text":1759},{"id":1984,"depth":408,"text":1985},{"id":2133,"depth":408,"text":2134},"Understanding JWT tokens, refresh cycles, cookie management, and secure authentication patterns.","md",null,{},{"icon":266},{"title":263,"description":2195},"jpMRsAEvHZj46Xq7FedR7Cire9Q8MmfYqZ9_ZjLWnpE",[2203,2205],{"title":254,"path":255,"stem":256,"description":2204,"icon":167,"children":-1},"End-to-end flow for how a customer discovers, books, pays for, and completes a service on the Booki platform.",{"title":268,"path":269,"stem":270,"description":2206,"icon":177,"children":-1},"Invite-based branch creation flow, branch status lifecycle, and API endpoints for managing multi-branch organizations in booki-api.",1777787842937]