[{"data":1,"prerenderedAt":2440},["ShallowReactive",2],{"navigation":3,"\u002Fapi\u002Fusers-and-security":358,"\u002Fapi\u002Fusers-and-security-surround":2435},[4,14,36,69,140,341],{"title":5,"path":6,"stem":7,"children":8},"Introduction","\u002Fgetting-started","1.getting-started\u002F1.index",[9,10],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation",{"title":15,"path":16,"stem":17,"children":18,"page":35},"Guides","\u002Fguides","2.guides",[19,23,27,31],{"title":20,"path":21,"stem":22},"Your First Layout","\u002Fguides\u002Fyour-first-layout","2.guides\u002F1.your-first-layout",{"title":24,"path":25,"stem":26},"Your First Page Template","\u002Fguides\u002Fyour-first-page-template","2.guides\u002F2.your-first-page-template",{"title":28,"path":29,"stem":30},"Your First Component","\u002Fguides\u002Fyour-first-component","2.guides\u002F3.your-first-component",{"title":32,"path":33,"stem":34},"Alternative UI Variants","\u002Fguides\u002Falternative-ui-variants","2.guides\u002F4.alternative-ui-variants",false,{"title":37,"path":38,"stem":39,"children":40,"page":35},"Core Concepts","\u002Fcore-concepts","3.core-concepts",[41,45,49,53,57,61,65],{"title":42,"path":43,"stem":44},"How It All Works","\u002Fcore-concepts\u002Farchitecture","3.core-concepts\u002F1.architecture",{"title":46,"path":47,"stem":48},"The Data Model","\u002Fcore-concepts\u002Fthe-data-model","3.core-concepts\u002F2.the-data-model",{"title":50,"path":51,"stem":52},"Layouts & Pages","\u002Fcore-concepts\u002Flayouts-and-pages","3.core-concepts\u002F3.layouts-and-pages",{"title":54,"path":55,"stem":56},"Dynamic Pages","\u002Fcore-concepts\u002Fdynamic-pages","3.core-concepts\u002F4.dynamic-pages",{"title":58,"path":59,"stem":60},"Components","\u002Fcore-concepts\u002Fcomponents","3.core-concepts\u002F5.components",{"title":62,"path":63,"stem":64},"Draft & Publish Workflow","\u002Fcore-concepts\u002Fdraft-and-publish","3.core-concepts\u002F6.draft-and-publish",{"title":66,"path":67,"stem":68},"The Admin Panel","\u002Fcore-concepts\u002Fadmin-panel","3.core-concepts\u002F7.admin-panel",{"title":70,"path":71,"stem":72,"children":73,"page":35},"Api","\u002Fapi","4.api",[74,78,116,120,124,128,132,136],{"title":75,"path":76,"stem":77},"Bundle Setup","\u002Fapi\u002Fbundle-setup","4.api\u002F1.bundle-setup",{"title":58,"path":79,"stem":80,"children":81,"page":35},"\u002Fapi\u002Fcomponents","4.api\u002F2.components",[82,86,103],{"title":83,"path":84,"stem":85},"Creating Components","\u002Fapi\u002Fcomponents\u002Fcreating-components","4.api\u002F2.components\u002F1.creating-components",{"title":87,"path":88,"stem":89,"children":90,"page":35},"Annotations","\u002Fapi\u002Fcomponents\u002Fannotations","4.api\u002F2.components\u002F2.annotations",[91,95,99],{"title":92,"path":93,"stem":94},"Publishable","\u002Fapi\u002Fcomponents\u002Fannotations\u002Fpublishable","4.api\u002F2.components\u002F2.annotations\u002F1.publishable",{"title":96,"path":97,"stem":98},"Uploadable","\u002Fapi\u002Fcomponents\u002Fannotations\u002Fuploadable","4.api\u002F2.components\u002F2.annotations\u002F2.uploadable",{"title":100,"path":101,"stem":102},"Timestamped","\u002Fapi\u002Fcomponents\u002Fannotations\u002Ftimestamped","4.api\u002F2.components\u002F2.annotations\u002F3.timestamped",{"title":104,"path":105,"stem":106,"children":107,"page":35},"Built Ins","\u002Fapi\u002Fcomponents\u002Fbuilt-ins","4.api\u002F2.components\u002F3.built-ins",[108,112],{"title":109,"path":110,"stem":111},"Collection Component","\u002Fapi\u002Fcomponents\u002Fbuilt-ins\u002Fcollection-component","4.api\u002F2.components\u002F3.built-ins\u002F1.collection-component",{"title":113,"path":114,"stem":115},"Form Component","\u002Fapi\u002Fcomponents\u002Fbuilt-ins\u002Fform-component","4.api\u002F2.components\u002F3.built-ins\u002F2.form-component",{"title":117,"path":118,"stem":119},"Dynamic & Nested Pages","\u002Fapi\u002Fdynamic-pages","4.api\u002F3.dynamic-pages",{"title":121,"path":122,"stem":123},"Users & Security","\u002Fapi\u002Fusers-and-security","4.api\u002F4.users-and-security",{"title":125,"path":126,"stem":127},"Data Fixtures","\u002Fapi\u002Fdata-fixtures","4.api\u002F5.data-fixtures",{"title":129,"path":130,"stem":131},"Configuration Reference","\u002Fapi\u002Fconfiguration","4.api\u002F6.configuration",{"title":133,"path":134,"stem":135},"Console Commands","\u002Fapi\u002Fconsole-commands","4.api\u002F7.console-commands",{"title":137,"path":138,"stem":139},"Debugging & Profiler","\u002Fapi\u002Fdebugging","4.api\u002F8.debugging",{"title":141,"path":142,"stem":143,"children":144,"page":35},"Nuxt Module","\u002Fnuxt-module","5.nuxt-module",[145,149,162,182,207,211,295,320,324],{"title":146,"path":147,"stem":148},"Module Setup","\u002Fnuxt-module\u002Fmodule-setup","5.nuxt-module\u002F1.module-setup",{"title":150,"path":151,"stem":152,"children":153,"page":35},"Configuration","\u002Fnuxt-module\u002Fconfiguration","5.nuxt-module\u002F2.configuration",[154,158],{"title":155,"path":156,"stem":157},"Nuxt Config","\u002Fnuxt-module\u002Fconfiguration\u002Fnuxt-config","5.nuxt-module\u002F2.configuration\u002F1.nuxt-config",{"title":159,"path":160,"stem":161},"Site Config & SEO","\u002Fnuxt-module\u002Fconfiguration\u002Fsite-config-and-seo","5.nuxt-module\u002F2.configuration\u002F2.site-config-and-seo",{"title":163,"path":164,"stem":165,"children":166,"page":35},"Building Your Ui","\u002Fnuxt-module\u002Fbuilding-your-ui","5.nuxt-module\u002F3.building-your-ui",[167,171,175,178],{"title":168,"path":169,"stem":170},"Layouts","\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcreating-layouts","5.nuxt-module\u002F3.building-your-ui\u002F1.creating-layouts",{"title":172,"path":173,"stem":174},"Page Templates","\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcreating-page-templates","5.nuxt-module\u002F3.building-your-ui\u002F2.creating-page-templates",{"title":83,"path":176,"stem":177},"\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcreating-components","5.nuxt-module\u002F3.building-your-ui\u002F3.creating-components",{"title":179,"path":180,"stem":181},"CLI Generator","\u002Fnuxt-module\u002Fbuilding-your-ui\u002Fcwa-cli","5.nuxt-module\u002F3.building-your-ui\u002F4.cwa-cli",{"title":183,"path":184,"stem":185,"children":186,"page":35},"Cwa Components","\u002Fnuxt-module\u002Fcwa-components","5.nuxt-module\u002F4.cwa-components",[187,191,195,199,203],{"title":188,"path":189,"stem":190},"\u003CCwaComponentGroup \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-component-group","5.nuxt-module\u002F4.cwa-components\u002F1.cwa-component-group",{"title":192,"path":193,"stem":194},"\u003CCwaPage \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-page","5.nuxt-module\u002F4.cwa-components\u002F2.cwa-page",{"title":196,"path":197,"stem":198},"\u003CCwaLink \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-link","5.nuxt-module\u002F4.cwa-components\u002F3.cwa-link",{"title":200,"path":201,"stem":202},"\u003CCwaImage \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-image","5.nuxt-module\u002F4.cwa-components\u002F4.cwa-image",{"title":204,"path":205,"stem":206},"\u003CCwaDefaultLayout \u002F>","\u002Fnuxt-module\u002Fcwa-components\u002Fcwa-default-layout","5.nuxt-module\u002F4.cwa-components\u002F5.cwa-default-layout",{"title":208,"path":209,"stem":210},"The useCwa() API","\u002Fnuxt-module\u002Fcwa-api","5.nuxt-module\u002F5.cwa-api",{"title":212,"path":213,"stem":214,"children":215,"page":35},"Composables","\u002Fnuxt-module\u002Fcomposables","5.nuxt-module\u002F6.composables",[216,224,261,278],{"title":217,"path":218,"stem":219,"children":220,"page":35},"Layout","\u002Fnuxt-module\u002Fcomposables\u002Flayout","5.nuxt-module\u002F6.composables\u002F0.layout",[221],{"title":217,"path":222,"stem":223},"\u002Fnuxt-module\u002Fcomposables\u002Flayout\u002Fuse-cwa-layout","5.nuxt-module\u002F6.composables\u002F0.layout\u002F1.use-cwa-layout",{"title":225,"path":226,"stem":227,"children":228,"page":35},"Component","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent","5.nuxt-module\u002F6.composables\u002F1.component",[229,233,237,241,245,249,253,257],{"title":230,"path":231,"stem":232},"Component (recommended)","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-component","5.nuxt-module\u002F6.composables\u002F1.component\u002F0.use-cwa-component",{"title":234,"path":235,"stem":236},"Resource","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-resource","5.nuxt-module\u002F6.composables\u002F1.component\u002F1.use-cwa-resource",{"title":238,"path":239,"stem":240},"Collection Resource","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-collection-resource","5.nuxt-module\u002F6.composables\u002F1.component\u002F2.use-cwa-collection-resource",{"title":242,"path":243,"stem":244},"Image Resource","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-image-resource","5.nuxt-module\u002F6.composables\u002F1.component\u002F3.use-cwa-image-resource",{"title":246,"path":247,"stem":248},"Form","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form","5.nuxt-module\u002F6.composables\u002F1.component\u002F4.use-cwa-form",{"title":250,"path":251,"stem":252},"Form Input","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form-input","5.nuxt-module\u002F6.composables\u002F1.component\u002F5.use-cwa-form-input",{"title":254,"path":255,"stem":256},"Form Repeated","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form-repeated","5.nuxt-module\u002F6.composables\u002F1.component\u002F6.use-cwa-form-repeated",{"title":258,"path":259,"stem":260},"Form Collection","\u002Fnuxt-module\u002Fcomposables\u002Fcomponent\u002Fuse-cwa-form-collection","5.nuxt-module\u002F6.composables\u002F1.component\u002F7.use-cwa-form-collection",{"title":262,"path":263,"stem":264,"children":265,"page":35},"Admin Manager","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager","5.nuxt-module\u002F6.composables\u002F2.admin-manager",[266,270,274],{"title":267,"path":268,"stem":269},"Manager Tab","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager\u002Fuse-cwa-resource-manager-tab","5.nuxt-module\u002F6.composables\u002F2.admin-manager\u002F1.use-cwa-resource-manager-tab",{"title":271,"path":272,"stem":273},"Resource Model","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager\u002Fuse-cwa-resource-model","5.nuxt-module\u002F6.composables\u002F2.admin-manager\u002F2.use-cwa-resource-model",{"title":275,"path":276,"stem":277},"Resource Upload","\u002Fnuxt-module\u002Fcomposables\u002Fadmin-manager\u002Fuse-cwa-resource-upload","5.nuxt-module\u002F6.composables\u002F2.admin-manager\u002F3.use-cwa-resource-upload",{"title":279,"path":280,"stem":281,"children":282,"page":35},"Utilities","\u002Fnuxt-module\u002Fcomposables\u002Futilities","5.nuxt-module\u002F6.composables\u002F3.utilities",[283,287,291],{"title":284,"path":285,"stem":286},"Resource Endpoint","\u002Fnuxt-module\u002Fcomposables\u002Futilities\u002Fuse-cwa-resource-endpoint","5.nuxt-module\u002F6.composables\u002F3.utilities\u002F1.use-cwa-resource-endpoint",{"title":288,"path":289,"stem":290},"Query Model","\u002Fnuxt-module\u002Fcomposables\u002Futilities\u002Fuse-query-bound-model","5.nuxt-module\u002F6.composables\u002F3.utilities\u002F2.use-query-bound-model",{"title":292,"path":293,"stem":294},"Resource Route","\u002Fnuxt-module\u002Fcomposables\u002Futilities\u002Fuse-cwa-resource-route","5.nuxt-module\u002F6.composables\u002F3.utilities\u002F3.use-cwa-resource-route",{"title":296,"path":297,"stem":298,"children":299,"page":35},"Component Helpers","\u002Fnuxt-module\u002Fcomponent-helpers","5.nuxt-module\u002F7.component-helpers",[300,304,308,312,316],{"title":301,"path":302,"stem":303},"Images & Media","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fimages-and-uploads","5.nuxt-module\u002F7.component-helpers\u002F1.images-and-uploads",{"title":305,"path":306,"stem":307},"Collections & Pagination","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fcollections-and-pagination","5.nuxt-module\u002F7.component-helpers\u002F2.collections-and-pagination",{"title":309,"path":310,"stem":311},"HTML Content","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fhtml-content","5.nuxt-module\u002F7.component-helpers\u002F3.html-content",{"title":313,"path":314,"stem":315},"Real-Time Updates","\u002Fnuxt-module\u002Fcomponent-helpers\u002Freal-time-updates","5.nuxt-module\u002F7.component-helpers\u002F4.real-time-updates",{"title":317,"path":318,"stem":319},"Forms","\u002Fnuxt-module\u002Fcomponent-helpers\u002Fforms","5.nuxt-module\u002F7.component-helpers\u002F5.forms",{"title":321,"path":322,"stem":323},"Authentication","\u002Fnuxt-module\u002Fauthentication","5.nuxt-module\u002F8.authentication",{"title":325,"path":326,"stem":327,"children":328,"page":35},"Cwa Layer","\u002Fnuxt-module\u002Fcwa-layer","5.nuxt-module\u002F9.cwa-layer",[329,333,337],{"title":330,"path":331,"stem":332},"Overview","\u002Fnuxt-module\u002Fcwa-layer\u002Foverview","5.nuxt-module\u002F9.cwa-layer\u002F1.overview",{"title":334,"path":335,"stem":336},"Auth Pages","\u002Fnuxt-module\u002Fcwa-layer\u002Fauth-pages","5.nuxt-module\u002F9.cwa-layer\u002F2.auth-pages",{"title":338,"path":339,"stem":340},"Admin Panel","\u002Fnuxt-module\u002Fcwa-layer\u002Fadmin-panel","5.nuxt-module\u002F9.cwa-layer\u002F3.admin-panel",{"title":342,"path":343,"stem":344,"children":345,"page":35},"Deployment","\u002Fdeployment","6.deployment",[346,350,354],{"title":347,"path":348,"stem":349},"Docker","\u002Fdeployment\u002Fdocker","6.deployment\u002F1.docker",{"title":351,"path":352,"stem":353},"Kubernetes & Helm","\u002Fdeployment\u002Fkubernetes","6.deployment\u002F2.kubernetes",{"title":355,"path":356,"stem":357},"CI\u002FCD","\u002Fdeployment\u002Fci-cd","6.deployment\u002F3.ci-cd",{"id":359,"title":121,"badge":360,"body":363,"description":2429,"extension":2430,"links":2431,"meta":2432,"navigation":461,"path":122,"seo":2433,"stem":123,"__hash__":2434},"docs\u002F4.api\u002F4.users-and-security.md",{"label":361,"color":362},"Draft","amber",{"type":364,"value":365,"toc":2411},"minimark",[366,375,380,402,406,416,650,655,784,799,803,806,875,882,893,898,913,917,920,1058,1062,1143,1147,1154,1544,1548,1554,1676,1683,1687,1769,1780,1784,1849,1853,1856,1993,2000,2009,2013,2016,2102,2126,2129,2159,2164,2175,2200,2214,2220,2225,2243,2246,2261,2265,2272,2278,2304,2307,2311,2324,2330,2380,2383,2407],[367,368,369,370,374],"p",{},"CWA uses cookie-based JWT authentication. The API sets a secure HttpOnly cookie on login; the Nuxt module reads auth state from the JWT payload. No ",[371,372,373],"code",{},"Authorization"," headers, no manual token storage — the browser handles it transparently.",[376,377,379],"h2",{"id":378},"the-authentication-flow","The Authentication Flow",[381,382,383,390,393,396,399],"ol",{},[384,385,386,387],"li",{},"Client sends credentials to ",[371,388,389],{},"POST \u002Flogin",[384,391,392],{},"API validates, issues a JWT and a refresh token — both as HttpOnly cookies",[384,394,395],{},"Every subsequent request sends the cookies automatically (same-origin or configured CORS)",[384,397,398],{},"When the JWT expires, the API auto-refreshes it using the refresh token cookie",[384,400,401],{},"The client never sees or stores the raw token values",[376,403,405],{"id":404},"abstractuser","AbstractUser",[367,407,408,409,412,413,415],{},"Your ",[371,410,411],{},"User"," entity (created by the Flex recipe) extends ",[371,414,405],{},":",[417,418,423],"pre",{"className":419,"code":420,"language":421,"meta":422,"style":422},"language-php shiki shiki-themes github-light github-dark material-theme-palenight","\u002F\u002F src\u002FEntity\u002FUser.php\nnamespace App\\Entity;\n\nuse ApiPlatform\\Metadata\\ApiResource;\nuse Doctrine\\ORM\\Mapping as ORM;\nuse Silverback\\ApiComponentsBundle\\Annotation as Silverback;\nuse Silverback\\ApiComponentsBundle\\Entity\\User\\AbstractUser;\n\n#[ORM\\Entity]\n#[ApiResource(\n    operations: [\u002F* restrict to ROLE_SUPER_ADMIN *\u002F]\n)]\nclass User extends AbstractUser\n{\n    \u002F\u002F Add custom fields here\n}\n","php","",[371,424,425,434,456,463,486,512,536,561,566,582,592,608,616,632,638,644],{"__ignoreMap":422},[426,427,430],"span",{"class":428,"line":429},"line",1,[426,431,433],{"class":432},"sTBSN","\u002F\u002F src\u002FEntity\u002FUser.php\n",[426,435,437,441,445,449,452],{"class":428,"line":436},2,[426,438,440],{"class":439},"stmX-","namespace",[426,442,444],{"class":443},"sRCss"," App",[426,446,448],{"class":447},"sn4go","\\",[426,450,451],{"class":443},"Entity",[426,453,455],{"class":454},"sOvfz",";\n",[426,457,459],{"class":428,"line":458},3,[426,460,462],{"emptyLinePlaceholder":461},true,"\n",[426,464,466,469,473,476,479,481,484],{"class":428,"line":465},4,[426,467,468],{"class":439},"use",[426,470,472],{"class":471},"sc2zw"," ApiPlatform",[426,474,448],{"class":475},"sBtbT",[426,477,478],{"class":471},"Metadata",[426,480,448],{"class":475},[426,482,483],{"class":471},"ApiResource",[426,485,455],{"class":454},[426,487,489,491,494,496,499,501,504,507,510],{"class":428,"line":488},5,[426,490,468],{"class":439},[426,492,493],{"class":471}," Doctrine",[426,495,448],{"class":475},[426,497,498],{"class":471},"ORM",[426,500,448],{"class":475},[426,502,503],{"class":471},"Mapping",[426,505,506],{"class":439}," as",[426,508,509],{"class":443}," ORM",[426,511,455],{"class":454},[426,513,515,517,520,522,525,527,530,532,534],{"class":428,"line":514},6,[426,516,468],{"class":439},[426,518,519],{"class":471}," Silverback",[426,521,448],{"class":475},[426,523,524],{"class":471},"ApiComponentsBundle",[426,526,448],{"class":475},[426,528,529],{"class":471},"Annotation",[426,531,506],{"class":439},[426,533,519],{"class":443},[426,535,455],{"class":454},[426,537,539,541,543,545,547,549,551,553,555,557,559],{"class":428,"line":538},7,[426,540,468],{"class":439},[426,542,519],{"class":471},[426,544,448],{"class":475},[426,546,524],{"class":471},[426,548,448],{"class":475},[426,550,451],{"class":471},[426,552,448],{"class":475},[426,554,411],{"class":471},[426,556,448],{"class":475},[426,558,405],{"class":471},[426,560,455],{"class":454},[426,562,564],{"class":428,"line":563},8,[426,565,462],{"emptyLinePlaceholder":461},[426,567,569,573,575,577,579],{"class":428,"line":568},9,[426,570,572],{"class":571},"sPB8G","#[",[426,574,498],{"class":471},[426,576,448],{"class":475},[426,578,451],{"class":471},[426,580,581],{"class":571},"]\n",[426,583,585,587,589],{"class":428,"line":584},10,[426,586,572],{"class":571},[426,588,483],{"class":471},[426,590,591],{"class":454},"(\n",[426,593,595,598,600,603,606],{"class":428,"line":594},11,[426,596,597],{"class":443},"    operations",[426,599,415],{"class":454},[426,601,602],{"class":454}," [",[426,604,605],{"class":432},"\u002F* restrict to ROLE_SUPER_ADMIN *\u002F",[426,607,581],{"class":454},[426,609,611,614],{"class":428,"line":610},12,[426,612,613],{"class":454},")",[426,615,581],{"class":571},[426,617,619,623,626,629],{"class":428,"line":618},13,[426,620,622],{"class":621},"swB56","class",[426,624,625],{"class":443}," User",[426,627,628],{"class":621}," extends",[426,630,631],{"class":443}," AbstractUser\n",[426,633,635],{"class":428,"line":634},14,[426,636,637],{"class":454},"{\n",[426,639,641],{"class":428,"line":640},15,[426,642,643],{"class":432},"    \u002F\u002F Add custom fields here\n",[426,645,647],{"class":428,"line":646},16,[426,648,649],{"class":454},"}\n",[651,652,654],"h3",{"id":653},"what-abstractuser-provides","What AbstractUser Provides",[656,657,658,674],"table",{},[659,660,661],"thead",{},[662,663,664,668,671],"tr",{},[665,666,667],"th",{},"Field",[665,669,670],{},"Serialization group",[665,672,673],{},"Notes",[675,676,677,693,707,726,740,756,770],"tbody",{},[662,678,679,685,690],{},[680,681,682],"td",{},[371,683,684],{},"username",[680,686,687],{},[371,688,689],{},"User:output",[680,691,692],{},"Used as login identifier",[662,694,695,700,704],{},[680,696,697],{},[371,698,699],{},"emailAddress",[680,701,702],{},[371,703,689],{},[680,705,706],{},"Unique; separate from username",[662,708,709,714,719],{},[680,710,711],{},[371,712,713],{},"roles",[680,715,716],{},[371,717,718],{},"User:superAdmin",[680,720,721,722,725],{},"Array; ",[371,723,724],{},"ROLE_USER"," always included",[662,727,728,733,737],{},[680,729,730],{},[371,731,732],{},"enabled",[680,734,735],{},[371,736,718],{},[680,738,739],{},"Disabled users cannot log in",[662,741,742,747,753],{},[680,743,744],{},[371,745,746],{},"plainPassword",[680,748,749,752],{},[371,750,751],{},"User:input"," (write-only)",[680,754,755],{},"Hashed before persist",[662,757,758,763,767],{},[680,759,760],{},[371,761,762],{},"emailAddressVerified",[680,764,765],{},[371,766,689],{},[680,768,769],{},"Set by email verification flow",[662,771,772,777,781],{},[680,773,774],{},[371,775,776],{},"newEmailAddress",[680,778,779],{},[371,780,689],{},[680,782,783],{},"Pending email change",[367,785,786,790,791,794,795,798],{},[787,788,789],"strong",{},"Passwords"," are never serialized to output — ",[371,792,793],{},"readable: false"," is set on the hashed ",[371,796,797],{},"password"," field.",[376,800,802],{"id":801},"generating-jwt-keys","Generating JWT Keys",[367,804,805],{},"One-time setup per environment:",[417,807,811],{"className":808,"code":809,"language":810,"meta":422,"style":422},"language-bash shiki shiki-themes github-light github-dark material-theme-palenight","mkdir -p config\u002Fjwt\nopenssl genpkey -out config\u002Fjwt\u002Fprivate.pem -aes256 -algorithm rsa -pkeyopt rsa_keygen_bits:4096\nopenssl pkey -in config\u002Fjwt\u002Fprivate.pem -out config\u002Fjwt\u002Fpublic.pem -pubout\n","bash",[371,812,813,826,855],{"__ignoreMap":422},[426,814,815,818,822],{"class":428,"line":429},[426,816,817],{"class":443},"mkdir",[426,819,821],{"class":820},"szhYu"," -p",[426,823,825],{"class":824},"sLL54"," config\u002Fjwt\n",[426,827,828,831,834,837,840,843,846,849,852],{"class":428,"line":436},[426,829,830],{"class":443},"openssl",[426,832,833],{"class":824}," genpkey",[426,835,836],{"class":820}," -out",[426,838,839],{"class":824}," config\u002Fjwt\u002Fprivate.pem",[426,841,842],{"class":820}," -aes256",[426,844,845],{"class":820}," -algorithm",[426,847,848],{"class":824}," rsa",[426,850,851],{"class":820}," -pkeyopt",[426,853,854],{"class":824}," rsa_keygen_bits:4096\n",[426,856,857,859,862,865,867,869,872],{"class":428,"line":458},[426,858,830],{"class":443},[426,860,861],{"class":824}," pkey",[426,863,864],{"class":820}," -in",[426,866,839],{"class":824},[426,868,836],{"class":820},[426,870,871],{"class":824}," config\u002Fjwt\u002Fpublic.pem",[426,873,874],{"class":820}," -pubout\n",[367,876,877,878,881],{},"Add to ",[371,879,880],{},".env.local"," (never commit):",[417,883,887],{"className":884,"code":885,"language":886,"meta":422,"style":422},"language-ini shiki shiki-themes github-light github-dark material-theme-palenight","JWT_PASSPHRASE=your_secure_passphrase\n","ini",[371,888,889],{"__ignoreMap":422},[426,890,891],{"class":428,"line":429},[426,892,885],{},[367,894,877,895,415],{},[371,896,897],{},".env",[417,899,901],{"className":884,"code":900,"language":886,"meta":422,"style":422},"JWT_SECRET_KEY=%kernel.project_dir%\u002Fconfig\u002Fjwt\u002Fprivate.pem\nJWT_PUBLIC_KEY=%kernel.project_dir%\u002Fconfig\u002Fjwt\u002Fpublic.pem\n",[371,902,903,908],{"__ignoreMap":422},[426,904,905],{"class":428,"line":429},[426,906,907],{},"JWT_SECRET_KEY=%kernel.project_dir%\u002Fconfig\u002Fjwt\u002Fprivate.pem\n",[426,909,910],{"class":428,"line":436},[426,911,912],{},"JWT_PUBLIC_KEY=%kernel.project_dir%\u002Fconfig\u002Fjwt\u002Fpublic.pem\n",[376,914,916],{"id":915},"lexik_jwt_authentication-configuration","lexik_jwt_authentication Configuration",[367,918,919],{},"The JWT cookie name must match the refresh token cookie name in the bundle config:",[417,921,925],{"className":922,"code":923,"language":924,"meta":422,"style":422},"language-yaml shiki shiki-themes github-light github-dark material-theme-palenight","# config\u002Fpackages\u002Flexik_jwt_authentication.yaml\nlexik_jwt_authentication:\n    secret_key: '%env(resolve:JWT_SECRET_KEY)%'\n    public_key: '%env(resolve:JWT_PUBLIC_KEY)%'\n    pass_phrase: '%env(JWT_PASSPHRASE)%'\n    token_ttl: 3600\n    set_cookies:\n        api_components:\n            lifetime: 604800  # 1 week\n            samesite: '%env(JWT_COOKIE_SAMESITE)%'\n            secure: true\n            httpOnly: true\n","yaml",[371,926,927,932,941,958,972,986,997,1004,1011,1024,1038,1049],{"__ignoreMap":422},[426,928,929],{"class":428,"line":429},[426,930,931],{"class":432},"# config\u002Fpackages\u002Flexik_jwt_authentication.yaml\n",[426,933,934,938],{"class":428,"line":436},[426,935,937],{"class":936},"s-h7I","lexik_jwt_authentication",[426,939,940],{"class":454},":\n",[426,942,943,946,948,952,955],{"class":428,"line":458},[426,944,945],{"class":936},"    secret_key",[426,947,415],{"class":454},[426,949,951],{"class":950},"seSrl"," '",[426,953,954],{"class":824},"%env(resolve:JWT_SECRET_KEY)%",[426,956,957],{"class":950},"'\n",[426,959,960,963,965,967,970],{"class":428,"line":465},[426,961,962],{"class":936},"    public_key",[426,964,415],{"class":454},[426,966,951],{"class":950},[426,968,969],{"class":824},"%env(resolve:JWT_PUBLIC_KEY)%",[426,971,957],{"class":950},[426,973,974,977,979,981,984],{"class":428,"line":488},[426,975,976],{"class":936},"    pass_phrase",[426,978,415],{"class":454},[426,980,951],{"class":950},[426,982,983],{"class":824},"%env(JWT_PASSPHRASE)%",[426,985,957],{"class":950},[426,987,988,991,993],{"class":428,"line":514},[426,989,990],{"class":936},"    token_ttl",[426,992,415],{"class":454},[426,994,996],{"class":995},"scSvc"," 3600\n",[426,998,999,1002],{"class":428,"line":538},[426,1000,1001],{"class":936},"    set_cookies",[426,1003,940],{"class":454},[426,1005,1006,1009],{"class":428,"line":563},[426,1007,1008],{"class":936},"        api_components",[426,1010,940],{"class":454},[426,1012,1013,1016,1018,1021],{"class":428,"line":568},[426,1014,1015],{"class":936},"            lifetime",[426,1017,415],{"class":454},[426,1019,1020],{"class":995}," 604800",[426,1022,1023],{"class":432},"  # 1 week\n",[426,1025,1026,1029,1031,1033,1036],{"class":428,"line":584},[426,1027,1028],{"class":936},"            samesite",[426,1030,415],{"class":454},[426,1032,951],{"class":950},[426,1034,1035],{"class":824},"%env(JWT_COOKIE_SAMESITE)%",[426,1037,957],{"class":950},[426,1039,1040,1043,1045],{"class":428,"line":594},[426,1041,1042],{"class":936},"            secure",[426,1044,415],{"class":454},[426,1046,1048],{"class":1047},"swWMF"," true\n",[426,1050,1051,1054,1056],{"class":428,"line":610},[426,1052,1053],{"class":936},"            httpOnly",[426,1055,415],{"class":454},[426,1057,1048],{"class":1047},[376,1059,1061],{"id":1060},"refresh-token-configuration","Refresh Token Configuration",[417,1063,1065],{"className":922,"code":1064,"language":924,"meta":422,"style":422},"silverback_api_components:\n    refresh_token:\n        handler_id: silverback.api_components.refresh_token.storage.doctrine\n        options:\n            class: App\\Entity\\RefreshToken\n        cookie_name: api_components   # must match lexik_jwt cookie name\n        ttl: 604800                   # 1 week\n        database_user_provider: database\n",[371,1066,1067,1074,1081,1091,1098,1108,1121,1133],{"__ignoreMap":422},[426,1068,1069,1072],{"class":428,"line":429},[426,1070,1071],{"class":936},"silverback_api_components",[426,1073,940],{"class":454},[426,1075,1076,1079],{"class":428,"line":436},[426,1077,1078],{"class":936},"    refresh_token",[426,1080,940],{"class":454},[426,1082,1083,1086,1088],{"class":428,"line":458},[426,1084,1085],{"class":936},"        handler_id",[426,1087,415],{"class":454},[426,1089,1090],{"class":824}," silverback.api_components.refresh_token.storage.doctrine\n",[426,1092,1093,1096],{"class":428,"line":465},[426,1094,1095],{"class":936},"        options",[426,1097,940],{"class":454},[426,1099,1100,1103,1105],{"class":428,"line":488},[426,1101,1102],{"class":936},"            class",[426,1104,415],{"class":454},[426,1106,1107],{"class":824}," App\\Entity\\RefreshToken\n",[426,1109,1110,1113,1115,1118],{"class":428,"line":514},[426,1111,1112],{"class":936},"        cookie_name",[426,1114,415],{"class":454},[426,1116,1117],{"class":824}," api_components",[426,1119,1120],{"class":432},"   # must match lexik_jwt cookie name\n",[426,1122,1123,1126,1128,1130],{"class":428,"line":538},[426,1124,1125],{"class":936},"        ttl",[426,1127,415],{"class":454},[426,1129,1020],{"class":995},[426,1131,1132],{"class":432},"                   # 1 week\n",[426,1134,1135,1138,1140],{"class":428,"line":563},[426,1136,1137],{"class":936},"        database_user_provider",[426,1139,415],{"class":454},[426,1141,1142],{"class":824}," database\n",[376,1144,1146],{"id":1145},"security-configuration","Security Configuration",[367,1148,1149,1150,1153],{},"The Flex recipe provides a working ",[371,1151,1152],{},"security.yaml",". Key sections:",[417,1155,1157],{"className":922,"code":1156,"language":924,"meta":422,"style":422},"security:\n    role_hierarchy:\n        ROLE_ADMIN: ROLE_USER\n        ROLE_SUPER_ADMIN: ROLE_ADMIN\n\n    firewalls:\n        main:\n            stateless: true\n            provider: database\n            guard:\n                authenticators:\n                    - lexik_jwt_authentication.jwt_token_authenticator\n\n    access_control:\n        # Anonymous access for auth flows\n        - { path: '^\u002Flogin', roles: PUBLIC_ACCESS }\n        - { path: '^\u002Ftoken\u002Frefresh', roles: PUBLIC_ACCESS }\n        - { path: '^\u002Fpassword\u002Freset', roles: PUBLIC_ACCESS }\n        - { path: '^\u002Fpassword\u002Fupdate', roles: PUBLIC_ACCESS }\n\n        # Allow anonymous form submissions (contact forms etc.)\n        - { path: '^\u002Fcomponent\u002Fforms\u002F.*\u002Fsubmit', methods: ['POST', 'PATCH'], roles: PUBLIC_ACCESS }\n\n        # Public read access\n        - { path: '^\u002F', methods: ['GET'], roles: PUBLIC_ACCESS }\n\n        # Mutations require authentication\n        - { path: '^\u002F', roles: ROLE_USER }\n",[371,1158,1159,1166,1173,1183,1193,1197,1204,1211,1220,1229,1236,1243,1251,1255,1262,1267,1302,1330,1358,1386,1391,1397,1451,1456,1462,1505,1510,1516],{"__ignoreMap":422},[426,1160,1161,1164],{"class":428,"line":429},[426,1162,1163],{"class":936},"security",[426,1165,940],{"class":454},[426,1167,1168,1171],{"class":428,"line":436},[426,1169,1170],{"class":936},"    role_hierarchy",[426,1172,940],{"class":454},[426,1174,1175,1178,1180],{"class":428,"line":458},[426,1176,1177],{"class":936},"        ROLE_ADMIN",[426,1179,415],{"class":454},[426,1181,1182],{"class":824}," ROLE_USER\n",[426,1184,1185,1188,1190],{"class":428,"line":465},[426,1186,1187],{"class":936},"        ROLE_SUPER_ADMIN",[426,1189,415],{"class":454},[426,1191,1192],{"class":824}," ROLE_ADMIN\n",[426,1194,1195],{"class":428,"line":488},[426,1196,462],{"emptyLinePlaceholder":461},[426,1198,1199,1202],{"class":428,"line":514},[426,1200,1201],{"class":936},"    firewalls",[426,1203,940],{"class":454},[426,1205,1206,1209],{"class":428,"line":538},[426,1207,1208],{"class":936},"        main",[426,1210,940],{"class":454},[426,1212,1213,1216,1218],{"class":428,"line":563},[426,1214,1215],{"class":936},"            stateless",[426,1217,415],{"class":454},[426,1219,1048],{"class":1047},[426,1221,1222,1225,1227],{"class":428,"line":568},[426,1223,1224],{"class":936},"            provider",[426,1226,415],{"class":454},[426,1228,1142],{"class":824},[426,1230,1231,1234],{"class":428,"line":584},[426,1232,1233],{"class":936},"            guard",[426,1235,940],{"class":454},[426,1237,1238,1241],{"class":428,"line":594},[426,1239,1240],{"class":936},"                authenticators",[426,1242,940],{"class":454},[426,1244,1245,1248],{"class":428,"line":610},[426,1246,1247],{"class":454},"                    -",[426,1249,1250],{"class":824}," lexik_jwt_authentication.jwt_token_authenticator\n",[426,1252,1253],{"class":428,"line":618},[426,1254,462],{"emptyLinePlaceholder":461},[426,1256,1257,1260],{"class":428,"line":634},[426,1258,1259],{"class":936},"    access_control",[426,1261,940],{"class":454},[426,1263,1264],{"class":428,"line":640},[426,1265,1266],{"class":432},"        # Anonymous access for auth flows\n",[426,1268,1269,1272,1275,1278,1280,1282,1285,1288,1291,1294,1296,1299],{"class":428,"line":646},[426,1270,1271],{"class":454},"        -",[426,1273,1274],{"class":454}," {",[426,1276,1277],{"class":936}," path",[426,1279,415],{"class":454},[426,1281,951],{"class":950},[426,1283,1284],{"class":824},"^\u002Flogin",[426,1286,1287],{"class":950},"'",[426,1289,1290],{"class":454},",",[426,1292,1293],{"class":936}," roles",[426,1295,415],{"class":454},[426,1297,1298],{"class":824}," PUBLIC_ACCESS",[426,1300,1301],{"class":454}," }\n",[426,1303,1305,1307,1309,1311,1313,1315,1318,1320,1322,1324,1326,1328],{"class":428,"line":1304},17,[426,1306,1271],{"class":454},[426,1308,1274],{"class":454},[426,1310,1277],{"class":936},[426,1312,415],{"class":454},[426,1314,951],{"class":950},[426,1316,1317],{"class":824},"^\u002Ftoken\u002Frefresh",[426,1319,1287],{"class":950},[426,1321,1290],{"class":454},[426,1323,1293],{"class":936},[426,1325,415],{"class":454},[426,1327,1298],{"class":824},[426,1329,1301],{"class":454},[426,1331,1333,1335,1337,1339,1341,1343,1346,1348,1350,1352,1354,1356],{"class":428,"line":1332},18,[426,1334,1271],{"class":454},[426,1336,1274],{"class":454},[426,1338,1277],{"class":936},[426,1340,415],{"class":454},[426,1342,951],{"class":950},[426,1344,1345],{"class":824},"^\u002Fpassword\u002Freset",[426,1347,1287],{"class":950},[426,1349,1290],{"class":454},[426,1351,1293],{"class":936},[426,1353,415],{"class":454},[426,1355,1298],{"class":824},[426,1357,1301],{"class":454},[426,1359,1361,1363,1365,1367,1369,1371,1374,1376,1378,1380,1382,1384],{"class":428,"line":1360},19,[426,1362,1271],{"class":454},[426,1364,1274],{"class":454},[426,1366,1277],{"class":936},[426,1368,415],{"class":454},[426,1370,951],{"class":950},[426,1372,1373],{"class":824},"^\u002Fpassword\u002Fupdate",[426,1375,1287],{"class":950},[426,1377,1290],{"class":454},[426,1379,1293],{"class":936},[426,1381,415],{"class":454},[426,1383,1298],{"class":824},[426,1385,1301],{"class":454},[426,1387,1389],{"class":428,"line":1388},20,[426,1390,462],{"emptyLinePlaceholder":461},[426,1392,1394],{"class":428,"line":1393},21,[426,1395,1396],{"class":432},"        # Allow anonymous form submissions (contact forms etc.)\n",[426,1398,1400,1402,1404,1406,1408,1410,1413,1415,1417,1420,1422,1424,1426,1429,1431,1433,1435,1438,1440,1443,1445,1447,1449],{"class":428,"line":1399},22,[426,1401,1271],{"class":454},[426,1403,1274],{"class":454},[426,1405,1277],{"class":936},[426,1407,415],{"class":454},[426,1409,951],{"class":950},[426,1411,1412],{"class":824},"^\u002Fcomponent\u002Fforms\u002F.*\u002Fsubmit",[426,1414,1287],{"class":950},[426,1416,1290],{"class":454},[426,1418,1419],{"class":936}," methods",[426,1421,415],{"class":454},[426,1423,602],{"class":454},[426,1425,1287],{"class":950},[426,1427,1428],{"class":824},"POST",[426,1430,1287],{"class":950},[426,1432,1290],{"class":454},[426,1434,951],{"class":950},[426,1436,1437],{"class":824},"PATCH",[426,1439,1287],{"class":950},[426,1441,1442],{"class":454},"],",[426,1444,1293],{"class":936},[426,1446,415],{"class":454},[426,1448,1298],{"class":824},[426,1450,1301],{"class":454},[426,1452,1454],{"class":428,"line":1453},23,[426,1455,462],{"emptyLinePlaceholder":461},[426,1457,1459],{"class":428,"line":1458},24,[426,1460,1461],{"class":432},"        # Public read access\n",[426,1463,1465,1467,1469,1471,1473,1475,1478,1480,1482,1484,1486,1488,1490,1493,1495,1497,1499,1501,1503],{"class":428,"line":1464},25,[426,1466,1271],{"class":454},[426,1468,1274],{"class":454},[426,1470,1277],{"class":936},[426,1472,415],{"class":454},[426,1474,951],{"class":950},[426,1476,1477],{"class":824},"^\u002F",[426,1479,1287],{"class":950},[426,1481,1290],{"class":454},[426,1483,1419],{"class":936},[426,1485,415],{"class":454},[426,1487,602],{"class":454},[426,1489,1287],{"class":950},[426,1491,1492],{"class":824},"GET",[426,1494,1287],{"class":950},[426,1496,1442],{"class":454},[426,1498,1293],{"class":936},[426,1500,415],{"class":454},[426,1502,1298],{"class":824},[426,1504,1301],{"class":454},[426,1506,1508],{"class":428,"line":1507},26,[426,1509,462],{"emptyLinePlaceholder":461},[426,1511,1513],{"class":428,"line":1512},27,[426,1514,1515],{"class":432},"        # Mutations require authentication\n",[426,1517,1519,1521,1523,1525,1527,1529,1531,1533,1535,1537,1539,1542],{"class":428,"line":1518},28,[426,1520,1271],{"class":454},[426,1522,1274],{"class":454},[426,1524,1277],{"class":936},[426,1526,415],{"class":454},[426,1528,951],{"class":950},[426,1530,1477],{"class":824},[426,1532,1287],{"class":950},[426,1534,1290],{"class":454},[426,1536,1293],{"class":936},[426,1538,415],{"class":454},[426,1540,1541],{"class":824}," ROLE_USER",[426,1543,1301],{"class":454},[376,1545,1547],{"id":1546},"email-verification-flow","Email Verification Flow",[367,1549,1550,1551,415],{},"Configure verification behaviour in ",[371,1552,1553],{},"silverback_api_components.yaml",[417,1555,1557],{"className":922,"code":1556,"language":924,"meta":422,"style":422},"silverback_api_components:\n    user:\n        class_name: App\\Entity\\User\n        email_verification:\n            default_value: false          # new users start unverified\n            verify_on_register: true      # send verification email on POST \u002Fusers\n            verify_on_change: true        # re-verify when email changes\n            deny_unverified_login: true   # block unverified users from logging in\n            email:\n                redirect_path_query: null\n                default_redirect_path: \u002Fverify-email\u002F{{ username }}\u002F{{ token }}\n                subject: Please verify your email\n",[371,1558,1559,1565,1572,1582,1589,1602,1615,1627,1639,1646,1656,1666],{"__ignoreMap":422},[426,1560,1561,1563],{"class":428,"line":429},[426,1562,1071],{"class":936},[426,1564,940],{"class":454},[426,1566,1567,1570],{"class":428,"line":436},[426,1568,1569],{"class":936},"    user",[426,1571,940],{"class":454},[426,1573,1574,1577,1579],{"class":428,"line":458},[426,1575,1576],{"class":936},"        class_name",[426,1578,415],{"class":454},[426,1580,1581],{"class":824}," App\\Entity\\User\n",[426,1583,1584,1587],{"class":428,"line":465},[426,1585,1586],{"class":936},"        email_verification",[426,1588,940],{"class":454},[426,1590,1591,1594,1596,1599],{"class":428,"line":488},[426,1592,1593],{"class":936},"            default_value",[426,1595,415],{"class":454},[426,1597,1598],{"class":1047}," false",[426,1600,1601],{"class":432},"          # new users start unverified\n",[426,1603,1604,1607,1609,1612],{"class":428,"line":514},[426,1605,1606],{"class":936},"            verify_on_register",[426,1608,415],{"class":454},[426,1610,1611],{"class":1047}," true",[426,1613,1614],{"class":432},"      # send verification email on POST \u002Fusers\n",[426,1616,1617,1620,1622,1624],{"class":428,"line":538},[426,1618,1619],{"class":936},"            verify_on_change",[426,1621,415],{"class":454},[426,1623,1611],{"class":1047},[426,1625,1626],{"class":432},"        # re-verify when email changes\n",[426,1628,1629,1632,1634,1636],{"class":428,"line":563},[426,1630,1631],{"class":936},"            deny_unverified_login",[426,1633,415],{"class":454},[426,1635,1611],{"class":1047},[426,1637,1638],{"class":432},"   # block unverified users from logging in\n",[426,1640,1641,1644],{"class":428,"line":568},[426,1642,1643],{"class":936},"            email",[426,1645,940],{"class":454},[426,1647,1648,1651,1653],{"class":428,"line":584},[426,1649,1650],{"class":936},"                redirect_path_query",[426,1652,415],{"class":454},[426,1654,1655],{"class":475}," null\n",[426,1657,1658,1661,1663],{"class":428,"line":594},[426,1659,1660],{"class":936},"                default_redirect_path",[426,1662,415],{"class":454},[426,1664,1665],{"class":824}," \u002Fverify-email\u002F{{ username }}\u002F{{ token }}\n",[426,1667,1668,1671,1673],{"class":428,"line":610},[426,1669,1670],{"class":936},"                subject",[426,1672,415],{"class":454},[426,1674,1675],{"class":824}," Please verify your email\n",[367,1677,1678,1679,1682],{},"The Nuxt module provides the ",[371,1680,1681],{},"\u002Fverify-email\u002F[username]\u002F[token]"," page automatically.",[376,1684,1686],{"id":1685},"password-reset-flow","Password Reset Flow",[417,1688,1690],{"className":922,"code":1689,"language":924,"meta":422,"style":422},"silverback_api_components:\n    user:\n        password_reset:\n            email:\n                redirect_path_query: null\n                default_redirect_path: \u002Freset-password\u002F{{ username }}\u002F{{ token }}\n                subject: Your password reset request\n            repeat_ttl_seconds: 8600      # minimum time between reset requests\n            request_timeout_seconds: 3600 # token validity window\n",[371,1691,1692,1698,1704,1711,1717,1725,1734,1743,1756],{"__ignoreMap":422},[426,1693,1694,1696],{"class":428,"line":429},[426,1695,1071],{"class":936},[426,1697,940],{"class":454},[426,1699,1700,1702],{"class":428,"line":436},[426,1701,1569],{"class":936},[426,1703,940],{"class":454},[426,1705,1706,1709],{"class":428,"line":458},[426,1707,1708],{"class":936},"        password_reset",[426,1710,940],{"class":454},[426,1712,1713,1715],{"class":428,"line":465},[426,1714,1643],{"class":936},[426,1716,940],{"class":454},[426,1718,1719,1721,1723],{"class":428,"line":488},[426,1720,1650],{"class":936},[426,1722,415],{"class":454},[426,1724,1655],{"class":475},[426,1726,1727,1729,1731],{"class":428,"line":514},[426,1728,1660],{"class":936},[426,1730,415],{"class":454},[426,1732,1733],{"class":824}," \u002Freset-password\u002F{{ username }}\u002F{{ token }}\n",[426,1735,1736,1738,1740],{"class":428,"line":538},[426,1737,1670],{"class":936},[426,1739,415],{"class":454},[426,1741,1742],{"class":824}," Your password reset request\n",[426,1744,1745,1748,1750,1753],{"class":428,"line":563},[426,1746,1747],{"class":936},"            repeat_ttl_seconds",[426,1749,415],{"class":454},[426,1751,1752],{"class":995}," 8600",[426,1754,1755],{"class":432},"      # minimum time between reset requests\n",[426,1757,1758,1761,1763,1766],{"class":428,"line":568},[426,1759,1760],{"class":936},"            request_timeout_seconds",[426,1762,415],{"class":454},[426,1764,1765],{"class":995}," 3600",[426,1767,1768],{"class":432}," # token validity window\n",[367,1770,1771,1772,1775,1776,1779],{},"The Nuxt module provides ",[371,1773,1774],{},"\u002Fforgot-password"," and ",[371,1777,1778],{},"\u002Freset-password\u002F[username]\u002F[token]"," automatically.",[376,1781,1783],{"id":1782},"email-address-change-flow","Email Address Change Flow",[417,1785,1787],{"className":922,"code":1786,"language":924,"meta":422,"style":422},"silverback_api_components:\n    user:\n        new_email_confirmation:\n            email:\n                redirect_path_query: null\n                default_redirect_path: \u002Fconfirm-new-email\u002F{{ username }}\u002F{{ new_email }}\u002F{{ token }}\n                subject: Please confirm your new email address\n            request_timeout_seconds: 86400\n",[371,1788,1789,1795,1801,1808,1814,1822,1831,1840],{"__ignoreMap":422},[426,1790,1791,1793],{"class":428,"line":429},[426,1792,1071],{"class":936},[426,1794,940],{"class":454},[426,1796,1797,1799],{"class":428,"line":436},[426,1798,1569],{"class":936},[426,1800,940],{"class":454},[426,1802,1803,1806],{"class":428,"line":458},[426,1804,1805],{"class":936},"        new_email_confirmation",[426,1807,940],{"class":454},[426,1809,1810,1812],{"class":428,"line":465},[426,1811,1643],{"class":936},[426,1813,940],{"class":454},[426,1815,1816,1818,1820],{"class":428,"line":488},[426,1817,1650],{"class":936},[426,1819,415],{"class":454},[426,1821,1655],{"class":475},[426,1823,1824,1826,1828],{"class":428,"line":514},[426,1825,1660],{"class":936},[426,1827,415],{"class":454},[426,1829,1830],{"class":824}," \u002Fconfirm-new-email\u002F{{ username }}\u002F{{ new_email }}\u002F{{ token }}\n",[426,1832,1833,1835,1837],{"class":428,"line":538},[426,1834,1670],{"class":936},[426,1836,415],{"class":454},[426,1838,1839],{"class":824}," Please confirm your new email address\n",[426,1841,1842,1844,1846],{"class":428,"line":563},[426,1843,1760],{"class":936},[426,1845,415],{"class":454},[426,1847,1848],{"class":995}," 86400\n",[376,1850,1852],{"id":1851},"notification-emails","Notification Emails",[367,1854,1855],{},"Configure which system emails are sent and their subjects:",[417,1857,1859],{"className":922,"code":1858,"language":924,"meta":422,"style":422},"silverback_api_components:\n    user:\n        emails:\n            welcome:\n                enabled: true\n                subject: 'Welcome to {{ website_name }}'\n            user_enabled:\n                enabled: true\n                subject: 'Your account has been enabled'\n            username_changed:\n                enabled: true\n                subject: 'Your username has been updated'\n            password_changed:\n                enabled: true\n                subject: 'Your password has been changed'\n",[371,1860,1861,1867,1873,1880,1887,1896,1909,1916,1924,1937,1944,1952,1965,1972,1980],{"__ignoreMap":422},[426,1862,1863,1865],{"class":428,"line":429},[426,1864,1071],{"class":936},[426,1866,940],{"class":454},[426,1868,1869,1871],{"class":428,"line":436},[426,1870,1569],{"class":936},[426,1872,940],{"class":454},[426,1874,1875,1878],{"class":428,"line":458},[426,1876,1877],{"class":936},"        emails",[426,1879,940],{"class":454},[426,1881,1882,1885],{"class":428,"line":465},[426,1883,1884],{"class":936},"            welcome",[426,1886,940],{"class":454},[426,1888,1889,1892,1894],{"class":428,"line":488},[426,1890,1891],{"class":936},"                enabled",[426,1893,415],{"class":454},[426,1895,1048],{"class":1047},[426,1897,1898,1900,1902,1904,1907],{"class":428,"line":514},[426,1899,1670],{"class":936},[426,1901,415],{"class":454},[426,1903,951],{"class":950},[426,1905,1906],{"class":824},"Welcome to {{ website_name }}",[426,1908,957],{"class":950},[426,1910,1911,1914],{"class":428,"line":538},[426,1912,1913],{"class":936},"            user_enabled",[426,1915,940],{"class":454},[426,1917,1918,1920,1922],{"class":428,"line":563},[426,1919,1891],{"class":936},[426,1921,415],{"class":454},[426,1923,1048],{"class":1047},[426,1925,1926,1928,1930,1932,1935],{"class":428,"line":568},[426,1927,1670],{"class":936},[426,1929,415],{"class":454},[426,1931,951],{"class":950},[426,1933,1934],{"class":824},"Your account has been enabled",[426,1936,957],{"class":950},[426,1938,1939,1942],{"class":428,"line":584},[426,1940,1941],{"class":936},"            username_changed",[426,1943,940],{"class":454},[426,1945,1946,1948,1950],{"class":428,"line":594},[426,1947,1891],{"class":936},[426,1949,415],{"class":454},[426,1951,1048],{"class":1047},[426,1953,1954,1956,1958,1960,1963],{"class":428,"line":610},[426,1955,1670],{"class":936},[426,1957,415],{"class":454},[426,1959,951],{"class":950},[426,1961,1962],{"class":824},"Your username has been updated",[426,1964,957],{"class":950},[426,1966,1967,1970],{"class":428,"line":618},[426,1968,1969],{"class":936},"            password_changed",[426,1971,940],{"class":454},[426,1973,1974,1976,1978],{"class":428,"line":634},[426,1975,1891],{"class":936},[426,1977,415],{"class":454},[426,1979,1048],{"class":1047},[426,1981,1982,1984,1986,1988,1991],{"class":428,"line":640},[426,1983,1670],{"class":936},[426,1985,415],{"class":454},[426,1987,951],{"class":950},[426,1989,1990],{"class":824},"Your password has been changed",[426,1992,957],{"class":950},[367,1994,1995,1996,1999],{},"Set ",[371,1997,1998],{},"MAILER_DSN"," in your environment:",[417,2001,2003],{"className":884,"code":2002,"language":886,"meta":422,"style":422},"MAILER_DSN=smtp:\u002F\u002Fuser:pass@smtp.example.com:587\n",[371,2004,2005],{"__ignoreMap":422},[426,2006,2007],{"class":428,"line":429},[426,2008,2002],{},[376,2010,2012],{"id":2011},"route-security","Route Security",[367,2014,2015],{},"Restrict which routes are visible in the API based on the current user's role:",[417,2017,2019],{"className":922,"code":2018,"language":924,"meta":422,"style":422},"silverback_api_components:\n    route_security:\n        - { route: '\u002Fuser-area*', security: \"is_granted('ROLE_USER')\" }\n        - { route: '\u002Fadmin*', security: \"is_granted('ROLE_ADMIN')\" }\n",[371,2020,2021,2027,2034,2070],{"__ignoreMap":422},[426,2022,2023,2025],{"class":428,"line":429},[426,2024,1071],{"class":936},[426,2026,940],{"class":454},[426,2028,2029,2032],{"class":428,"line":436},[426,2030,2031],{"class":936},"    route_security",[426,2033,940],{"class":454},[426,2035,2036,2038,2040,2043,2045,2047,2050,2052,2054,2057,2059,2062,2065,2068],{"class":428,"line":458},[426,2037,1271],{"class":454},[426,2039,1274],{"class":454},[426,2041,2042],{"class":936}," route",[426,2044,415],{"class":454},[426,2046,951],{"class":950},[426,2048,2049],{"class":824},"\u002Fuser-area*",[426,2051,1287],{"class":950},[426,2053,1290],{"class":454},[426,2055,2056],{"class":936}," security",[426,2058,415],{"class":454},[426,2060,2061],{"class":950}," \"",[426,2063,2064],{"class":824},"is_granted('ROLE_USER')",[426,2066,2067],{"class":950},"\"",[426,2069,1301],{"class":454},[426,2071,2072,2074,2076,2078,2080,2082,2085,2087,2089,2091,2093,2095,2098,2100],{"class":428,"line":465},[426,2073,1271],{"class":454},[426,2075,1274],{"class":454},[426,2077,2042],{"class":936},[426,2079,415],{"class":454},[426,2081,951],{"class":950},[426,2083,2084],{"class":824},"\u002Fadmin*",[426,2086,1287],{"class":950},[426,2088,1290],{"class":454},[426,2090,2056],{"class":936},[426,2092,415],{"class":454},[426,2094,2061],{"class":950},[426,2096,2097],{"class":824},"is_granted('ROLE_ADMIN')",[426,2099,2067],{"class":950},[426,2101,1301],{"class":454},[367,2103,2104,2107,2108,2111,2112,2115,2116,2118,2119,2122,2123,2125],{},[371,2105,2106],{},"route_security"," accepts any number of patterns. Each ",[371,2109,2110],{},"route"," value supports a ",[371,2113,2114],{},"*"," wildcard that matches any sequence of characters (internally converted to a regex — ",[371,2117,2114],{}," does not need to be a ",[371,2120,2121],{},"%","-style SQL wildcard). The ",[371,2124,1163],{}," value is any Symfony expression-language security expression.",[367,2127,2128],{},"Two things happen for each rule:",[2130,2131,2132,2150],"ul",{},[384,2133,2134,2137,2138,2141,2142,2145,2146,2149],{},[787,2135,2136],{},"Collection filtering"," — the ",[371,2139,2140],{},"Route"," collection endpoint (",[371,2143,2144],{},"GET \u002F_\u002Froutes",") omits routes matching the pattern when the expression is not satisfied. Anonymous users won't see ",[371,2147,2148],{},"\u002Fadmin\u002F*"," routes at all.",[384,2151,2152,2155,2156,2158],{},[787,2153,2154],{},"Item access"," — fetching a specific ",[371,2157,2140],{}," by IRI is denied if any matching rule's expression fails.",[376,2160,2162],{"id":2161},"routable_security",[371,2163,2161],{},[367,2165,2166,2167,2170,2171,2174],{},"Controls who can ",[787,2168,2169],{},"read"," un-routed pages and page data, and who can ",[787,2172,2173],{},"create"," new pages and page data:",[417,2176,2178],{"className":922,"code":2177,"language":924,"meta":422,"style":422},"silverback_api_components:\n    routable_security: \"is_granted('ROLE_ADMIN')\"\n",[371,2179,2180,2186],{"__ignoreMap":422},[426,2181,2182,2184],{"class":428,"line":429},[426,2183,1071],{"class":936},[426,2185,940],{"class":454},[426,2187,2188,2191,2193,2195,2197],{"class":428,"line":436},[426,2189,2190],{"class":936},"    routable_security",[426,2192,415],{"class":454},[426,2194,2061],{"class":950},[426,2196,2097],{"class":824},[426,2198,2199],{"class":950},"\"\n",[367,2201,2202,2203,1775,2206,2209,2210,2213],{},"Without this, every ",[371,2204,2205],{},"Page",[371,2207,2208],{},"PageData"," record is visible in API collections regardless of whether it has a public route. This matters for template pages (",[371,2211,2212],{},"isTemplate: true",") and draft pages — they exist in the database but have no URL.",[367,2215,2216,2217,2219],{},"When ",[371,2218,2161],{}," is set:",[367,2221,2222],{},[787,2223,2224],{},"GET (read access)",[2130,2226,2227,2234],{},[384,2228,2229,2230,2233],{},"Users who ",[787,2231,2232],{},"pass"," the expression see all records (including un-routed ones).",[384,2235,2229,2236,2239,2240,2242],{},[787,2237,2238],{},"fail"," the expression only see records that have a ",[371,2241,2110],{}," assigned — i.e., publicly accessible pages.",[367,2244,2245],{},"This prevents anonymous users from discovering admin-only templates or draft content through the collection endpoints.",[367,2247,2248,2251,2252,2254,2255,2257,2258,2260],{},[787,2249,2250],{},"POST (create access)","\nCreating a new ",[371,2253,2205],{}," or ",[371,2256,2208],{}," resource requires the ",[371,2259,2161],{}," expression to pass. This matches the existing restriction on edit operations — both creating and modifying CMS structure require admin access.",[376,2262,2264],{"id":2263},"component-security","Component Security",[367,2266,2267,2268,2271],{},"Components are automatically secured based on the routes they are reachable through. You do not need to configure this — it is built into the bundle via ",[371,2269,2270],{},"ComponentVoter",".",[367,2273,2274,2275,2277],{},"When a ",[371,2276,1492],{}," request is made for a specific component IRI, the bundle checks whether that component is accessible to the current user by:",[381,2279,2280,2286,2295,2301],{},[384,2281,2282,2285],{},[787,2283,2284],{},"Route check"," — is the component part of a page that has a publicly accessible route? If yes, access is granted.",[384,2287,2288,2291,2292,2294],{},[787,2289,2290],{},"PageData check"," — is the component referenced as a property on a ",[371,2293,2208],{}," resource with a reachable route? If yes, access is granted.",[384,2296,2297,2300],{},[787,2298,2299],{},"Template check"," — is the component placed in a page template used by reachable page data? If yes, access is granted.",[384,2302,2303],{},"If none of the above resolve (the component is genuinely unreachable for this user), access is denied.",[367,2305,2306],{},"This means components placed exclusively on admin pages are automatically hidden from anonymous API clients without any extra configuration.",[376,2308,2310],{"id":2309},"creating-the-first-admin-user","Creating the First Admin User",[417,2312,2314],{"className":808,"code":2313,"language":810,"meta":422,"style":422},"bin\u002Fconsole silverback:api-components:user:create\n",[371,2315,2316],{"__ignoreMap":422},[426,2317,2318,2321],{"class":428,"line":429},[426,2319,2320],{"class":443},"bin\u002Fconsole",[426,2322,2323],{"class":824}," silverback:api-components:user:create\n",[367,2325,2326,2327,2329],{},"You'll be prompted for username, email, and password. Without flags, the user is created with ",[371,2328,724],{}," only.",[656,2331,2332,2342],{},[659,2333,2334],{},[662,2335,2336,2339],{},[665,2337,2338],{},"Flag",[665,2340,2341],{},"Role granted",[675,2343,2344,2356,2368],{},[662,2345,2346,2352],{},[680,2347,2348],{},[2349,2350,2351],"em",{},"(none)",[680,2353,2354],{},[371,2355,724],{},[662,2357,2358,2363],{},[680,2359,2360],{},[371,2361,2362],{},"--admin",[680,2364,2365],{},[371,2366,2367],{},"ROLE_ADMIN",[662,2369,2370,2375],{},[680,2371,2372],{},[371,2373,2374],{},"--super-admin",[680,2376,2377],{},[371,2378,2379],{},"ROLE_SUPER_ADMIN",[367,2381,2382],{},"To create an admin non-interactively:",[417,2384,2386],{"className":808,"code":2385,"language":810,"meta":422,"style":422},"bin\u002Fconsole silverback:api-components:user:create alice alice@example.com s3cr3t --admin\n",[371,2387,2388],{"__ignoreMap":422},[426,2389,2390,2392,2395,2398,2401,2404],{"class":428,"line":429},[426,2391,2320],{"class":443},[426,2393,2394],{"class":824}," silverback:api-components:user:create",[426,2396,2397],{"class":824}," alice",[426,2399,2400],{"class":824}," alice@example.com",[426,2402,2403],{"class":824}," s3cr3t",[426,2405,2406],{"class":820}," --admin\n",[2408,2409,2410],"style",{},"html pre.shiki code .sTBSN, html code.shiki .sTBSN{--shiki-light:#6A737D;--shiki-light-font-style:inherit;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .stmX-, html code.shiki .stmX-{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F78C6C}html pre.shiki code .sRCss, html code.shiki .sRCss{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#FFCB6B}html pre.shiki code .sn4go, html code.shiki .sn4go{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#89DDFF}html pre.shiki code .sOvfz, html code.shiki .sOvfz{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#89DDFF}html pre.shiki code .sc2zw, html code.shiki .sc2zw{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#BABED8}html pre.shiki code .sBtbT, html code.shiki .sBtbT{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#89DDFF}html pre.shiki code .sPB8G, html code.shiki .sPB8G{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#BABED8}html pre.shiki code .swB56, html code.shiki .swB56{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#C792EA}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 .szhYu, html code.shiki .szhYu{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#C3E88D}html pre.shiki code .sLL54, html code.shiki .sLL54{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#C3E88D}html pre.shiki code .s-h7I, html code.shiki .s-h7I{--shiki-light:#22863A;--shiki-default:#85E89D;--shiki-dark:#F07178}html pre.shiki code .seSrl, html code.shiki .seSrl{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#89DDFF}html pre.shiki code .scSvc, html code.shiki .scSvc{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#F78C6C}html pre.shiki code .swWMF, html code.shiki .swWMF{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#FF9CAC}",{"title":422,"searchDepth":436,"depth":436,"links":2412},[2413,2414,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428],{"id":378,"depth":436,"text":379},{"id":404,"depth":436,"text":405,"children":2415},[2416],{"id":653,"depth":458,"text":654},{"id":801,"depth":436,"text":802},{"id":915,"depth":436,"text":916},{"id":1060,"depth":436,"text":1061},{"id":1145,"depth":436,"text":1146},{"id":1546,"depth":436,"text":1547},{"id":1685,"depth":436,"text":1686},{"id":1782,"depth":436,"text":1783},{"id":1851,"depth":436,"text":1852},{"id":2011,"depth":436,"text":2012},{"id":2161,"depth":436,"text":2161},{"id":2263,"depth":436,"text":2264},{"id":2309,"depth":436,"text":2310},"JWT cookie authentication, the AbstractUser entity, email verification, password reset, and Symfony security configuration.","md",null,{},{"title":121,"description":2429},"8snx8yt_sWsm1hA4UaKI1jdsRVbMyNDcduHs33k6rag",[2436,2438],{"title":117,"path":118,"stem":119,"description":2437,"children":-1},"Build blogs, event listings, and multi-level page hierarchies using AbstractPageData and nested Page relationships.",{"title":125,"path":126,"stem":127,"description":2439,"children":-1},"Use AbstractCwaScaffold and CwaFixtureBuilder to seed your database with layouts, pages, routes, components, and page data in a fluent API.",1782512897431]