[{"data":1,"prerenderedAt":4199},["ShallowReactive",2],{"navigation_docs":3,"-modules-identity-auth-client-mode":587,"-modules-identity-auth-client-mode-surround":4194},[4,50,155,441,504],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":49},"Get Started","i-lucide-rocket","\u002Fget-started","1.get-started",[10,15,20,25,30,35,40,45],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fget-started\u002Fintroduction","1.get-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fget-started\u002Finstallation","1.get-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Project structure","\u002Fget-started\u002Fproject-structure","1.get-started\u002F3.project-structure","i-lucide-folder-tree",{"title":26,"path":27,"stem":28,"icon":29},"Configuration","\u002Fget-started\u002Fconfiguration","1.get-started\u002F4.configuration","i-lucide-settings",{"title":31,"path":32,"stem":33,"icon":34},"Authentication","\u002Fget-started\u002Fauthentication","1.get-started\u002F5.authentication","i-lucide-lock",{"title":36,"path":37,"stem":38,"icon":39},"Adding modules","\u002Fget-started\u002Fadding-modules","1.get-started\u002F6.adding-modules","i-lucide-puzzle",{"title":41,"path":42,"stem":43,"icon":44},"Database","\u002Fget-started\u002Fdatabase","1.get-started\u002F7.database","i-lucide-database",{"title":46,"path":47,"stem":48,"icon":6},"Deployment","\u002Fget-started\u002Fdeployment","1.get-started\u002F8.deployment",false,{"title":51,"icon":52,"path":53,"stem":54,"children":55,"page":49},"Guide","i-lucide-book-open","\u002Fguide","2.guide",[56,90,115,125],{"title":57,"icon":49,"path":58,"stem":59,"children":60,"page":49},"Concepts","\u002Fguide\u002Fconcepts","2.guide\u002F1.concepts",[61,66,71,76,80,85],{"title":62,"path":63,"stem":64,"icon":65},"Architecture","\u002Fguide\u002Fconcepts\u002Farchitecture","2.guide\u002F1.concepts\u002F1.architecture","i-lucide-blocks",{"title":67,"path":68,"stem":69,"icon":70},"Access control","\u002Fguide\u002Fconcepts\u002Fauth-and-scopes","2.guide\u002F1.concepts\u002F2.auth-and-scopes","i-lucide-shield-check",{"title":72,"path":73,"stem":74,"icon":75},"Extension points","\u002Fguide\u002Fconcepts\u002Fextension-points","2.guide\u002F1.concepts\u002F3.extension-points","i-lucide-plug",{"title":77,"path":78,"stem":79,"icon":44},"Database extensions","\u002Fguide\u002Fconcepts\u002Fdatabase-extensions","2.guide\u002F1.concepts\u002F4.database-extensions",{"title":81,"path":82,"stem":83,"icon":84},"Identity","\u002Fguide\u002Fconcepts\u002Fidentity","2.guide\u002F1.concepts\u002F5.identity","i-lucide-fingerprint",{"title":86,"path":87,"stem":88,"icon":89},"Glossary","\u002Fguide\u002Fconcepts\u002Fglossary","2.guide\u002F1.concepts\u002F6.glossary","i-lucide-book-a",{"title":91,"icon":49,"path":92,"stem":93,"children":94,"page":49},"UX patterns","\u002Fguide\u002Fux-patterns","2.guide\u002F2.ux-patterns",[95,100,105,110],{"title":96,"path":97,"stem":98,"icon":99},"Layouts and navigation","\u002Fguide\u002Fux-patterns\u002Flayouts-and-navigation","2.guide\u002F2.ux-patterns\u002F1.layouts-and-navigation","i-lucide-layout-template",{"title":101,"path":102,"stem":103,"icon":104},"Pages","\u002Fguide\u002Fux-patterns\u002Fpages","2.guide\u002F2.ux-patterns\u002F2.pages","i-lucide-table",{"title":106,"path":107,"stem":108,"icon":109},"Forms and actions","\u002Fguide\u002Fux-patterns\u002Fforms-and-actions","2.guide\u002F2.ux-patterns\u002F3.forms-and-actions","i-lucide-square-pen",{"title":111,"path":112,"stem":113,"icon":114},"Text and formatting","\u002Fguide\u002Fux-patterns\u002Ftext-and-formatting","2.guide\u002F2.ux-patterns\u002F4.text-and-formatting","i-lucide-type",{"title":116,"icon":49,"path":117,"stem":118,"children":119,"page":49},"Best practices","\u002Fguide\u002Fbest-practices","2.guide\u002F3.best-practices",[120],{"title":121,"path":122,"stem":123,"icon":124},"HTTP routes","\u002Fguide\u002Fbest-practices\u002Fhttp-routes","2.guide\u002F3.best-practices\u002F1.http-routes","i-lucide-route",{"title":126,"icon":49,"path":127,"stem":128,"children":129,"page":49},"Going further","\u002Fguide\u002Fgoing-further","2.guide\u002F4.going-further",[130,135,140,145,150],{"title":131,"path":132,"stem":133,"icon":134},"Use your own OAuth server","\u002Fguide\u002Fgoing-further\u002Fown-oauth-server","2.guide\u002F4.going-further\u002F1.own-oauth-server","i-lucide-key-round",{"title":136,"path":137,"stem":138,"icon":139},"Create an OAuth application","\u002Fguide\u002Fgoing-further\u002Foauth-application","2.guide\u002F4.going-further\u002F2.oauth-application","i-lucide-app-window",{"title":141,"path":142,"stem":143,"icon":144},"Signing keys","\u002Fguide\u002Fgoing-further\u002Fsigning-keys","2.guide\u002F4.going-further\u002F3.signing-keys","i-lucide-key-square",{"title":146,"path":147,"stem":148,"icon":149},"Stripe setup","\u002Fguide\u002Fgoing-further\u002Fstripe-setup","2.guide\u002F4.going-further\u002F4.stripe-setup","i-lucide-credit-card",{"title":151,"path":152,"stem":153,"icon":154},"Migrate to the permission model","\u002Fguide\u002Fgoing-further\u002Fmigrate-access-control","2.guide\u002F4.going-further\u002F5.migrate-access-control","i-lucide-arrow-right-left",{"title":156,"icon":157,"path":158,"stem":159,"children":160},"Modules","i-lucide-boxes","\u002Fmodules","3.modules",[161,163,244,273,320,375],{"title":156,"path":158,"stem":162},"3.modules\u002Findex",{"title":81,"icon":49,"path":164,"stem":165,"children":166,"page":49},"\u002Fmodules\u002Fidentity","3.modules\u002F1.identity",[167,190,194,198,220,224,240],{"title":168,"path":169,"stem":170,"children":171},"Auth","\u002Fmodules\u002Fidentity\u002Fauth","3.modules\u002F1.identity\u002F1.auth\u002Findex",[172,174,178,182,186],{"title":173,"path":169,"stem":170},"Overview",{"title":175,"path":176,"stem":177},"Server API","\u002Fmodules\u002Fidentity\u002Fauth\u002Fserver","3.modules\u002F1.identity\u002F1.auth\u002F2.server",{"title":179,"path":180,"stem":181},"Reference","\u002Fmodules\u002Fidentity\u002Fauth\u002Freference","3.modules\u002F1.identity\u002F1.auth\u002F3.reference",{"title":183,"path":184,"stem":185},"Client mode","\u002Fmodules\u002Fidentity\u002Fauth\u002Fclient-mode","3.modules\u002F1.identity\u002F1.auth\u002F4.client-mode",{"title":187,"path":188,"stem":189},"OAuth providers","\u002Fmodules\u002Fidentity\u002Fauth\u002Foauth-providers","3.modules\u002F1.identity\u002F1.auth\u002F5.oauth-providers",{"title":191,"path":192,"stem":193},"Users","\u002Fmodules\u002Fidentity\u002Fusers","3.modules\u002F1.identity\u002F2.users",{"title":195,"path":196,"stem":197},"Account","\u002Fmodules\u002Fidentity\u002Faccount","3.modules\u002F1.identity\u002F3.account",{"title":199,"path":200,"stem":201,"children":202},"Authorization","\u002Fmodules\u002Fidentity\u002Fauthorization","3.modules\u002F1.identity\u002F4.authorization\u002Findex",[203,204,208,212,216],{"title":173,"path":200,"stem":201},{"title":205,"path":206,"stem":207},"Roles and requirements","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Froles-and-requirements","3.modules\u002F1.identity\u002F4.authorization\u002F2.roles-and-requirements",{"title":209,"path":210,"stem":211},"Policies","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fpolicies","3.modules\u002F1.identity\u002F4.authorization\u002F3.policies",{"title":213,"path":214,"stem":215},"Client","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fclient","3.modules\u002F1.identity\u002F4.authorization\u002F4.client",{"title":217,"path":218,"stem":219},"Admin","\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fadmin","3.modules\u002F1.identity\u002F4.authorization\u002F5.admin",{"title":221,"path":222,"stem":223},"Preferences","\u002Fmodules\u002Fidentity\u002Fpreferences","3.modules\u002F1.identity\u002F5.preferences",{"title":225,"path":226,"stem":227,"children":228},"OAuth Server","\u002Fmodules\u002Fidentity\u002Foauth-server","3.modules\u002F1.identity\u002F6.oauth-server\u002Findex",[229,230,233,237],{"title":173,"path":226,"stem":227},{"title":175,"path":231,"stem":232},"\u002Fmodules\u002Fidentity\u002Foauth-server\u002Fserver","3.modules\u002F1.identity\u002F6.oauth-server\u002F2.server",{"title":234,"path":235,"stem":236},"Hooks","\u002Fmodules\u002Fidentity\u002Foauth-server\u002Fhooks","3.modules\u002F1.identity\u002F6.oauth-server\u002F3.hooks",{"title":179,"path":238,"stem":239},"\u002Fmodules\u002Fidentity\u002Foauth-server\u002Froutes-and-clients","3.modules\u002F1.identity\u002F6.oauth-server\u002F4.routes-and-clients",{"title":241,"path":242,"stem":243},"OAuth Resource","\u002Fmodules\u002Fidentity\u002Foauth-resource","3.modules\u002F1.identity\u002F8.oauth-resource",{"title":245,"icon":49,"path":246,"stem":247,"children":248,"page":49},"Commerce","\u002Fmodules\u002Fcommerce","3.modules\u002F2.commerce",[249,253,257],{"title":250,"path":251,"stem":252},"Stripe","\u002Fmodules\u002Fcommerce\u002Fstripe","3.modules\u002F2.commerce\u002F1.stripe",{"title":254,"path":255,"stem":256},"Payments","\u002Fmodules\u002Fcommerce\u002Fpayments","3.modules\u002F2.commerce\u002F2.payments",{"title":258,"path":259,"stem":260,"children":261},"Subscriptions","\u002Fmodules\u002Fcommerce\u002Fsubscriptions","3.modules\u002F2.commerce\u002F3.subscriptions\u002Findex",[262,263,266,270],{"title":173,"path":259,"stem":260},{"title":175,"path":264,"stem":265},"\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Fserver","3.modules\u002F2.commerce\u002F3.subscriptions\u002F2.server",{"title":267,"path":268,"stem":269},"App","\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Fapp","3.modules\u002F2.commerce\u002F3.subscriptions\u002F3.app",{"title":179,"path":271,"stem":272},"\u002Fmodules\u002Fcommerce\u002Fsubscriptions\u002Freference","3.modules\u002F2.commerce\u002F3.subscriptions\u002F4.reference",{"title":274,"icon":49,"path":275,"stem":276,"children":277,"page":49},"Features","\u002Fmodules\u002Ffeatures","3.modules\u002F3.features",[278,293,312,316],{"title":279,"path":280,"stem":281,"children":282},"Events","\u002Fmodules\u002Ffeatures\u002Fevents","3.modules\u002F3.features\u002F1.events\u002Findex",[283,284,287,290],{"title":173,"path":280,"stem":281},{"title":175,"path":285,"stem":286},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Fserver","3.modules\u002F3.features\u002F1.events\u002F2.server",{"title":267,"path":288,"stem":289},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Fapp","3.modules\u002F3.features\u002F1.events\u002F3.app",{"title":179,"path":291,"stem":292},"\u002Fmodules\u002Ffeatures\u002Fevents\u002Freference","3.modules\u002F3.features\u002F1.events\u002F4.reference",{"title":294,"path":295,"stem":296,"children":297},"Forms","\u002Fmodules\u002Ffeatures\u002Fforms","3.modules\u002F3.features\u002F2.forms\u002Findex",[298,299,303,306,309],{"title":173,"path":295,"stem":296},{"title":300,"path":301,"stem":302},"Definition","\u002Fmodules\u002Ffeatures\u002Fforms\u002Fdefinition","3.modules\u002F3.features\u002F2.forms\u002F2.definition",{"title":175,"path":304,"stem":305},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Fserver","3.modules\u002F3.features\u002F2.forms\u002F3.server",{"title":267,"path":307,"stem":308},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Fapp","3.modules\u002F3.features\u002F2.forms\u002F4.app",{"title":179,"path":310,"stem":311},"\u002Fmodules\u002Ffeatures\u002Fforms\u002Freference","3.modules\u002F3.features\u002F2.forms\u002F5.reference",{"title":313,"path":314,"stem":315},"Cookie Consent","\u002Fmodules\u002Ffeatures\u002Fcookie-consent","3.modules\u002F3.features\u002F3.cookie-consent",{"title":317,"path":318,"stem":319},"MCP","\u002Fmodules\u002Ffeatures\u002Fmcp","3.modules\u002F3.features\u002F4.mcp",{"title":321,"icon":49,"path":322,"stem":323,"children":324,"page":49},"Interface","\u002Fmodules\u002Finterface","3.modules\u002F4.interface",[325,350,353,357,361],{"title":326,"path":327,"stem":328,"children":329},"UI","\u002Fmodules\u002Finterface\u002Fui","3.modules\u002F4.interface\u002F1.ui\u002Findex",[330,331,335,339,343,347],{"title":173,"path":327,"stem":328},{"title":332,"path":333,"stem":334},"Page components","\u002Fmodules\u002Finterface\u002Fui\u002Fpage-components","3.modules\u002F4.interface\u002F1.ui\u002F2.page-components",{"title":336,"path":337,"stem":338},"App shell","\u002Fmodules\u002Finterface\u002Fui\u002Fapp-shell","3.modules\u002F4.interface\u002F1.ui\u002F3.app-shell",{"title":340,"path":341,"stem":342},"Form inputs","\u002Fmodules\u002Finterface\u002Fui\u002Fform-inputs","3.modules\u002F4.interface\u002F1.ui\u002F4.form-inputs",{"title":344,"path":345,"stem":346},"Composables and helpers","\u002Fmodules\u002Finterface\u002Fui\u002Fcomposables","3.modules\u002F4.interface\u002F1.ui\u002F5.composables",{"title":179,"path":348,"stem":349},"\u002Fmodules\u002Finterface\u002Fui\u002Freference","3.modules\u002F4.interface\u002F1.ui\u002F6.reference",{"title":217,"path":351,"stem":352},"\u002Fmodules\u002Finterface\u002Fadmin","3.modules\u002F4.interface\u002F2.admin",{"title":354,"path":355,"stem":356},"Menu","\u002Fmodules\u002Finterface\u002Fmenu","3.modules\u002F4.interface\u002F3.menu",{"title":358,"path":359,"stem":360},"Widget","\u002Fmodules\u002Finterface\u002Fwidget","3.modules\u002F4.interface\u002F4.widget",{"title":362,"path":363,"stem":364,"children":365},"Mobile","\u002Fmodules\u002Finterface\u002Fmobile","3.modules\u002F4.interface\u002F5.mobile\u002Findex",[366,367,371],{"title":173,"path":363,"stem":364},{"title":368,"path":369,"stem":370},"CLI and devices","\u002Fmodules\u002Finterface\u002Fmobile\u002Fcli-and-devices","3.modules\u002F4.interface\u002F5.mobile\u002F2.cli-and-devices",{"title":372,"path":373,"stem":374},"Splash screen","\u002Fmodules\u002Finterface\u002Fmobile\u002Fsplash-screen","3.modules\u002F4.interface\u002F5.mobile\u002F3.splash-screen",{"title":376,"icon":49,"path":377,"stem":378,"children":379,"page":49},"Platform","\u002Fmodules\u002Fplatform","3.modules\u002F5.platform",[380,402,406,423],{"title":381,"path":382,"stem":383,"children":384},"Module Kit","\u002Fmodules\u002Fplatform\u002Fmodule-kit","3.modules\u002F5.platform\u002F1.module-kit\u002Findex",[385,386,390,394,398],{"title":173,"path":382,"stem":383},{"title":387,"path":388,"stem":389},"Server toolkit","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fserver-toolkit","3.modules\u002F5.platform\u002F1.module-kit\u002F2.server-toolkit",{"title":391,"path":392,"stem":393},"Registries and menus","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fregistries-and-menus","3.modules\u002F5.platform\u002F1.module-kit\u002F3.registries-and-menus",{"title":395,"path":396,"stem":397},"Translations","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fi18n","3.modules\u002F5.platform\u002F1.module-kit\u002F4.i18n",{"title":399,"path":400,"stem":401},"Database helpers","\u002Fmodules\u002Fplatform\u002Fmodule-kit\u002Fdatabase","3.modules\u002F5.platform\u002F1.module-kit\u002F5.database",{"title":403,"path":404,"stem":405},"Notify","\u002Fmodules\u002Fplatform\u002Fnotify","3.modules\u002F5.platform\u002F2.notify",{"title":407,"path":408,"stem":409,"children":410},"Email Templates","\u002Fmodules\u002Fplatform\u002Femail-templates","3.modules\u002F5.platform\u002F3.email-templates\u002Findex",[411,412,416,419],{"title":173,"path":408,"stem":409},{"title":413,"path":414,"stem":415},"Email components","\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fcomponents","3.modules\u002F5.platform\u002F3.email-templates\u002F2.components",{"title":175,"path":417,"stem":418},"\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fserver","3.modules\u002F5.platform\u002F3.email-templates\u002F3.server",{"title":420,"path":421,"stem":422},"Module emails","\u002Fmodules\u002Fplatform\u002Femail-templates\u002Fmodule-emails","3.modules\u002F5.platform\u002F3.email-templates\u002F4.module-emails",{"title":424,"path":425,"stem":426,"children":427},"Base Layer","\u002Fmodules\u002Fplatform\u002Fbase-layer","3.modules\u002F5.platform\u002F4.base-layer\u002Findex",[428,429,433,437],{"title":173,"path":425,"stem":426},{"title":430,"path":431,"stem":432},"Content collections","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Fcontent-collections","3.modules\u002F5.platform\u002F4.base-layer\u002F2.content-collections",{"title":434,"path":435,"stem":436},"Layouts and routing","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Flayouts-and-routing","3.modules\u002F5.platform\u002F4.base-layer\u002F3.layouts-and-routing",{"title":438,"path":439,"stem":440},"Composables and utils","\u002Fmodules\u002Fplatform\u002Fbase-layer\u002Fcomposables-and-utils","3.modules\u002F5.platform\u002F4.base-layer\u002F4.composables-and-utils",{"title":442,"icon":443,"path":444,"stem":445,"children":446,"page":49},"Examples","i-lucide-code-xml","\u002Fexamples","4.examples",[447,466,476],{"title":448,"icon":49,"path":449,"stem":450,"children":451,"page":49},"Starters","\u002Fexamples\u002Fstarters","4.examples\u002F1.starters",[452,456,461],{"title":453,"path":454,"stem":455,"icon":6},"Workspace starter","\u002Fexamples\u002Fstarters\u002Fworkspace","4.examples\u002F1.starters\u002F1.workspace",{"title":457,"path":458,"stem":459,"icon":460},"Mobile starter","\u002Fexamples\u002Fstarters\u002Fmobile","4.examples\u002F1.starters\u002F2.mobile","i-lucide-smartphone",{"title":462,"path":463,"stem":464,"icon":465},"Standalone mobile starter","\u002Fexamples\u002Fstarters\u002Fmobile-standalone","4.examples\u002F1.starters\u002F3.mobile-standalone","i-lucide-tablet-smartphone",{"title":467,"icon":49,"path":468,"stem":469,"children":470,"page":49},"Apps","\u002Fexamples\u002Fapps","4.examples\u002F2.apps",[471],{"title":472,"path":473,"stem":474,"icon":475},"Frigear website app","\u002Fexamples\u002Fapps\u002Ffrigear-nu-website","4.examples\u002F2.apps\u002F1.frigear-nu-website","i-lucide-layout-dashboard",{"title":477,"icon":49,"path":478,"stem":479,"children":480,"page":49},"Tasks","\u002Fexamples\u002Ftasks","4.examples\u002F3.tasks",[481,485,489,494,499],{"title":482,"path":483,"stem":484,"icon":70},"Protect a route","\u002Fexamples\u002Ftasks\u002Fprotect-a-route","4.examples\u002F3.tasks\u002F1.protect-a-route",{"title":486,"path":487,"stem":488,"icon":475},"Add an admin page","\u002Fexamples\u002Ftasks\u002Fadd-an-admin-page","4.examples\u002F3.tasks\u002F2.add-an-admin-page",{"title":490,"path":491,"stem":492,"icon":493},"Sell event tickets","\u002Fexamples\u002Ftasks\u002Fsell-event-tickets","4.examples\u002F3.tasks\u002F3.sell-event-tickets","i-lucide-ticket",{"title":495,"path":496,"stem":497,"icon":498},"Build a form","\u002Fexamples\u002Ftasks\u002Fbuild-a-form","4.examples\u002F3.tasks\u002F4.build-a-form","i-lucide-clipboard-list",{"title":500,"path":501,"stem":502,"icon":503},"Send an email","\u002Fexamples\u002Ftasks\u002Fsend-an-email","4.examples\u002F3.tasks\u002F5.send-an-email","i-lucide-mail",{"title":505,"icon":506,"path":507,"stem":508,"children":509,"page":49},"Contribute","i-lucide-git-pull-request","\u002Fcontribute","5.contribute",[510,513,518,544,549,552,556,571],{"title":173,"path":511,"stem":512,"icon":506},"\u002Fcontribute\u002Foverview","5.contribute\u002F1.overview",{"title":514,"path":515,"stem":516,"icon":517},"Local development","\u002Fcontribute\u002Flocal-development","5.contribute\u002F2.local-development","i-lucide-terminal",{"title":519,"icon":49,"path":520,"stem":521,"children":522,"page":49},"Writing a module","\u002Fcontribute\u002Fwriting-a-module","5.contribute\u002F3.writing-a-module",[523,527,532,536,541],{"title":524,"path":525,"stem":526,"icon":39},"Scaffold a module","\u002Fcontribute\u002Fwriting-a-module\u002Fscaffold","5.contribute\u002F3.writing-a-module\u002F1.scaffold",{"title":528,"path":529,"stem":530,"icon":531},"Setup checklist","\u002Fcontribute\u002Fwriting-a-module\u002Fsetup-checklist","5.contribute\u002F3.writing-a-module\u002F2.setup-checklist","i-lucide-list-checks",{"title":533,"path":534,"stem":535,"icon":44},"Database tables","\u002Fcontribute\u002Fwriting-a-module\u002Fdatabase-tables","5.contribute\u002F3.writing-a-module\u002F3.database-tables",{"title":537,"path":538,"stem":539,"icon":540},"Testing","\u002Fcontribute\u002Fwriting-a-module\u002Ftesting","5.contribute\u002F3.writing-a-module\u002F4.testing","i-lucide-flask-conical",{"title":67,"path":542,"stem":543,"icon":70},"\u002Fcontribute\u002Fwriting-a-module\u002Faccess-control","5.contribute\u002F3.writing-a-module\u002F5.access-control",{"title":545,"path":546,"stem":547,"icon":548},"Publishing","\u002Fcontribute\u002Fpublishing","5.contribute\u002F4.publishing","i-lucide-package-check",{"title":448,"path":550,"stem":551,"icon":6},"\u002Fcontribute\u002Fstarters","5.contribute\u002F5.starters",{"title":553,"path":554,"stem":555,"icon":52},"Documentation","\u002Fcontribute\u002Fdocumentation","5.contribute\u002F6.documentation",{"title":557,"icon":49,"path":558,"stem":559,"children":560,"page":49},"Tooling","\u002Fcontribute\u002Ftooling","5.contribute\u002F7.tooling",[561,566],{"title":562,"path":563,"stem":564,"icon":565},"CLI","\u002Fcontribute\u002Ftooling\u002Fcli","5.contribute\u002F7.tooling\u002F1.cli","i-lucide-square-terminal",{"title":567,"path":568,"stem":569,"icon":570},"ESLint config","\u002Fcontribute\u002Ftooling\u002Feslint-config","5.contribute\u002F7.tooling\u002F2.eslint-config","i-lucide-spell-check",{"title":572,"icon":49,"path":573,"stem":574,"children":575},"Decisions","\u002Fcontribute\u002Fdecisions","5.contribute\u002F8.decisions\u002Findex",[576,578,583],{"title":572,"path":573,"stem":574,"icon":577},"i-lucide-scale",{"title":579,"path":580,"stem":581,"icon":582},"Session lifetimes per OAuth client","\u002Fcontribute\u002Fdecisions\u002Foauth-token-lifetimes","5.contribute\u002F8.decisions\u002F1.oauth-token-lifetimes","i-lucide-timer",{"title":584,"path":585,"stem":586,"icon":70},"One permission model","\u002Fcontribute\u002Fdecisions\u002Fpermission-model","5.contribute\u002F8.decisions\u002F2.permission-model",{"id":588,"title":589,"body":590,"description":4187,"extension":4188,"links":4189,"meta":4190,"navigation":4191,"path":184,"seo":4192,"stem":185,"__hash__":4193},"docs\u002F3.modules\u002F1.identity\u002F1.auth\u002F4.client-mode.md","Auth client mode",{"type":591,"value":592,"toc":4161},"minimark",[593,616,620,669,681,686,1251,1268,1272,1275,1375,1385,1389,1396,1919,1929,1943,1956,1977,1984,2004,2017,2027,2045,2049,2055,2157,2174,2178,2185,2280,2303,2306,2311,2402,2409,2426,2429,2432,2618,2718,2760,2768,2817,2831,2844,2869,2872,2875,2900,2903,2948,2966,2978,3135,3184,3254,3259,3263,3269,3337,3358,3382,3385,3392,3467,3480,3491,3494,3510,3516,3520,3548,3552,3617,3621,3624,3712,3716,3728,3752,3756,3766,4005,4093,4136,4140,4157],[594,595,596,597,604,605,608,609,611,612,615],"p",{},"Client mode signs people in from an app without its own server, such as a browser single-page application (SPA) or a\n",[598,599,603],"a",{"href":600,"rel":601},"https:\u002F\u002Fcapacitorjs.com",[602],"nofollow","Capacitor"," app: at an ",[598,606,607],{"href":87},"issuer",", with PKCE (Proof Key for Code\nExchange), and with tokens the app keeps and refreshes itself. This page is for app developers; client mode only, with\nthe same app code and ",[598,610,199],{"href":200}," guards as\n",[598,613,614],{"href":87},"server mode",".",[617,618],"module-runtime",{":client":619,":mobile":619},"true",[621,622,623,637,657],"note",{},[594,624,625,629,630,636],{},[626,627,628],"strong",{},"Installed for you:"," ",[598,631,632],{"href":382},[633,634,635],"code",{},"@frigear-nu\u002Fmodule-kit",". Client mode installs none of server\nmode's dependencies (NuxtHub, nuxt-auth-utils, Notify, Menu).",[594,638,639,642,643,646,647,646,650,653,654,615],{},[626,640,641],{},"You add:"," in a Capacitor app, ",[633,644,645],{},"@capacitor\u002Fapp",", ",[633,648,649],{},"@capacitor\u002Fbrowser",[633,651,652],{},"@capacitor\u002Fpreferences"," and\n",[633,655,656],{},"@aparajita\u002Fcapacitor-secure-storage",[594,658,659,629,662,665,666,615],{},[626,660,661],{},"Optional:",[633,663,664],{},"@nuxt\u002Fui",", for the sign-in and callback pages and ",[633,667,668],{},"AuthSignInButton",[670,671,672,673,676,677,615],"caution",{},"For a server-rendered web app, keep server mode. Client mode moves the credential from an httpOnly cookie into\n",[633,674,675],{},"localStorage"," (or the Keychain on a device). There, any cross-site scripting (XSS) can read it in a browser, and the\nserver cannot know who is signed in. See ",[598,678,680],{"href":679},"#security","Security",[682,683,685],"h2",{"id":684},"quick-setup","Quick setup",[687,688,689,694,748,752,755,1063,1067,1071,1081,1105,1117,1121],"steps",{},[690,691,693],"h3",{"id":692},"install-the-modules","Install the modules",[695,696,701],"pre",{"className":697,"code":698,"language":699,"meta":700,"style":700},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm add @frigear-nu\u002Fauth @frigear-nu\u002Fauthorization\n# inside a Capacitor app also:\npnpm add @capacitor\u002Fapp @capacitor\u002Fbrowser @capacitor\u002Fpreferences @aparajita\u002Fcapacitor-secure-storage\n","bash","",[633,702,703,722,729],{"__ignoreMap":700},[704,705,708,712,716,719],"span",{"class":706,"line":707},"line",1,[704,709,711],{"class":710},"sBMFI","pnpm",[704,713,715],{"class":714},"sfazB"," add",[704,717,718],{"class":714}," @frigear-nu\u002Fauth",[704,720,721],{"class":714}," @frigear-nu\u002Fauthorization\n",[704,723,725],{"class":706,"line":724},2,[704,726,728],{"class":727},"sHwdD","# inside a Capacitor app also:\n",[704,730,732,734,736,739,742,745],{"class":706,"line":731},3,[704,733,711],{"class":710},[704,735,715],{"class":714},[704,737,738],{"class":714}," @capacitor\u002Fapp",[704,740,741],{"class":714}," @capacitor\u002Fbrowser",[704,743,744],{"class":714}," @capacitor\u002Fpreferences",[704,746,747],{"class":714}," @aparajita\u002Fcapacitor-secure-storage\n",[690,749,751],{"id":750},"configure-client-mode","Configure client mode",[594,753,754],{},"Set the mode, the issuer and your app's client id. The route rule signs people in everywhere: the sign-in and callback\npages stay open without a rule, and a visitor is sent to the sign-in page.",[695,756,761],{"className":757,"code":758,"filename":759,"language":760,"meta":700,"style":700},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNuxtConfig({\n  modules: ['@nuxt\u002Fui', '@frigear-nu\u002Fauth', '@frigear-nu\u002Fauthorization'],\n  authentication: {\n    mode: 'client',\n    client: {\n      issuer: 'https:\u002F\u002Ffrigear.nu',\n      clientId: 'my-app',\n      scopes: ['openid', 'profile', 'email', 'offline_access'], \u002F\u002F must contain 'openid'\n      apiBase: 'https:\u002F\u002Fapi.example.com', \u002F\u002F default: the issuer\n      native: { scheme: 'com.example.app' }, \u002F\u002F redirect URI com.example.app:\u002Fauth\u002Fcallback\n    },\n  },\n  routeRules: {\n    '\u002F**': { authenticated: true },\n  },\n})\n","nuxt.config.ts","ts",[633,762,763,784,829,839,856,866,883,900,951,971,1000,1006,1012,1022,1049,1054],{"__ignoreMap":700},[704,764,765,769,772,776,780],{"class":706,"line":707},[704,766,768],{"class":767},"s7zQu","export",[704,770,771],{"class":767}," default",[704,773,775],{"class":774},"s2Zo4"," defineNuxtConfig",[704,777,779],{"class":778},"sTEyZ","(",[704,781,783],{"class":782},"sMK4o","{\n",[704,785,786,790,793,796,799,801,803,806,809,812,814,816,818,821,823,826],{"class":706,"line":724},[704,787,789],{"class":788},"swJcz","  modules",[704,791,792],{"class":782},":",[704,794,795],{"class":778}," [",[704,797,798],{"class":782},"'",[704,800,664],{"class":714},[704,802,798],{"class":782},[704,804,805],{"class":782},",",[704,807,808],{"class":782}," '",[704,810,811],{"class":714},"@frigear-nu\u002Fauth",[704,813,798],{"class":782},[704,815,805],{"class":782},[704,817,808],{"class":782},[704,819,820],{"class":714},"@frigear-nu\u002Fauthorization",[704,822,798],{"class":782},[704,824,825],{"class":778},"]",[704,827,828],{"class":782},",\n",[704,830,831,834,836],{"class":706,"line":731},[704,832,833],{"class":788},"  authentication",[704,835,792],{"class":782},[704,837,838],{"class":782}," {\n",[704,840,842,845,847,849,852,854],{"class":706,"line":841},4,[704,843,844],{"class":788},"    mode",[704,846,792],{"class":782},[704,848,808],{"class":782},[704,850,851],{"class":714},"client",[704,853,798],{"class":782},[704,855,828],{"class":782},[704,857,859,862,864],{"class":706,"line":858},5,[704,860,861],{"class":788},"    client",[704,863,792],{"class":782},[704,865,838],{"class":782},[704,867,869,872,874,876,879,881],{"class":706,"line":868},6,[704,870,871],{"class":788},"      issuer",[704,873,792],{"class":782},[704,875,808],{"class":782},[704,877,878],{"class":714},"https:\u002F\u002Ffrigear.nu",[704,880,798],{"class":782},[704,882,828],{"class":782},[704,884,886,889,891,893,896,898],{"class":706,"line":885},7,[704,887,888],{"class":788},"      clientId",[704,890,792],{"class":782},[704,892,808],{"class":782},[704,894,895],{"class":714},"my-app",[704,897,798],{"class":782},[704,899,828],{"class":782},[704,901,903,906,908,910,912,915,917,919,921,924,926,928,930,933,935,937,939,942,944,946,948],{"class":706,"line":902},8,[704,904,905],{"class":788},"      scopes",[704,907,792],{"class":782},[704,909,795],{"class":778},[704,911,798],{"class":782},[704,913,914],{"class":714},"openid",[704,916,798],{"class":782},[704,918,805],{"class":782},[704,920,808],{"class":782},[704,922,923],{"class":714},"profile",[704,925,798],{"class":782},[704,927,805],{"class":782},[704,929,808],{"class":782},[704,931,932],{"class":714},"email",[704,934,798],{"class":782},[704,936,805],{"class":782},[704,938,808],{"class":782},[704,940,941],{"class":714},"offline_access",[704,943,798],{"class":782},[704,945,825],{"class":778},[704,947,805],{"class":782},[704,949,950],{"class":727}," \u002F\u002F must contain 'openid'\n",[704,952,954,957,959,961,964,966,968],{"class":706,"line":953},9,[704,955,956],{"class":788},"      apiBase",[704,958,792],{"class":782},[704,960,808],{"class":782},[704,962,963],{"class":714},"https:\u002F\u002Fapi.example.com",[704,965,798],{"class":782},[704,967,805],{"class":782},[704,969,970],{"class":727}," \u002F\u002F default: the issuer\n",[704,972,974,977,979,982,985,987,989,992,994,997],{"class":706,"line":973},10,[704,975,976],{"class":788},"      native",[704,978,792],{"class":782},[704,980,981],{"class":782}," {",[704,983,984],{"class":788}," scheme",[704,986,792],{"class":782},[704,988,808],{"class":782},[704,990,991],{"class":714},"com.example.app",[704,993,798],{"class":782},[704,995,996],{"class":782}," },",[704,998,999],{"class":727}," \u002F\u002F redirect URI com.example.app:\u002Fauth\u002Fcallback\n",[704,1001,1003],{"class":706,"line":1002},11,[704,1004,1005],{"class":782},"    },\n",[704,1007,1009],{"class":706,"line":1008},12,[704,1010,1011],{"class":782},"  },\n",[704,1013,1015,1018,1020],{"class":706,"line":1014},13,[704,1016,1017],{"class":788},"  routeRules",[704,1019,792],{"class":782},[704,1021,838],{"class":782},[704,1023,1025,1028,1031,1033,1035,1037,1040,1042,1046],{"class":706,"line":1024},14,[704,1026,1027],{"class":782},"    '",[704,1029,1030],{"class":788},"\u002F**",[704,1032,798],{"class":782},[704,1034,792],{"class":782},[704,1036,981],{"class":782},[704,1038,1039],{"class":788}," authenticated",[704,1041,792],{"class":782},[704,1043,1045],{"class":1044},"sfNiH"," true",[704,1047,1048],{"class":782}," },\n",[704,1050,1052],{"class":706,"line":1051},15,[704,1053,1011],{"class":782},[704,1055,1057,1060],{"class":706,"line":1056},16,[704,1058,1059],{"class":782},"}",[704,1061,1062],{"class":778},")\n",[690,1064,1066],{"id":1065},"register-the-app-at-the-issuer","Register the app at the issuer",[1068,1069,1070],"warning",{},"Sign-in fails unless the redirect URIs match exactly and the issuer allows your origins.",[594,1072,1073,1074,629,1077,1080],{},"Register a ",[626,1075,1076],{},"public",[598,1078,1079],{"href":87},"OAuth application"," at the issuer with these redirect URIs:",[1082,1083,1084,1096],"ul",{},[1085,1086,1087,1088,1091,1092,1095],"li",{},"browser: ",[633,1089,1090],{},"\u003Corigin>\u002Fauth\u002Fcallback",", for example ",[633,1093,1094],{},"http:\u002F\u002Flocalhost:3000\u002Fauth\u002Fcallback",";",[1085,1097,1098,1099,1091,1102,615],{},"native: ",[633,1100,1101],{},"\u003Cscheme in lowercase>:\u002Fauth\u002Fcallback",[633,1103,1104],{},"com.example.app:\u002Fauth\u002Fcallback",[594,1106,1107,1108,646,1111,1114,1115,615],{},"Any OpenID Connect provider works as the issuer. It must also allow the app's origins for CORS on the token, revoke and\nuserinfo endpoints. These are ",[633,1109,1110],{},"capacitor:\u002F\u002Flocalhost",[633,1112,1113],{},"https:\u002F\u002Flocalhost"," and your dev origin. The full list is in\n",[598,1116,131],{"href":132},[690,1118,1120],{"id":1119},"call-your-api","Call your API",[695,1122,1127],{"className":1123,"code":1124,"filename":1125,"language":1126,"meta":700,"style":700},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cscript setup lang=\"ts\">\nconst { user } = useUserSession()\nconst { logout } = useAuth()\nconst { data: bills } = await useApi\u003CBill[]>('\u002Fapi\u002Fbills')\n\u003C\u002Fscript>\n","app\u002Fpages\u002Fbills.vue","vue",[633,1128,1129,1157,1178,1196,1242],{"__ignoreMap":700},[704,1130,1131,1134,1137,1141,1144,1147,1150,1152,1154],{"class":706,"line":707},[704,1132,1133],{"class":782},"\u003C",[704,1135,1136],{"class":788},"script",[704,1138,1140],{"class":1139},"spNyl"," setup",[704,1142,1143],{"class":1139}," lang",[704,1145,1146],{"class":782},"=",[704,1148,1149],{"class":782},"\"",[704,1151,760],{"class":714},[704,1153,1149],{"class":782},[704,1155,1156],{"class":782},">\n",[704,1158,1159,1162,1164,1167,1169,1172,1175],{"class":706,"line":724},[704,1160,1161],{"class":1139},"const",[704,1163,981],{"class":782},[704,1165,1166],{"class":778}," user ",[704,1168,1059],{"class":782},[704,1170,1171],{"class":782}," =",[704,1173,1174],{"class":774}," useUserSession",[704,1176,1177],{"class":778},"()\n",[704,1179,1180,1182,1184,1187,1189,1191,1194],{"class":706,"line":731},[704,1181,1161],{"class":1139},[704,1183,981],{"class":782},[704,1185,1186],{"class":778}," logout ",[704,1188,1059],{"class":782},[704,1190,1171],{"class":782},[704,1192,1193],{"class":774}," useAuth",[704,1195,1177],{"class":778},[704,1197,1198,1200,1202,1205,1207,1210,1212,1214,1217,1220,1222,1225,1228,1231,1233,1235,1238,1240],{"class":706,"line":841},[704,1199,1161],{"class":1139},[704,1201,981],{"class":782},[704,1203,1204],{"class":788}," data",[704,1206,792],{"class":782},[704,1208,1209],{"class":778}," bills ",[704,1211,1059],{"class":782},[704,1213,1171],{"class":782},[704,1215,1216],{"class":767}," await",[704,1218,1219],{"class":774}," useApi",[704,1221,1133],{"class":782},[704,1223,1224],{"class":710},"Bill",[704,1226,1227],{"class":778},"[]",[704,1229,1230],{"class":782},">",[704,1232,779],{"class":778},[704,1234,798],{"class":782},[704,1236,1237],{"class":714},"\u002Fapi\u002Fbills",[704,1239,798],{"class":782},[704,1241,1062],{"class":778},[704,1243,1244,1247,1249],{"class":706,"line":858},[704,1245,1246],{"class":782},"\u003C\u002F",[704,1248,1136],{"class":788},[704,1250,1156],{"class":782},[1252,1253,1256,1259,1260,1263,1264,1267],"callout",{"color":1254,"icon":1255},"success","i-lucide-check",[626,1257,1258],{},"What you should see:"," opening the app sends you to ",[633,1261,1262],{},"\u002Flogin",". After you sign in at the issuer, you come back to the\npage you opened, and ",[633,1265,1266],{},"useUserSession().user"," holds your name and email.",[682,1269,1271],{"id":1270},"the-mode","The mode",[594,1273,1274],{},"Client mode checks the app when it builds:",[1276,1277,1278,1294],"table",{},[1279,1280,1281],"thead",{},[1282,1283,1284,1288,1291],"tr",{},[1285,1286,1287],"th",{},"Check",[1285,1289,1290],{},"What happens",[1285,1292,1293],{},"Why",[1295,1296,1297,1317,1333,1350],"tbody",{},[1282,1298,1299,1303,1314],{},[1300,1301,1302],"td",{},"Server-side rendering (SSR) is off",[1300,1304,1305,1306,1309,1310,1313],{},"Client mode sets ",[633,1307,1308],{},"ssr: false",". ",[633,1311,1312],{},"ssr: true"," in the app or a layer fails the build.",[1300,1315,1316],{},"A server render would always be signed out.",[1282,1318,1319,1324,1330],{},[1300,1320,1321,1323],{},[633,1322,914],{}," is required",[1300,1325,1326,1327,1329],{},"Scopes without ",[633,1328,914],{}," fail the build.",[1300,1331,1332],{},"The signed-in user comes from the ID token.",[1282,1334,1335,1338,1347],{},[1300,1336,1337],{},"No server modules",[1300,1339,1340,1343,1344,1346],{},[633,1341,1342],{},"nuxt-auth-utils"," and ",[598,1345,191],{"href":192}," fail the build, naming the module that installed them.",[1300,1348,1349],{},"They need a server and a database.",[1282,1351,1352,1355,1372],{},[1300,1353,1354],{},"Guards need Authorization",[1300,1356,1357,1360,1361,646,1364,1367,1368,1371],{},[633,1358,1359],{},"routeRules"," with ",[633,1362,1363],{},"authenticated",[633,1365,1366],{},"permission"," or ",[633,1369,1370],{},"guest"," but no Authorization print a warning.",[1300,1373,1374],{},"Nothing would check them.",[594,1376,1377,1378,1380,1381,1384],{},"The ",[633,1379,914],{}," check also covers ",[633,1382,1383],{},"runtimeConfig.public.authentication.client.scope",", and an environment override is\nchecked again when the client starts. The modules that install Users are server mode only: Account, Events, Payments,\nSubscriptions and Preferences.",[682,1386,1388],{"id":1387},"options","Options",[594,1390,1391,1392,1395],{},"Options go under the ",[633,1393,1394],{},"authentication"," key.",[1276,1397,1398,1414],{},[1279,1399,1400],{},[1282,1401,1402,1405,1408,1411],{},[1285,1403,1404],{},"Option",[1285,1406,1407],{},"Type",[1285,1409,1410],{},"Default",[1285,1412,1413],{},"Purpose",[1295,1415,1416,1434,1450,1472,1495,1519,1543,1562,1581,1597,1617,1647,1666,1693,1717,1738,1761,1782,1805,1826,1849,1869,1895],{},[1282,1417,1418,1423,1428,1431],{},[1300,1419,1420],{},[633,1421,1422],{},"client.issuer",[1300,1424,1425],{},[633,1426,1427],{},"string",[1300,1429,1430],{},"–",[1300,1432,1433],{},"Required (option or env). The issuer URL.",[1282,1435,1436,1441,1445,1447],{},[1300,1437,1438],{},[633,1439,1440],{},"client.clientId",[1300,1442,1443],{},[633,1444,1427],{},[1300,1446,1430],{},[1300,1448,1449],{},"Required (option or env). The id of your public OAuth application.",[1282,1451,1452,1457,1462,1467],{},[1300,1453,1454],{},[633,1455,1456],{},"client.scopes",[1300,1458,1459],{},[633,1460,1461],{},"string[]",[1300,1463,1464],{},[633,1465,1466],{},"['openid']",[1300,1468,1469,1470,615],{},"Requested scopes. Must contain ",[633,1471,914],{},[1282,1473,1474,1479,1483,1486],{},[1300,1475,1476],{},[633,1477,1478],{},"client.apiBase",[1300,1480,1481],{},[633,1482,1427],{},[1300,1484,1485],{},"the issuer",[1300,1487,1488,1489,1343,1492,615],{},"Base URL of ",[633,1490,1491],{},"$api",[633,1493,1494],{},"useApi",[1282,1496,1497,1502,1506,1513],{},[1300,1498,1499],{},[633,1500,1501],{},"client.apiOrigins",[1300,1503,1504],{},[633,1505,1461],{},[1300,1507,1508,1509,1512],{},"the ",[633,1510,1511],{},"apiBase"," and issuer origins",[1300,1514,1515,1516,1518],{},"Origins ",[633,1517,1491],{}," sends the bearer token to.",[1282,1520,1521,1526,1531,1536],{},[1300,1522,1523],{},[633,1524,1525],{},"client.onUnauthorized",[1300,1527,1528],{},[633,1529,1530],{},"'signOut' | 'none'",[1300,1532,1533],{},[633,1534,1535],{},"'signOut'",[1300,1537,1538,1539,1542],{},"What a ",[633,1540,1541],{},"401"," does that a forced refresh did not fix.",[1282,1544,1545,1550,1554,1559],{},[1300,1546,1547],{},[633,1548,1549],{},"client.redirectUri",[1300,1551,1552],{},[633,1553,1427],{},[1300,1555,1556],{},[633,1557,1558],{},"\u003Corigin>\u003CcallbackPath>",[1300,1560,1561],{},"The browser redirect URI.",[1282,1563,1564,1569,1573,1578],{},[1300,1565,1566],{},[633,1567,1568],{},"client.callbackPath",[1300,1570,1571],{},[633,1572,1427],{},[1300,1574,1575],{},[633,1576,1577],{},"\u002Fauth\u002Fcallback",[1300,1579,1580],{},"Path of the callback page and of the redirect URIs derived from it.",[1282,1582,1583,1588,1592,1594],{},[1300,1584,1585],{},[633,1586,1587],{},"client.native.scheme",[1300,1589,1590],{},[633,1591,1427],{},[1300,1593,1430],{},[1300,1595,1596],{},"Custom URL scheme, usually the app id.",[1282,1598,1599,1604,1608,1610],{},[1300,1600,1601],{},[633,1602,1603],{},"client.native.redirectUri",[1300,1605,1606],{},[633,1607,1427],{},[1300,1609,1430],{},[1300,1611,1612,1613,1616],{},"A full native redirect URI instead, for example a claimed ",[633,1614,1615],{},"https"," universal link.",[1282,1618,1619,1624,1629,1632],{},[1300,1620,1621],{},[633,1622,1623],{},"client.endpoints",[1300,1625,1626],{},[633,1627,1628],{},"Partial\u003COAuthEndpoints>",[1300,1630,1631],{},"discovered",[1300,1633,1634,646,1637,646,1640,646,1643,1646],{},[633,1635,1636],{},"authorization",[633,1638,1639],{},"token",[633,1641,1642],{},"revocation",[633,1644,1645],{},"userinfo"," and more.",[1282,1648,1649,1654,1659,1663],{},[1300,1650,1651],{},[633,1652,1653],{},"client.discovery",[1300,1655,1656],{},[633,1657,1658],{},"boolean",[1300,1660,1661],{},[633,1662,619],{},[1300,1664,1665],{},"Find the endpoints through OpenID Connect discovery.",[1282,1667,1668,1673,1678,1683],{},[1300,1669,1670],{},[633,1671,1672],{},"client.authorizationParams",[1300,1674,1675],{},[633,1676,1677],{},"Record\u003Cstring, string>",[1300,1679,1680],{},[633,1681,1682],{},"{}",[1300,1684,1685,1686,646,1689,1692],{},"Extra authorization request parameters (",[633,1687,1688],{},"prompt",[633,1690,1691],{},"audience",", ...).",[1282,1694,1695,1700,1705,1710],{},[1300,1696,1697],{},[633,1698,1699],{},"client.storage",[1300,1701,1702],{},[633,1703,1704],{},"StorageOption",[1300,1706,1707],{},[633,1708,1709],{},"auto",[1300,1711,1712,1713,615],{},"Where tokens live. See ",[598,1714,1716],{"href":1715},"#token-storage","Token storage",[1282,1718,1719,1724,1728,1731],{},[1300,1720,1721],{},[633,1722,1723],{},"client.mapUser",[1300,1725,1726],{},[633,1727,1427],{},[1300,1729,1730],{},"the claims mapping",[1300,1732,1733,1734,615],{},"Path to a file whose default export maps the signed-in user. See ",[598,1735,1737],{"href":1736},"#the-user","The user",[1282,1739,1740,1745,1749,1754],{},[1300,1741,1742],{},[633,1743,1744],{},"client.userinfo",[1300,1746,1747],{},[633,1748,1658],{},[1300,1750,1751],{},[633,1752,1753],{},"false",[1300,1755,1756,1757,1760],{},"The default mapping merges the issuer's ",[633,1758,1759],{},"\u002Fuserinfo"," response too.",[1282,1762,1763,1768,1772,1775],{},[1300,1764,1765],{},[633,1766,1767],{},"client.redirect.login",[1300,1769,1770],{},[633,1771,1427],{},[1300,1773,1774],{},"the sign-in page",[1300,1776,1777,1778,1781],{},"Where ",[633,1779,1780],{},"onUnauthorized: 'signOut'"," and a failed native sign-in send the visitor.",[1282,1783,1784,1789,1793,1798],{},[1300,1785,1786],{},[633,1787,1788],{},"client.redirect.afterLogin",[1300,1790,1791],{},[633,1792,1427],{},[1300,1794,1795],{},[633,1796,1797],{},"\u002F",[1300,1799,1800,1801,1804],{},"After a sign-in that started without a ",[633,1802,1803],{},"returnTo",". A path on this site.",[1282,1806,1807,1812,1816,1820],{},[1300,1808,1809],{},[633,1810,1811],{},"client.redirect.afterLogout",[1300,1813,1814],{},[633,1815,1427],{},[1300,1817,1818],{},[633,1819,1797],{},[1300,1821,1822,1823,1804],{},"After ",[633,1824,1825],{},"logout()",[1282,1827,1828,1833,1838,1842],{},[1300,1829,1830],{},[633,1831,1832],{},"client.dev.rewriteLoopback",[1300,1834,1835],{},[633,1836,1837],{},"boolean | string",[1300,1839,1840],{},[633,1841,619],{},[1300,1843,1844,1845,1848],{},"Rewrites ",[633,1846,1847],{},"localhost"," in development on a device.",[1282,1850,1851,1856,1860,1864],{},[1300,1852,1853],{},[633,1854,1855],{},"client.allowClientSecretInBundle",[1300,1857,1858],{},[633,1859,1658],{},[1300,1861,1862],{},[633,1863,1753],{},[1300,1865,1866,1867,615],{},"Allow a build that embeds a client secret. See ",[598,1868,680],{"href":679},[1282,1870,1871,1876,1881,1889],{},[1300,1872,1873],{},[633,1874,1875],{},"settings.pages.login",[1300,1877,1878],{},[633,1879,1880],{},"string | boolean",[1300,1882,1883,1885,1886,1888],{},[633,1884,619],{}," (",[633,1887,1262],{},")",[1300,1890,1891,1892,1894],{},"The sign-in page (needs ",[633,1893,664],{},"). On by default in client mode.",[1282,1896,1897,1902,1906,1910],{},[1300,1898,1899],{},[633,1900,1901],{},"settings.pages.callback",[1300,1903,1904],{},[633,1905,1658],{},[1300,1907,1908],{},[633,1909,619],{},[1300,1911,1912,1913,1915,1916,1918],{},"The callback page at ",[633,1914,1568],{}," (needs ",[633,1917,664],{},"). Client mode only.",[594,1920,1921,1925,1926,1928],{},[626,1922,1923,615],{},[633,1924,1456],{}," Add ",[633,1927,941],{}," for refresh tokens where the provider needs it.",[594,1930,1931,1935,1936,1939,1940,1942],{},[626,1932,1933,615],{},[633,1934,1501],{}," Setting it replaces the default. Any other origin gets no token. The core's own\n",[633,1937,1938],{},"client.fetch"," sends the token to these origins plus ",[633,1941,1511],{}," and the issuer.",[594,1944,1945,629,1949,1951,1952,1955],{},[626,1946,1947,615],{},[633,1948,1525],{},[633,1950,1535],{}," signs out and goes to the sign-in page, then back afterwards. ",[633,1953,1954],{},"'none'"," only\nthrows.",[594,1957,1958,1962,1963,1966,1967,1970,1971,1973,1974,615],{},[626,1959,1960,615],{},[633,1961,1587],{}," The redirect URI is ",[633,1964,1965],{},"\u003Cscheme lowercase>:\u003CcallbackPath>",". An invalid scheme, for example one\nwith ",[633,1968,1969],{},"_",", fails the build. ",[598,1972,362],{"href":363}," fills it in from ",[633,1975,1976],{},"appId",[594,1978,1979,1983],{},[626,1980,1981,615],{},[633,1982,1623],{}," Each is absolute or relative to the issuer. They win over discovery.",[594,1985,1986,1990,1991,1994,1995,1997,1998,2000,2001,1692],{},[626,1987,1988,615],{},[633,1989,1653],{}," Discovery reads ",[633,1992,1993],{},"openid-configuration"," and falls back to RFC 8414 (OAuth server metadata).\n",[633,1996,1753],{}," uses the ",[598,1999,225],{"href":226}," paths (",[633,2002,2003],{},"\u002Foauth\u002Fauthorize",[594,2005,2006,2010,2011,2013,2014,2016],{},[626,2007,2008,615],{},[633,2009,1832],{}," In development on a device, ",[633,2012,1847],{}," in the issuer and ",[633,2015,1511],{}," becomes the host\nthe app was loaded from. A string sets the host.",[594,2018,2019,2023,2024,2026],{},[626,2020,2021,615],{},[633,2022,1875],{}," A string sets another path, ",[633,2025,1753],{}," none.",[594,2028,2029,2030,2033,2034,2037,2038,2040,2041,2044],{},"The other ",[633,2031,2032],{},"settings"," (password, emailed links, passkeys, OAuth providers) are server mode only. In client mode every\nfeature flag in ",[633,2035,2036],{},"runtimeConfig.public.authentication"," is ",[633,2039,1753],{},", so code that checks them works in both modes.\n",[633,2042,2043],{},"useAuthPages()"," returns the sign-in path in both modes.",[690,2046,2048],{"id":2047},"sign-in-page-branding","Sign-in page branding",[594,2050,2051,2052,792],{},"Brand the sign-in page in ",[633,2053,2054],{},"app.config.ts",[695,2056,2059],{"className":757,"code":2057,"filename":2058,"language":760,"meta":700,"style":700},"export default defineAppConfig({\n  authentication: {\n    login: { title: 'Household bills', description: 'Sign in to continue.', logo: '\u002Flogo.svg', icon: 'i-lucide-wallet' },\n  },\n})\n","app\u002Fapp.config.ts",[633,2060,2061,2074,2082,2147,2151],{"__ignoreMap":700},[704,2062,2063,2065,2067,2070,2072],{"class":706,"line":707},[704,2064,768],{"class":767},[704,2066,771],{"class":767},[704,2068,2069],{"class":774}," defineAppConfig",[704,2071,779],{"class":778},[704,2073,783],{"class":782},[704,2075,2076,2078,2080],{"class":706,"line":724},[704,2077,833],{"class":788},[704,2079,792],{"class":782},[704,2081,838],{"class":782},[704,2083,2084,2087,2089,2091,2094,2096,2098,2101,2103,2105,2108,2110,2112,2115,2117,2119,2122,2124,2126,2129,2131,2133,2136,2138,2140,2143,2145],{"class":706,"line":731},[704,2085,2086],{"class":788},"    login",[704,2088,792],{"class":782},[704,2090,981],{"class":782},[704,2092,2093],{"class":788}," title",[704,2095,792],{"class":782},[704,2097,808],{"class":782},[704,2099,2100],{"class":714},"Household bills",[704,2102,798],{"class":782},[704,2104,805],{"class":782},[704,2106,2107],{"class":788}," description",[704,2109,792],{"class":782},[704,2111,808],{"class":782},[704,2113,2114],{"class":714},"Sign in to continue.",[704,2116,798],{"class":782},[704,2118,805],{"class":782},[704,2120,2121],{"class":788}," logo",[704,2123,792],{"class":782},[704,2125,808],{"class":782},[704,2127,2128],{"class":714},"\u002Flogo.svg",[704,2130,798],{"class":782},[704,2132,805],{"class":782},[704,2134,2135],{"class":788}," icon",[704,2137,792],{"class":782},[704,2139,808],{"class":782},[704,2141,2142],{"class":714},"i-lucide-wallet",[704,2144,798],{"class":782},[704,2146,1048],{"class":782},[704,2148,2149],{"class":706,"line":841},[704,2150,1011],{"class":782},[704,2152,2153,2155],{"class":706,"line":858},[704,2154,1059],{"class":782},[704,2156,1062],{"class":778},[594,2158,2159,2162,2163,1309,2166,2169,2170,2173],{},[633,2160,2161],{},"logo"," is an image path or ",[633,2164,2165],{},"{ light, dark }",[633,2167,2168],{},"icon"," shows when there is no logo. The page strings are in the\n",[633,2171,2172],{},"auth.client"," i18n namespace.",[690,2175,2177],{"id":2176},"runtime-config","Runtime config",[594,2179,2180,2181,2184],{},"The runtime config is ",[633,2182,2183],{},"runtimeConfig.public.authentication.client",". Your app's own values win over the module options.",[1276,2186,2187,2196],{},[1279,2188,2189],{},[1282,2190,2191,2194],{},[1285,2192,2193],{},"Variable",[1285,2195,1404],{},[1295,2197,2198,2209,2221,2234,2245,2258,2268],{},[1282,2199,2200,2205],{},[1300,2201,2202],{},[633,2203,2204],{},"NUXT_PUBLIC_AUTHENTICATION_CLIENT_ISSUER",[1300,2206,2207],{},[633,2208,607],{},[1282,2210,2211,2216],{},[1300,2212,2213],{},[633,2214,2215],{},"NUXT_PUBLIC_AUTHENTICATION_CLIENT_CLIENT_ID",[1300,2217,2218],{},[633,2219,2220],{},"clientId",[1282,2222,2223,2228],{},[1300,2224,2225],{},[633,2226,2227],{},"NUXT_PUBLIC_AUTHENTICATION_CLIENT_SCOPE",[1300,2229,2230,2233],{},[633,2231,2232],{},"scopes",", as a space separated string",[1282,2235,2236,2241],{},[1300,2237,2238],{},[633,2239,2240],{},"NUXT_PUBLIC_AUTHENTICATION_CLIENT_API_BASE",[1300,2242,2243],{},[633,2244,1511],{},[1282,2246,2247,2252],{},[1300,2248,2249],{},[633,2250,2251],{},"NUXT_PUBLIC_AUTHENTICATION_CLIENT_REDIRECT_URI",[1300,2253,2254,2257],{},[633,2255,2256],{},"redirectUri"," (browser)",[1282,2259,2260,2265],{},[1300,2261,2262],{},[633,2263,2264],{},"NUXT_PUBLIC_AUTHENTICATION_CLIENT_NATIVE_REDIRECT_URI",[1300,2266,2267],{},"the native redirect URI",[1282,2269,2270,2275],{},[1300,2271,2272],{},[633,2273,2274],{},"NUXT_PUBLIC_AUTHENTICATION_CLIENT_CLIENT_SECRET",[1300,2276,2277,2278,615],{},"Development only, against a confidential application. See ",[598,2279,680],{"href":679},[1082,2281,2282,2291,2300],{},[1085,2283,2284,2287,2288,615],{},[633,2285,2286],{},"NUXT_PUBLIC_AUTHENTICATION_CLIENT_SECRET"," works as well as ",[633,2289,2290],{},"..._CLIENT_CLIENT_SECRET",[1085,2292,2293,2294,1885,2296,2299],{},"A list set in ",[633,2295,2183],{},[633,2297,2298],{},"apiOrigins",") replaces the module's.",[1085,2301,2302],{},"In a static build the values are baked in when it is generated.",[690,2304,1716],{"id":2305},"token-storage",[594,2307,1377,2308,2310],{},[633,2309,1699],{}," option decides where tokens live.",[1276,2312,2313,2323],{},[1279,2314,2315],{},[1282,2316,2317,2320],{},[1285,2318,2319],{},"Value",[1285,2321,2322],{},"Where",[1295,2324,2325,2337,2350,2362,2380,2390],{},[1282,2326,2327,2331],{},[1300,2328,2329],{},[633,2330,1709],{},[1300,2332,2333,2334,2336],{},"Secure storage on a device, ",[633,2335,675],{}," in a browser.",[1282,2338,2339,2344],{},[1300,2340,2341],{},[633,2342,2343],{},"secure",[1300,2345,2346,2347,2349],{},"Keychain \u002F Keystore (",[633,2348,656],{},"). Required on a device.",[1282,2351,2352,2357],{},[1300,2353,2354],{},[633,2355,2356],{},"preferences",[1300,2358,2359,2361],{},[633,2360,652],{}," (UserDefaults \u002F SharedPreferences, not encrypted).",[1282,2363,2364,2373],{},[1300,2365,2366,2369,2370],{},[633,2367,2368],{},"local"," \u002F ",[633,2371,2372],{},"session",[1300,2374,2375,2369,2377,615],{},[633,2376,675],{},[633,2378,2379],{},"sessionStorage",[1282,2381,2382,2387],{},[1300,2383,2384],{},[633,2385,2386],{},"memory",[1300,2388,2389],{},"Signed out on every reload.",[1282,2391,2392,2395],{},[1300,2393,2394],{},"a file path",[1300,2396,2397,2398,2401],{},"A file whose default export is a ",[633,2399,2400],{},"TokenStorage"," or a function returning one.",[594,2403,2404,2405,2408],{},"A file path is relative to the app's ",[633,2406,2407],{},"rootDir",", or names a package.",[1068,2410,2411,2412,2415,2416,1360,2419,2421,2422,2425],{},"An app with ",[633,2413,2414],{},"@capacitor\u002Fcore"," but without the secure storage plugin ",[626,2417,2418],{},"fails a production build",[633,2420,1709],{},",\nbecause the tokens would sit unencrypted. Install the plugin, or set ",[633,2423,2424],{},"storage: 'preferences'"," to accept that.",[594,2427,2428],{},"On a device, an install marker wipes tokens that survived a reinstall. The Capacitor plugins are optional peers: only\nthe installed ones are imported.",[682,2430,267],{"id":2431},"app",[695,2433,2435],{"className":757,"code":2434,"language":760,"meta":700,"style":700},"const { ready, loggedIn, user, session, fetch, clear } = useUserSession()\nconst { status, authenticated, signingIn, login, completeLogin, logout, getAccessToken, isCallbackUrl, claims, getClient } = useAuth()\nconst { data } = await useApi\u003CBill[]>('\u002Fapi\u002Fbills') \u002F\u002F client only (`server: false`) by default\nconst me = await useNuxtApp().$api\u003CMe>('\u002Fapi\u002Fme')\n",[633,2436,2437,2479,2540,2579],{"__ignoreMap":700},[704,2438,2439,2441,2443,2446,2448,2451,2453,2456,2458,2461,2463,2466,2468,2471,2473,2475,2477],{"class":706,"line":707},[704,2440,1161],{"class":1139},[704,2442,981],{"class":782},[704,2444,2445],{"class":778}," ready",[704,2447,805],{"class":782},[704,2449,2450],{"class":778}," loggedIn",[704,2452,805],{"class":782},[704,2454,2455],{"class":778}," user",[704,2457,805],{"class":782},[704,2459,2460],{"class":778}," session",[704,2462,805],{"class":782},[704,2464,2465],{"class":778}," fetch",[704,2467,805],{"class":782},[704,2469,2470],{"class":778}," clear ",[704,2472,1059],{"class":782},[704,2474,1171],{"class":782},[704,2476,1174],{"class":774},[704,2478,1177],{"class":778},[704,2480,2481,2483,2485,2488,2490,2492,2494,2497,2499,2502,2504,2507,2509,2512,2514,2517,2519,2522,2524,2527,2529,2532,2534,2536,2538],{"class":706,"line":724},[704,2482,1161],{"class":1139},[704,2484,981],{"class":782},[704,2486,2487],{"class":778}," status",[704,2489,805],{"class":782},[704,2491,1039],{"class":778},[704,2493,805],{"class":782},[704,2495,2496],{"class":778}," signingIn",[704,2498,805],{"class":782},[704,2500,2501],{"class":778}," login",[704,2503,805],{"class":782},[704,2505,2506],{"class":778}," completeLogin",[704,2508,805],{"class":782},[704,2510,2511],{"class":778}," logout",[704,2513,805],{"class":782},[704,2515,2516],{"class":778}," getAccessToken",[704,2518,805],{"class":782},[704,2520,2521],{"class":778}," isCallbackUrl",[704,2523,805],{"class":782},[704,2525,2526],{"class":778}," claims",[704,2528,805],{"class":782},[704,2530,2531],{"class":778}," getClient ",[704,2533,1059],{"class":782},[704,2535,1171],{"class":782},[704,2537,1193],{"class":774},[704,2539,1177],{"class":778},[704,2541,2542,2544,2546,2549,2551,2553,2555,2557,2559,2561,2563,2565,2567,2569,2571,2573,2576],{"class":706,"line":731},[704,2543,1161],{"class":1139},[704,2545,981],{"class":782},[704,2547,2548],{"class":778}," data ",[704,2550,1059],{"class":782},[704,2552,1171],{"class":782},[704,2554,1216],{"class":767},[704,2556,1219],{"class":774},[704,2558,1133],{"class":782},[704,2560,1224],{"class":710},[704,2562,1227],{"class":778},[704,2564,1230],{"class":782},[704,2566,779],{"class":778},[704,2568,798],{"class":782},[704,2570,1237],{"class":714},[704,2572,798],{"class":782},[704,2574,2575],{"class":778},") ",[704,2577,2578],{"class":727},"\u002F\u002F client only (`server: false`) by default\n",[704,2580,2581,2583,2586,2588,2590,2593,2596,2598,2600,2602,2605,2607,2609,2611,2614,2616],{"class":706,"line":841},[704,2582,1161],{"class":1139},[704,2584,2585],{"class":778}," me ",[704,2587,1146],{"class":782},[704,2589,1216],{"class":767},[704,2591,2592],{"class":774}," useNuxtApp",[704,2594,2595],{"class":778},"()",[704,2597,615],{"class":782},[704,2599,1491],{"class":774},[704,2601,1133],{"class":782},[704,2603,2604],{"class":710},"Me",[704,2606,1230],{"class":782},[704,2608,779],{"class":778},[704,2610,798],{"class":782},[704,2612,2613],{"class":714},"\u002Fapi\u002Fme",[704,2615,798],{"class":782},[704,2617,1062],{"class":778},[1276,2619,2620,2630],{},[1279,2621,2622],{},[1282,2623,2624,2627],{},[1285,2625,2626],{},"Name",[1285,2628,2629],{},"What it is",[1295,2631,2632,2642,2652,2668,2688,2704],{},[1282,2633,2634,2639],{},[1300,2635,2636],{},[633,2637,2638],{},"useUserSession()",[1300,2640,2641],{},"Who is signed in, in nuxt-auth-utils' shape.",[1282,2643,2644,2649],{},[1300,2645,2646],{},[633,2647,2648],{},"useAuth()",[1300,2650,2651],{},"The sign-in state and actions.",[1282,2653,2654,2659],{},[1300,2655,2656],{},[633,2657,2658],{},"useApi(url, options)",[1300,2660,2661,2664,2665,2667],{},[633,2662,2663],{},"useFetch"," through ",[633,2666,1491],{},", client only by default.",[1282,2669,2670,2674],{},[1300,2671,2672],{},[633,2673,1491],{},[1300,2675,2676,2679,2680,2682,2683,2685,2686,615],{},[633,2677,2678],{},"$fetch"," against ",[633,2681,1511],{},". Sends the bearer token to the ",[633,2684,2298],{}," only, and refreshes and retries once on ",[633,2687,1541],{},[1282,2689,2690,2695],{},[1300,2691,2692],{},[633,2693,2694],{},"\u003CAuthSignInButton return-to=\"\u002Fbills\" \u002F>",[1300,2696,2697,2698,2700,2701,615],{},"A sign-in button (needs ",[633,2699,664],{},"). Emits ",[633,2702,2703],{},"error",[1282,2705,2706,2712],{},[1300,2707,2708,646,2710],{},[633,2709,1262],{},[633,2711,1577],{},[1300,2713,2714,2715,2717],{},"Pages (need ",[633,2716,664],{},"). A page of your app at the same path wins.",[594,2719,2720,629,2724,2727,2728,2731,2732,2735,2736,2739,2740,2742,2743,2037,2745,2748,2749,2037,2752,2755,2756,2759],{},[626,2721,2722,615],{},[633,2723,2638],{},[633,2725,2726],{},"ready"," turns true once the stored tokens were read. ",[633,2729,2730],{},"loggedIn"," is true only when signed in\n",[626,2733,2734],{},"and"," there is a ",[633,2737,2738],{},"user"," (see ",[598,2741,1737],{"href":1736},"). ",[633,2744,2372],{},[633,2746,2747],{},"{ id, user }",", where the id belongs to the sign-in\nand survives refreshes. ",[633,2750,2751],{},"clear()",[633,2753,2754],{},"logout({ redirect: false })",", and ",[633,2757,2758],{},"openInPopup()"," throws.",[594,2761,2762,2767],{},[626,2763,2764,615],{},[633,2765,2766],{},"useUserSession().fetch()"," It maps the user again, with a fresh userinfo. It rejects when the mapping failed for a\nreason other than being offline; offline, it keeps the claims mapping.",[594,2769,2770,629,2774,2037,2777,646,2780,1367,2783,1309,2786,2789,2790,2793,2794,2797,2798,2800,2801,2804,2805,2808,2809,2812,2813,2816],{},[626,2771,2772,615],{},[633,2773,2648],{},[633,2775,2776],{},"status",[633,2778,2779],{},"unknown",[633,2781,2782],{},"signed-in",[633,2784,2785],{},"signed-out",[633,2787,2788],{},"login({ returnTo?, params? })"," starts a sign-in\nand ",[633,2791,2792],{},"completeLogin(url?)"," finishes it. ",[633,2795,2796],{},"logout({ redirect? })"," stays on the page with ",[633,2799,1753],{}," and goes to a string.\n",[633,2802,2803],{},"getAccessToken()"," refreshes when needed, and returns ",[633,2806,2807],{},"null"," when signed out or on the server. Only in client mode:\n",[633,2810,2811],{},"claims"," (the ID token claims) and ",[633,2814,2815],{},"getClient()"," (the core client).",[594,2818,2819,2824,2825,1343,2828,615],{},[626,2820,2821,2822,615],{},"Pages without ",[633,2823,664],{}," Build your own with ",[633,2826,2827],{},"useAuth().login()",[633,2829,2830],{},"completeLogin()",[594,2832,2833,2836,2837,2840,2841,2843],{},[633,2834,2835],{},"user.id"," is the issuer's ",[633,2838,2839],{},"sub",", a string. In server mode it is the local user's id. Code that runs in both modes treats\n",[633,2842,2835],{}," as opaque.",[594,2845,2846,2849,2850,2853,2854,2857,2858,2861,2862,2865,2866,615],{},[626,2847,2848],{},"Inside a native app."," The plugin completes sign-ins from the cold-start URL (",[633,2851,2852],{},"App.getLaunchUrl()",") and from\n",[633,2855,2856],{},"appUrlOpen",". Only callback URLs count: other deep links are left alone, and a link that answers no pending sign-in is\nignored. The plugin refreshes the tokens on ",[633,2859,2860],{},"resume",". A failed native sign-in goes to ",[633,2863,2864],{},"redirect.login"," with\n",[633,2867,2868],{},"?error=sign-in",[682,2870,1737],{"id":2871},"the-user",[594,2873,2874],{},"The user comes from the ID token.",[1082,2876,2877,2884,2891],{},[1085,2878,2879,2880,2883],{},"A sign-in whose response has no valid ID token fails in ",[633,2881,2882],{},"completeLogin",", and its tokens are discarded.",[1085,2885,2886,2887,2890],{},"A stored session without readable claims is signed out and fires ",[633,2888,2889],{},"auth:user-failed",". Causes are a corrupt store, or\nanother issuer or client.",[1085,2892,2893,2894,2896,2897,615],{},"So ",[633,2895,2730],{}," always means ",[633,2898,2899],{},"user !== null",[594,2901,2902],{},"By default the user is mapped from the claims only, so a cold start offline still knows who is signed in:",[695,2904,2906],{"className":757,"code":2905,"language":760,"meta":700,"style":700},"{ id: sub, sub, name, email, avatar: picture }\n",[633,2907,2908],{"__ignoreMap":700},[704,2909,2910,2913,2916,2918,2921,2923,2925,2927,2930,2932,2935,2937,2940,2942,2945],{"class":706,"line":707},[704,2911,2912],{"class":782},"{",[704,2914,2915],{"class":710}," id",[704,2917,792],{"class":782},[704,2919,2920],{"class":778}," sub",[704,2922,805],{"class":782},[704,2924,2920],{"class":778},[704,2926,805],{"class":782},[704,2928,2929],{"class":778}," name",[704,2931,805],{"class":782},[704,2933,2934],{"class":778}," email",[704,2936,805],{"class":782},[704,2938,2939],{"class":710}," avatar",[704,2941,792],{"class":782},[704,2943,2944],{"class":778}," picture",[704,2946,2947],{"class":782}," }\n",[594,2949,2950,2951,2954,2955,2958,2959,2962,2963,615],{},"Roles are not read from the token. What the user may do comes from the issuer: ",[633,2952,2953],{},"useAuthorization()"," asks its\n",[633,2956,2957],{},"GET \u002Fapi\u002Fauth\u002Fme\u002Faccess"," with the access token, and falls back to the token's ",[633,2960,2961],{},"permissions"," claim. See\n",[598,2964,183],{"href":2965},"\u002Fmodules\u002Fidentity\u002Fauthorization\u002Fclient#client-mode",[594,2967,2968,2971,2972,2974,2975,2977],{},[633,2969,2970],{},"client.userinfo: true"," merges the issuer's ",[633,2973,1759],{}," response into that. ",[633,2976,1723],{}," maps the user yourself,\nand may be async:",[695,2979,2982],{"className":757,"code":2980,"filename":2981,"language":760,"meta":700,"style":700},"import type { AuthClientUserContext } from '@frigear-nu\u002Fauth\u002Fclient-core'\n\nexport default async ({ claims, userinfo, api }: AuthClientUserContext) => ({\n  id: claims.sub,\n  name: claims.name ?? '',\n  avatar: (await userinfo()).picture as string | undefined,\n})\n","app\u002Fauth\u002Fmap-user.ts",[633,2983,2984,3011,3017,3056,3071,3093,3129],{"__ignoreMap":700},[704,2985,2986,2989,2992,2994,2997,3000,3003,3005,3008],{"class":706,"line":707},[704,2987,2988],{"class":767},"import",[704,2990,2991],{"class":767}," type",[704,2993,981],{"class":782},[704,2995,2996],{"class":778}," AuthClientUserContext",[704,2998,2999],{"class":782}," }",[704,3001,3002],{"class":767}," from",[704,3004,808],{"class":782},[704,3006,3007],{"class":714},"@frigear-nu\u002Fauth\u002Fclient-core",[704,3009,3010],{"class":782},"'\n",[704,3012,3013],{"class":706,"line":724},[704,3014,3016],{"emptyLinePlaceholder":3015},true,"\n",[704,3018,3019,3021,3023,3026,3029,3032,3034,3037,3039,3042,3045,3047,3049,3052,3054],{"class":706,"line":731},[704,3020,768],{"class":767},[704,3022,771],{"class":767},[704,3024,3025],{"class":1139}," async",[704,3027,3028],{"class":782}," ({",[704,3030,2526],{"class":3031},"sHdIc",[704,3033,805],{"class":782},[704,3035,3036],{"class":3031}," userinfo",[704,3038,805],{"class":782},[704,3040,3041],{"class":3031}," api",[704,3043,3044],{"class":782}," }:",[704,3046,2996],{"class":710},[704,3048,1888],{"class":782},[704,3050,3051],{"class":1139}," =>",[704,3053,1885],{"class":778},[704,3055,783],{"class":782},[704,3057,3058,3061,3063,3065,3067,3069],{"class":706,"line":841},[704,3059,3060],{"class":788},"  id",[704,3062,792],{"class":782},[704,3064,2526],{"class":778},[704,3066,615],{"class":782},[704,3068,2839],{"class":778},[704,3070,828],{"class":782},[704,3072,3073,3076,3078,3080,3082,3085,3088,3091],{"class":706,"line":858},[704,3074,3075],{"class":788},"  name",[704,3077,792],{"class":782},[704,3079,2526],{"class":778},[704,3081,615],{"class":782},[704,3083,3084],{"class":778},"name ",[704,3086,3087],{"class":782},"??",[704,3089,3090],{"class":782}," ''",[704,3092,828],{"class":782},[704,3094,3095,3098,3100,3102,3105,3107,3110,3112,3115,3118,3121,3124,3127],{"class":706,"line":868},[704,3096,3097],{"class":788},"  avatar",[704,3099,792],{"class":782},[704,3101,1885],{"class":778},[704,3103,3104],{"class":767},"await",[704,3106,3036],{"class":774},[704,3108,3109],{"class":778},"())",[704,3111,615],{"class":782},[704,3113,3114],{"class":778},"picture ",[704,3116,3117],{"class":767},"as",[704,3119,3120],{"class":710}," string",[704,3122,3123],{"class":782}," |",[704,3125,3126],{"class":710}," undefined",[704,3128,828],{"class":782},[704,3130,3131,3133],{"class":706,"line":885},[704,3132,1059],{"class":782},[704,3134,1062],{"class":778},[695,3136,3138],{"className":757,"code":3137,"filename":759,"language":760,"meta":700,"style":700},"authentication: { mode: 'client', client: { mapUser: '.\u002Fapp\u002Fauth\u002Fmap-user' } }\n",[633,3139,3140],{"__ignoreMap":700},[704,3141,3142,3144,3146,3148,3151,3153,3155,3157,3159,3161,3164,3166,3168,3171,3173,3175,3178,3180,3182],{"class":706,"line":707},[704,3143,1394],{"class":710},[704,3145,792],{"class":782},[704,3147,981],{"class":782},[704,3149,3150],{"class":710}," mode",[704,3152,792],{"class":782},[704,3154,808],{"class":782},[704,3156,851],{"class":714},[704,3158,798],{"class":782},[704,3160,805],{"class":782},[704,3162,3163],{"class":710}," client",[704,3165,792],{"class":782},[704,3167,981],{"class":782},[704,3169,3170],{"class":710}," mapUser",[704,3172,792],{"class":782},[704,3174,808],{"class":782},[704,3176,3177],{"class":714},".\u002Fapp\u002Fauth\u002Fmap-user",[704,3179,798],{"class":782},[704,3181,2999],{"class":782},[704,3183,2947],{"class":782},[1082,3185,3186,3195,3203,3211,3220,3223,3226,3235,3245],{},[1085,3187,3188,3191,3192,3194],{},[633,3189,3190],{},"userinfo()"," is fetched once per sign-in. It is fetched again after ",[633,3193,2766],{}," or after a refresh\nthat changed the claims.",[1085,3196,3197,3199,3200,3202],{},[633,3198,3190],{}," rejects a response whose ",[633,3201,2839],{}," is not the ID token's.",[1085,3204,3205,2037,3208,3210],{},[633,3206,3207],{},"api",[633,3209,1491],{},". It works while a restored session is mapped at startup.",[1085,3212,3213,3214,3216,3217,3219],{},"Until an async mapping finishes, ",[633,3215,2738],{}," is the claims mapping, so ",[633,3218,2730],{}," never waits on the network.",[1085,3221,3222],{},"Mapping again within one sign-in keeps the previous result until the new one lands.",[1085,3224,3225],{},"A result that arrives after a sign-out or another sign-in is dropped.",[1085,3227,3228,3229,3231,3232,3234],{},"A failure fires ",[633,3230,2889],{}," and leaves ",[633,3233,2738],{}," at the claims mapping.",[1085,3236,3237,3238,646,3241,3244],{},"A transient error is retried at the next refresh: offline, ",[633,3239,3240],{},"429",[633,3242,3243],{},"5xx",", or a mapping that takes over 15 seconds.",[1085,3246,3247,3248,3250,3251,615],{},"A ",[633,3249,1541],{}," goes through ",[633,3252,3253],{},"onUnauthorized",[594,3255,3256,3257,615],{},"What the client knows about permissions is a hint for the interface, never access control. See ",[598,3258,680],{"href":679},[682,3260,3262],{"id":3261},"guards","Guards",[594,3264,3265,3266,3268],{},"Your app chooses which pages need a user, through ",[598,3267,199],{"href":200},", as in server mode.\nNothing is protected by default.",[695,3270,3272],{"className":757,"code":3271,"filename":759,"language":760,"meta":700,"style":700},"routeRules: {\n  '\u002F**': { authenticated: true }, \u002F\u002F signed in everywhere\n  '\u002Fabout': { authenticated: false }, \u002F\u002F except here\n},\n",[633,3273,3274,3282,3307,3332],{"__ignoreMap":700},[704,3275,3276,3278,3280],{"class":706,"line":707},[704,3277,1359],{"class":710},[704,3279,792],{"class":782},[704,3281,838],{"class":782},[704,3283,3284,3287,3289,3291,3294,3296,3298,3300,3302,3304],{"class":706,"line":724},[704,3285,3286],{"class":782},"  '",[704,3288,1030],{"class":714},[704,3290,798],{"class":782},[704,3292,3293],{"class":788},": ",[704,3295,2912],{"class":782},[704,3297,1039],{"class":788},[704,3299,792],{"class":782},[704,3301,1045],{"class":1044},[704,3303,996],{"class":782},[704,3305,3306],{"class":727}," \u002F\u002F signed in everywhere\n",[704,3308,3309,3311,3314,3316,3318,3320,3322,3324,3327,3329],{"class":706,"line":731},[704,3310,3286],{"class":782},[704,3312,3313],{"class":714},"\u002Fabout",[704,3315,798],{"class":782},[704,3317,3293],{"class":788},[704,3319,2912],{"class":782},[704,3321,1039],{"class":788},[704,3323,792],{"class":782},[704,3325,3326],{"class":1044}," false",[704,3328,996],{"class":782},[704,3330,3331],{"class":727}," \u002F\u002F except here\n",[704,3333,3334],{"class":706,"line":841},[704,3335,3336],{"class":782},"},\n",[1082,3338,3339,3345,3352,3355],{},[1085,3340,3341,3344],{},[633,3342,3343],{},"definePageMeta({ authorize: false })"," opens one page.",[1085,3346,3347,3348,3351],{},"Auth's sign-in page and callback are exempt from less specific rules such as ",[633,3349,3350],{},"'\u002F**'",", without a rule of yours.",[1085,3353,3354],{},"A rule of yours for that exact path, or a more specific one, still applies.",[1085,3356,3357],{},"In client mode the rules only decide what the app shows. The API decides what is allowed.",[594,3359,3247,3360,3363,3364,3366,3367,3370,3371,3374,3375,3378,3379,3381],{},[598,3361,3362],{"href":87},"visitor"," on a guarded page is sent to the sign-in path (",[633,3365,1767],{},", by\ndefault the sign-in page) with the page in ",[633,3368,3369],{},"?redirect=",". Once signed in, they come back there. Authorization's\n",[633,3372,3373],{},"redirectTo"," changes the target. ",[633,3376,3377],{},"redirectTo: false"," shows a ",[633,3380,1541],{}," error instead.",[682,3383,234],{"id":3384},"hooks",[594,3386,3387,3388,3391],{},"Your app listens to these runtime hooks on the client with ",[633,3389,3390],{},"useNuxtApp().hook(...)",". They exist in client mode only.",[1276,3393,3394,3407],{},[1279,3395,3396],{},[1282,3397,3398,3401,3404],{},[1285,3399,3400],{},"Hook",[1285,3402,3403],{},"Payload",[1285,3405,3406],{},"When",[1295,3408,3409,3424,3439,3454],{},[1282,3410,3411,3416,3421],{},[1300,3412,3413],{},[633,3414,3415],{},"auth:signed-in",[1300,3417,3418],{},[633,3419,3420],{},"{ user, claims }",[1300,3422,3423],{},"After a sign-in completed and its user was mapped. Not when a stored session is restored.",[1282,3425,3426,3431,3436],{},[1300,3427,3428],{},[633,3429,3430],{},"auth:signed-out",[1300,3432,3433],{},[633,3434,3435],{},"{ reason }",[1300,3437,3438],{},"After the session ended.",[1282,3440,3441,3446,3451],{},[1300,3442,3443],{},[633,3444,3445],{},"auth:refresh-failed",[1300,3447,3448],{},[633,3449,3450],{},"{ error }",[1300,3452,3453],{},"A refresh failed but the session was kept (offline, server error, misconfigured client).",[1282,3455,3456,3460,3464],{},[1300,3457,3458],{},[633,3459,2889],{},[1300,3461,3462],{},[633,3463,3450],{},[1300,3465,3466],{},"The user could not be read.",[594,3468,3469,3473,3474,3477,3478,615],{},[626,3470,3471,615],{},[633,3472,3430],{}," The session ends through ",[633,3475,3476],{},"logout",", a rejected refresh token, the API refusing the tokens, or no\nidentity. A stored session cleared at startup only fires ",[633,3479,2889],{},[594,3481,3482,3486,3487,3490],{},[626,3483,3484,615],{},[633,3485,2889],{}," The causes are a stored session without identity (which is signed out), or a failed ",[633,3488,3489],{},"mapUser","\nor userinfo mapping.",[682,3492,680],{"id":3493},"security",[670,3495,3496,3499,3500,3503,3504,615],{},[626,3497,3498],{},"Guards are for the interface, not access control."," The ID token is decoded without a signature check. The stored\ntokens and the mapped user live in storage the device owner can edit. So a route rule or ",[633,3501,3502],{},"can()"," in a client-mode app\ndecides what to show, never what is allowed. Bundled pages must not contain privileged data. Every protected read and\nwrite goes to an API that checks ",[598,3505,3507],{"href":3506},"\u002Fmodules\u002Fidentity\u002Fauth\u002Fserver#protect-a-route",[633,3508,3509],{},"authorize",[594,3511,3512,3513,615],{},"Why a public application\nhas no secret is explained in ",[598,3514,81],{"href":3515},"\u002Fguide\u002Fconcepts\u002Fidentity#public-and-confidential-applications",[690,3517,3519],{"id":3518},"sign-in","Sign-in",[1082,3521,3522,3536,3542],{},[1085,3523,3524,3525,646,3528,3531,3532,3535],{},"PKCE uses S256, with ",[633,3526,3527],{},"state",[633,3529,3530],{},"nonce"," and the ",[633,3533,3534],{},"iss"," check. There is no client secret.",[1085,3537,3538,3539,3541],{},"Pending sign-ins are keyed by ",[633,3540,3527],{},". So a forged callback is ignored and never cancels a real sign-in, and two tabs\ncan sign in at once.",[1085,3543,3544,3545,3547],{},"An authorization response with a wrong ",[633,3546,3534],{}," is rejected (RFC 9207).",[690,3549,3551],{"id":3550},"tokens","Tokens",[1082,3553,3554,3573,3582,3588,3596],{},[1085,3555,3556,3559,3560,646,3562,2369,3565,646,3568,1343,3570,3572],{},[626,3557,3558],{},"ID token checks."," Auth checks ",[633,3561,3534],{},[633,3563,3564],{},"aud",[633,3566,3567],{},"azp",[633,3569,2839],{},[633,3571,3530],{},", not the device clock. A refreshed ID token\nthat fails them keeps the previous claims. The rotated tokens are always stored.",[1085,3574,3575,3578,3579,3581],{},[626,3576,3577],{},"No signature check."," The ID token comes straight from the token endpoint over TLS (OpenID Connect Core 3.1.3.7).\nResource servers must verify access tokens themselves, as ",[598,3580,241],{"href":242}," does.",[1085,3583,3584,3587],{},[626,3585,3586],{},"Refresh rotation."," One refresh runs at a time: single-flight in the page, Web Locks across tabs. The stored tokens\nare re-read under the lock, so a tab never reuses a rotated token. A refresh token that was not rotated is kept.",[1085,3589,3590,1885,3593,3595],{},[626,3591,3592],{},"Bearer tokens go to allowed origins only",[633,3594,1501],{},").",[1085,3597,3598,629,3601,646,3603,646,3606,1343,3609,3612,3613,615],{},[626,3599,3600],{},"Redirects stay on this site.",[633,3602,1803],{},[633,3604,3605],{},"redirect.afterLogin",[633,3607,3608],{},"redirect.afterLogout",[633,3610,3611],{},"logout({ redirect })","\nfollow the shared rule in ",[598,3614,3616],{"href":3615},"\u002Fmodules\u002Fidentity\u002Fauth\u002Freference#redirects","Redirects",[690,3618,3620],{"id":3619},"errors","Errors",[594,3622,3623],{},"Every request to the issuer times out after 15 seconds. Errors come in four kinds:",[1276,3625,3626,3639],{},[1279,3627,3628],{},[1282,3629,3630,3633,3636],{},[1285,3631,3632],{},"Kind",[1285,3634,3635],{},"Causes",[1285,3637,3638],{},"Effect",[1295,3640,3641,3657,3675,3700],{},[1282,3642,3643,3647,3654],{},[1300,3644,3645],{},[633,3646,2372],{},[1300,3648,3649,3650,3653],{},"An explicit ",[633,3651,3652],{},"invalid_grant"," or similar",[1300,3655,3656],{},"Signed out.",[1282,3658,3659,3664,3672],{},[1300,3660,3661],{},[633,3662,3663],{},"config",[1300,3665,3666,3669,3670],{},[633,3667,3668],{},"invalid_client",", an issuer mismatch, a bare ",[633,3671,1541],{},[1300,3673,3674],{},"Configuration problem.",[1282,3676,3677,3682,3697],{},[1300,3678,3679],{},[633,3680,3681],{},"transient",[1300,3683,3684,3685,646,3687,3689,3690,3693,3694,3696],{},"Network, timeouts, ",[633,3686,3240],{},[633,3688,3243],{},", a ",[633,3691,3692],{},"4xx"," other than ",[633,3695,1541],{}," without an OAuth error body",[1300,3698,3699],{},"The session is kept.",[1282,3701,3702,3706,3709],{},[1300,3703,3704],{},[633,3705,1636],{},[1300,3707,3708],{},"A failed sign-in",[1300,3710,3711],{},"The sign-in fails.",[690,3713,3715],{"id":3714},"client-secrets","Client secrets",[670,3717,3718,3719,646,3721,3723,3724,3727],{},"A client secret in a bundle is readable by anyone. A production build fails when\n",[633,3720,2274],{},[633,3722,2286],{}," or\n",[633,3725,3726],{},"runtimeConfig.public.authentication.client.clientSecret"," is set.",[1082,3729,3730,3739,3745],{},[1085,3731,3732,3734,3735,3738],{},[633,3733,2274],{}," is for ",[633,3736,3737],{},"nuxt dev"," against a confidential application.",[1085,3740,3741,3744],{},[633,3742,3743],{},"allowClientSecretInBundle: true"," overrides the build check, for throwaway builds.",[1085,3746,3747,3748,3751],{},"Outside development, ",[633,3749,3750],{},"clientSecret"," is not declared at all, so a runtime environment variable cannot reach the\nbundle's config.",[682,3753,3755],{"id":3754},"without-nuxt","Without Nuxt",[594,3757,3758,3759,3761,3762,3765],{},"The framework-agnostic core, ",[633,3760,3007],{},", works anywhere with ",[633,3763,3764],{},"fetch"," and WebCrypto:",[695,3767,3769],{"className":757,"code":3768,"language":760,"meta":700,"style":700},"import { createOAuthClient, webStorage } from '@frigear-nu\u002Fauth\u002Fclient-core'\n\nconst client = createOAuthClient({\n  issuer: 'https:\u002F\u002Ffrigear.nu',\n  clientId: 'my-app',\n  redirectUri: `${location.origin}\u002Fcallback`,\n  scope: 'openid offline_access',\n  storage: webStorage(),\n  attachTo: ['https:\u002F\u002Fapi.example.com'],\n})\nawait client.authorize() \u002F\u002F redirects\n\u002F\u002F on \u002Fcallback:\nconst { returnTo } = await client.handleCallback(location.href)\nconst response = await client.fetch('https:\u002F\u002Fapi.example.com\u002Fme')\n",[633,3770,3771,3795,3799,3814,3829,3844,3872,3888,3901,3920,3926,3942,3947,3977],{"__ignoreMap":700},[704,3772,3773,3775,3777,3780,3782,3785,3787,3789,3791,3793],{"class":706,"line":707},[704,3774,2988],{"class":767},[704,3776,981],{"class":782},[704,3778,3779],{"class":778}," createOAuthClient",[704,3781,805],{"class":782},[704,3783,3784],{"class":778}," webStorage",[704,3786,2999],{"class":782},[704,3788,3002],{"class":767},[704,3790,808],{"class":782},[704,3792,3007],{"class":714},[704,3794,3010],{"class":782},[704,3796,3797],{"class":706,"line":724},[704,3798,3016],{"emptyLinePlaceholder":3015},[704,3800,3801,3803,3806,3808,3810,3812],{"class":706,"line":731},[704,3802,1161],{"class":1139},[704,3804,3805],{"class":778}," client ",[704,3807,1146],{"class":782},[704,3809,3779],{"class":774},[704,3811,779],{"class":778},[704,3813,783],{"class":782},[704,3815,3816,3819,3821,3823,3825,3827],{"class":706,"line":841},[704,3817,3818],{"class":788},"  issuer",[704,3820,792],{"class":782},[704,3822,808],{"class":782},[704,3824,878],{"class":714},[704,3826,798],{"class":782},[704,3828,828],{"class":782},[704,3830,3831,3834,3836,3838,3840,3842],{"class":706,"line":858},[704,3832,3833],{"class":788},"  clientId",[704,3835,792],{"class":782},[704,3837,808],{"class":782},[704,3839,895],{"class":714},[704,3841,798],{"class":782},[704,3843,828],{"class":782},[704,3845,3846,3849,3851,3854,3857,3859,3862,3864,3867,3870],{"class":706,"line":868},[704,3847,3848],{"class":788},"  redirectUri",[704,3850,792],{"class":782},[704,3852,3853],{"class":782}," `${",[704,3855,3856],{"class":778},"location",[704,3858,615],{"class":782},[704,3860,3861],{"class":778},"origin",[704,3863,1059],{"class":782},[704,3865,3866],{"class":714},"\u002Fcallback",[704,3868,3869],{"class":782},"`",[704,3871,828],{"class":782},[704,3873,3874,3877,3879,3881,3884,3886],{"class":706,"line":885},[704,3875,3876],{"class":788},"  scope",[704,3878,792],{"class":782},[704,3880,808],{"class":782},[704,3882,3883],{"class":714},"openid offline_access",[704,3885,798],{"class":782},[704,3887,828],{"class":782},[704,3889,3890,3893,3895,3897,3899],{"class":706,"line":902},[704,3891,3892],{"class":788},"  storage",[704,3894,792],{"class":782},[704,3896,3784],{"class":774},[704,3898,2595],{"class":778},[704,3900,828],{"class":782},[704,3902,3903,3906,3908,3910,3912,3914,3916,3918],{"class":706,"line":953},[704,3904,3905],{"class":788},"  attachTo",[704,3907,792],{"class":782},[704,3909,795],{"class":778},[704,3911,798],{"class":782},[704,3913,963],{"class":714},[704,3915,798],{"class":782},[704,3917,825],{"class":778},[704,3919,828],{"class":782},[704,3921,3922,3924],{"class":706,"line":973},[704,3923,1059],{"class":782},[704,3925,1062],{"class":778},[704,3927,3928,3930,3932,3934,3936,3939],{"class":706,"line":1002},[704,3929,3104],{"class":767},[704,3931,3163],{"class":778},[704,3933,615],{"class":782},[704,3935,3509],{"class":774},[704,3937,3938],{"class":778},"() ",[704,3940,3941],{"class":727},"\u002F\u002F redirects\n",[704,3943,3944],{"class":706,"line":1008},[704,3945,3946],{"class":727},"\u002F\u002F on \u002Fcallback:\n",[704,3948,3949,3951,3953,3956,3958,3960,3962,3964,3966,3969,3972,3974],{"class":706,"line":1014},[704,3950,1161],{"class":1139},[704,3952,981],{"class":782},[704,3954,3955],{"class":778}," returnTo ",[704,3957,1059],{"class":782},[704,3959,1171],{"class":782},[704,3961,1216],{"class":767},[704,3963,3163],{"class":778},[704,3965,615],{"class":782},[704,3967,3968],{"class":774},"handleCallback",[704,3970,3971],{"class":778},"(location",[704,3973,615],{"class":782},[704,3975,3976],{"class":778},"href)\n",[704,3978,3979,3981,3984,3986,3988,3990,3992,3994,3996,3998,4001,4003],{"class":706,"line":1024},[704,3980,1161],{"class":1139},[704,3982,3983],{"class":778}," response ",[704,3985,1146],{"class":782},[704,3987,1216],{"class":767},[704,3989,3163],{"class":778},[704,3991,615],{"class":782},[704,3993,3764],{"class":774},[704,3995,779],{"class":778},[704,3997,798],{"class":782},[704,3999,4000],{"class":714},"https:\u002F\u002Fapi.example.com\u002Fme",[704,4002,798],{"class":782},[704,4004,1062],{"class":778},[1276,4006,4007,4017],{},[1279,4008,4009],{},[1282,4010,4011,4014],{},[1285,4012,4013],{},"Subpath",[1285,4015,4016],{},"What it has",[1295,4018,4019,4035,4051,4073],{},[1282,4020,4021,4025],{},[1300,4022,4023],{},[633,4024,3007],{},[1300,4026,4027,4028,646,4031,4034],{},"The framework-agnostic client: ",[633,4029,4030],{},"createOAuthClient",[633,4032,4033],{},"createSignInFlow",", storages, discovery, PKCE, the errors and the types.",[1282,4036,4037,4042],{},[1300,4038,4039],{},[633,4040,4041],{},"@frigear-nu\u002Fauth\u002Fcapacitor",[1300,4043,4044,1343,4047,4050],{},[633,4045,4046],{},"createCapacitorOAuthClient",[633,4048,4049],{},"onCapacitorCallback"," for a Capacitor app without Nuxt, and the adapters.",[1282,4052,4053,4058],{},[1300,4054,4055],{},[633,4056,4057],{},"@frigear-nu\u002Fauth\u002Fclient-types",[1300,4059,4060,4061,646,4064,646,4067,646,4070,4072],{},"Types only: ",[633,4062,4063],{},"ClientModuleOptions",[633,4065,4066],{},"AuthClientPublicConfig",[633,4068,4069],{},"AuthAppConfig",[633,4071,1704],{}," and the core's types.",[1282,4074,4075,4080],{},[1300,4076,4077],{},[633,4078,4079],{},"@frigear-nu\u002Fauth\u002Fmode",[1300,4081,4082,1343,4085,4088,4089,4092],{},[633,4083,4084],{},"resolveAuthMode(nuxt)",[633,4086,4087],{},"isSafeRedirect(value)",", free of ",[633,4090,4091],{},"@nuxt\u002Fkit",", for other modules.",[1082,4094,4095,4105,4124],{},[1085,4096,4097,4098,4101,4102,615],{},"The types of ",[633,4099,4100],{},"client-core"," include ",[633,4103,4104],{},"AuthClientUserContext",[1085,4106,4107,4108,4111,4112,646,4115,646,4118,1343,4121,615],{},"The adapters of ",[633,4109,4110],{},"capacitor"," are ",[633,4113,4114],{},"secureStorage",[633,4116,4117],{},"preferencesStorage",[633,4119,4120],{},"browserUserAgent",[633,4122,4123],{},"withInstallMarker",[1085,4125,4126,1343,4128,4131,4132,4135],{},[633,4127,2400],{},[633,4129,4130],{},"AuthorizationUserAgent"," are the extension points for another secure storage, or for an\n",[633,4133,4134],{},"ASWebAuthenticationSession"," user agent.",[682,4137,4139],{"id":4138},"next-steps","Next steps",[1082,4141,4142,4147,4152],{},[1085,4143,4144,4146],{},[598,4145,457],{"href":458}," – a Capacitor app that already runs in client mode.",[1085,4148,4149,4151],{},[598,4150,241],{"href":242}," – verify the access token in the API your app calls.",[1085,4153,4154,4156],{},[598,4155,199],{"href":200}," – the guards, in both modes.",[4158,4159,4160],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}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 .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 .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":700,"searchDepth":724,"depth":724,"links":4162},[4163,4169,4170,4175,4176,4177,4178,4179,4185,4186],{"id":684,"depth":724,"text":685,"children":4164},[4165,4166,4167,4168],{"id":692,"depth":731,"text":693},{"id":750,"depth":731,"text":751},{"id":1065,"depth":731,"text":1066},{"id":1119,"depth":731,"text":1120},{"id":1270,"depth":724,"text":1271},{"id":1387,"depth":724,"text":1388,"children":4171},[4172,4173,4174],{"id":2047,"depth":731,"text":2048},{"id":2176,"depth":731,"text":2177},{"id":2305,"depth":731,"text":1716},{"id":2431,"depth":724,"text":267},{"id":2871,"depth":724,"text":1737},{"id":3261,"depth":724,"text":3262},{"id":3384,"depth":724,"text":234},{"id":3493,"depth":724,"text":680,"children":4180},[4181,4182,4183,4184],{"id":3518,"depth":731,"text":3519},{"id":3550,"depth":731,"text":3551},{"id":3619,"depth":731,"text":3620},{"id":3714,"depth":731,"text":3715},{"id":3754,"depth":724,"text":3755},{"id":4138,"depth":724,"text":4139},"Sign people in from an app without its own server, such as a browser SPA or a Capacitor app, and call your API as them.","md",null,{},{"title":183},{"title":589,"description":4187},"TRyDikmtn_FEV4TkeS8-CjeQNsvyvyC5nev46DgCkk4",[4195,4197],{"title":179,"path":180,"stem":181,"description":4196,"children":-1},"Look up Auth's composables, hooks, routes, database tables and translations.",{"title":187,"path":188,"stem":189,"description":4198,"children":-1},"Let people sign in with GitHub, Google, frigear.nu or any OpenID Connect provider, and keep their tokens to call it.",1794503145950]