[{"data":1,"prerenderedAt":1881},["ShallowReactive",2],{"navigation":3,"\u002Fecosystem\u002Fnuxt-auth-idp":105,"\u002Fecosystem\u002Fnuxt-auth-idp-surround":1876},[4,44,79,92],{"title":5,"path":6,"stem":7,"children":8,"icon":43},"Getting Started","\u002Fgetting-started","1.getting-started\u002F1.index",[9,11,15,19,23,27,31,35,39],{"title":10,"path":6,"stem":7},"Introduction",{"title":12,"path":13,"stem":14},"Quick Start: Service Provider","\u002Fgetting-started\u002Fquickstart-sp","1.getting-started\u002F2.quickstart-sp",{"title":16,"path":17,"stem":18},"Quick Start: Identity Provider","\u002Fgetting-started\u002Fquickstart-idp","1.getting-started\u002F3.quickstart-idp",{"title":20,"path":21,"stem":22},"Quick Start: Agent","\u002Fgetting-started\u002Fquickstart-agent","1.getting-started\u002F4.quickstart-agent",{"title":24,"path":25,"stem":26},"Quick Start","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F5.installation",{"title":28,"path":29,"stem":30},"How It Works","\u002Fgetting-started\u002Fhow-it-works","1.getting-started\u002F6.how-it-works",{"title":32,"path":33,"stem":34},"For Service Providers","\u002Fgetting-started\u002Ffor-service-providers","1.getting-started\u002F7.for-service-providers",{"title":36,"path":37,"stem":38},"CLI (apes & ape-shell)","\u002Fgetting-started\u002Fcli","1.getting-started\u002F8.cli",{"title":40,"path":41,"stem":42},"Free-IdP Hosting Guide","\u002Fgetting-started\u002Ffree-idp-hosting","1.getting-started\u002F9.free-idp-hosting",false,{"title":45,"path":46,"stem":47,"children":48,"icon":43},"Ecosystem","\u002Fecosystem","2.ecosystem\u002F1.index",[49,51,55,59,63,67,71,75],{"title":50,"path":46,"stem":47},"Overview",{"title":52,"path":53,"stem":54},"OpenApe Auth","\u002Fecosystem\u002Fauth","2.ecosystem\u002F2.auth",{"title":56,"path":57,"stem":58},"OpenApe Grants","\u002Fecosystem\u002Fgrants","2.ecosystem\u002F3.grants",{"title":60,"path":61,"stem":62},"nuxt-auth-sp","\u002Fecosystem\u002Fnuxt-auth-sp","2.ecosystem\u002F4.nuxt-auth-sp",{"title":64,"path":65,"stem":66},"escapes","\u002Fecosystem\u002Fescapes","2.ecosystem\u002F5.escapes",{"title":68,"path":69,"stem":70},"nuxt-auth-idp","\u002Fecosystem\u002Fnuxt-auth-idp","2.ecosystem\u002F6.nuxt-auth-idp",{"title":72,"path":73,"stem":74},"Multi-Tenant IdP","\u002Fecosystem\u002Fmulti-tenant-idp","2.ecosystem\u002F7.multi-tenant-idp",{"title":76,"path":77,"stem":78},"Agent Recipe","\u002Fecosystem\u002Fagent-recipe","2.ecosystem\u002F8.agent-recipe",{"title":80,"icon":43,"path":81,"stem":82,"children":83,"page":43},"Security","\u002Fsecurity","3.security",[84,88],{"title":85,"path":86,"stem":87},"Compliance","\u002Fsecurity\u002Fcompliance","3.security\u002F1.compliance",{"title":89,"path":90,"stem":91},"Threat Model","\u002Fsecurity\u002Fthreat-model","3.security\u002F2.threat-model",{"title":93,"icon":43,"path":94,"stem":95,"children":96,"page":43},"Guides","\u002Fguides","4.guides",[97,101],{"title":98,"path":99,"stem":100},"Capabilities & Grants","\u002Fguides\u002Fcapabilities","4.guides\u002F1.capabilities",{"title":102,"path":103,"stem":104},"Delegation","\u002Fguides\u002Fdelegation","4.guides\u002F2.delegation",{"id":106,"title":68,"body":107,"description":1870,"extension":1871,"links":1872,"meta":1873,"navigation":462,"path":69,"seo":1874,"stem":70,"__hash__":1875},"docs\u002F2.ecosystem\u002F6.nuxt-auth-idp.md",{"type":108,"value":109,"toc":1836},"minimark",[110,115,127,137,141,146,171,178,311,329,333,340,530,541,545,550,950,956,1141,1145,1152,1160,1207,1213,1251,1258,1292,1299,1363,1370,1395,1406,1446,1453,1468,1472,1479,1519,1523,1529,1571,1656,1662,1669,1673,1691,1728,1737,1741,1760,1767,1771,1774,1802,1808,1812,1832],[111,112,114],"h1",{"id":113},"openapenuxt-auth-idp","@openape\u002Fnuxt-auth-idp",[116,117,118,119,126],"p",{},"Drop-in Nuxt module that turns a Nuxt app into a full OpenApe IdP — WebAuthn passkey login, SSH-key agent auth, OAuth\u002FOIDC endpoints, grant approval flows, federation, and admin UI. Counterpart to ",[120,121,122],"a",{"href":61},[123,124,125],"code",{},"@openape\u002Fnuxt-auth-sp"," on the service-provider side.",[116,128,129,130,136],{},"Pair it with a storage backend of your choice: the module ships with an in-memory store suitable for development, and the ",[120,131,135],{"href":132,"rel":133},"https:\u002F\u002Fgithub.com\u002Fopenape-ai\u002Fopenape\u002Ftree\u002Fmain\u002Fapps\u002Fopenape-free-idp",[134],"nofollow","openape-free-idp"," reference app wires it to Drizzle + libsql\u002FTurso for persistent production hosting.",[138,139,24],"h2",{"id":140},"quick-start",[142,143,145],"h3",{"id":144},"_1-install","1. Install",[147,148,153],"pre",{"className":149,"code":150,"language":151,"meta":152,"style":152},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm add @openape\u002Fnuxt-auth-idp\n","bash","",[123,154,155],{"__ignoreMap":152},[156,157,160,164,168],"span",{"class":158,"line":159},"line",1,[156,161,163],{"class":162},"sBMFI","pnpm",[156,165,167],{"class":166},"sfazB"," add",[156,169,170],{"class":166}," @openape\u002Fnuxt-auth-idp\n",[142,172,174,175],{"id":173},"_2-add-to-nuxtconfigts","2. Add to ",[123,176,177],{},"nuxt.config.ts",[147,179,183],{"className":180,"code":181,"language":182,"meta":152,"style":152},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export default defineNuxtConfig({\n  modules: ['@openape\u002Fnuxt-auth-idp'],\n  openapeIdp: {\n    issuer: 'https:\u002F\u002Fid.example.com',\n    rpName: 'Example IdP',\n    sessionSecret: '', \u002F\u002F set NUXT_OPENAPE_IDP_SESSION_SECRET in prod\n  },\n})\n","ts",[123,184,185,206,232,243,261,278,296,302],{"__ignoreMap":152},[156,186,187,191,194,198,202],{"class":158,"line":159},[156,188,190],{"class":189},"s7zQu","export",[156,192,193],{"class":189}," default",[156,195,197],{"class":196},"s2Zo4"," defineNuxtConfig",[156,199,201],{"class":200},"sTEyZ","(",[156,203,205],{"class":204},"sMK4o","{\n",[156,207,209,213,216,219,222,224,226,229],{"class":158,"line":208},2,[156,210,212],{"class":211},"swJcz","  modules",[156,214,215],{"class":204},":",[156,217,218],{"class":200}," [",[156,220,221],{"class":204},"'",[156,223,114],{"class":166},[156,225,221],{"class":204},[156,227,228],{"class":200},"]",[156,230,231],{"class":204},",\n",[156,233,235,238,240],{"class":158,"line":234},3,[156,236,237],{"class":211},"  openapeIdp",[156,239,215],{"class":204},[156,241,242],{"class":204}," {\n",[156,244,246,249,251,254,257,259],{"class":158,"line":245},4,[156,247,248],{"class":211},"    issuer",[156,250,215],{"class":204},[156,252,253],{"class":204}," '",[156,255,256],{"class":166},"https:\u002F\u002Fid.example.com",[156,258,221],{"class":204},[156,260,231],{"class":204},[156,262,264,267,269,271,274,276],{"class":158,"line":263},5,[156,265,266],{"class":211},"    rpName",[156,268,215],{"class":204},[156,270,253],{"class":204},[156,272,273],{"class":166},"Example IdP",[156,275,221],{"class":204},[156,277,231],{"class":204},[156,279,281,284,286,289,292],{"class":158,"line":280},6,[156,282,283],{"class":211},"    sessionSecret",[156,285,215],{"class":204},[156,287,288],{"class":204}," ''",[156,290,291],{"class":204},",",[156,293,295],{"class":294},"sHwdD"," \u002F\u002F set NUXT_OPENAPE_IDP_SESSION_SECRET in prod\n",[156,297,299],{"class":158,"line":298},7,[156,300,301],{"class":204},"  },\n",[156,303,305,308],{"class":158,"line":304},8,[156,306,307],{"class":204},"}",[156,309,310],{"class":200},")\n",[116,312,313,314,317,318,321,322,324,325,328],{},"In dev the module auto-generates a ",[123,315,316],{},"sessionSecret"," and derives ",[123,319,320],{},"rpID"," from the request host. In production you must set ",[123,323,316],{}," and ",[123,326,327],{},"adminEmails"," explicitly.",[142,330,332],{"id":331},"_3-register-a-storage-backend","3. Register a storage backend",[116,334,335,336,339],{},"The module is storage-agnostic. Register each store from a server plugin (",[123,337,338],{},"server\u002Fplugins\u002F02.stores.ts","):",[147,341,343],{"className":180,"code":342,"language":182,"meta":152,"style":152},"import {\n  defineUserStore,\n  defineCredentialStore,\n  defineKeyStore,\n  defineCodeStore,\n  defineRefreshTokenStore,\n  defineJtiStore,\n  defineWebAuthnChallengeStore,\n  defineRegistrationUrlStore,\n  defineGrantStore,\n  defineGrantChallengeStore,\n  defineSshKeyStore,\n  defineShapeStore,\n} from '#imports'\n\nexport default defineNitroPlugin(() => {\n  defineUserStore(() => myUserStore)\n  defineCredentialStore(() => myCredentialStore)\n  \u002F\u002F …register all stores\n})\n",[123,344,345,352,359,366,373,380,387,394,401,409,417,425,433,441,457,464,485,501,517,523],{"__ignoreMap":152},[156,346,347,350],{"class":158,"line":159},[156,348,349],{"class":189},"import",[156,351,242],{"class":204},[156,353,354,357],{"class":158,"line":208},[156,355,356],{"class":200},"  defineUserStore",[156,358,231],{"class":204},[156,360,361,364],{"class":158,"line":234},[156,362,363],{"class":200},"  defineCredentialStore",[156,365,231],{"class":204},[156,367,368,371],{"class":158,"line":245},[156,369,370],{"class":200},"  defineKeyStore",[156,372,231],{"class":204},[156,374,375,378],{"class":158,"line":263},[156,376,377],{"class":200},"  defineCodeStore",[156,379,231],{"class":204},[156,381,382,385],{"class":158,"line":280},[156,383,384],{"class":200},"  defineRefreshTokenStore",[156,386,231],{"class":204},[156,388,389,392],{"class":158,"line":298},[156,390,391],{"class":200},"  defineJtiStore",[156,393,231],{"class":204},[156,395,396,399],{"class":158,"line":304},[156,397,398],{"class":200},"  defineWebAuthnChallengeStore",[156,400,231],{"class":204},[156,402,404,407],{"class":158,"line":403},9,[156,405,406],{"class":200},"  defineRegistrationUrlStore",[156,408,231],{"class":204},[156,410,412,415],{"class":158,"line":411},10,[156,413,414],{"class":200},"  defineGrantStore",[156,416,231],{"class":204},[156,418,420,423],{"class":158,"line":419},11,[156,421,422],{"class":200},"  defineGrantChallengeStore",[156,424,231],{"class":204},[156,426,428,431],{"class":158,"line":427},12,[156,429,430],{"class":200},"  defineSshKeyStore",[156,432,231],{"class":204},[156,434,436,439],{"class":158,"line":435},13,[156,437,438],{"class":200},"  defineShapeStore",[156,440,231],{"class":204},[156,442,444,446,449,451,454],{"class":158,"line":443},14,[156,445,307],{"class":204},[156,447,448],{"class":189}," from",[156,450,253],{"class":204},[156,452,453],{"class":166},"#imports",[156,455,456],{"class":204},"'\n",[156,458,460],{"class":158,"line":459},15,[156,461,463],{"emptyLinePlaceholder":462},true,"\n",[156,465,467,469,471,474,476,479,483],{"class":158,"line":466},16,[156,468,190],{"class":189},[156,470,193],{"class":189},[156,472,473],{"class":196}," defineNitroPlugin",[156,475,201],{"class":200},[156,477,478],{"class":204},"()",[156,480,482],{"class":481},"spNyl"," =>",[156,484,242],{"class":204},[156,486,488,490,492,494,496,499],{"class":158,"line":487},17,[156,489,356],{"class":196},[156,491,201],{"class":211},[156,493,478],{"class":204},[156,495,482],{"class":481},[156,497,498],{"class":200}," myUserStore",[156,500,310],{"class":211},[156,502,504,506,508,510,512,515],{"class":158,"line":503},18,[156,505,363],{"class":196},[156,507,201],{"class":211},[156,509,478],{"class":204},[156,511,482],{"class":481},[156,513,514],{"class":200}," myCredentialStore",[156,516,310],{"class":211},[156,518,520],{"class":158,"line":519},19,[156,521,522],{"class":294},"  \u002F\u002F …register all stores\n",[156,524,526,528],{"class":158,"line":525},20,[156,527,307],{"class":204},[156,529,310],{"class":200},[116,531,532,533,540],{},"For a complete wired-up example (Drizzle + libsql), see ",[120,534,537],{"href":535,"rel":536},"https:\u002F\u002Fgithub.com\u002Fopenape-ai\u002Fopenape\u002Fblob\u002Fmain\u002Fapps\u002Fopenape-free-idp\u002Fserver\u002Fplugins\u002F03.stores.ts",[134],[123,538,539],{},"apps\u002Fopenape-free-idp\u002Fserver\u002Fplugins\u002F03.stores.ts",".",[138,542,544],{"id":543},"module-options","Module Options",[116,546,547,548,215],{},"Full configuration surface in ",[123,549,177],{},[147,551,553],{"className":180,"code":552,"language":182,"meta":152,"style":152},"openapeIdp: {\n  \u002F\u002F Security\n  sessionSecret: '',            \u002F\u002F 32+ char secret (required in prod)\n  sessionMaxAge: 604800,        \u002F\u002F session cookie TTL in seconds (7 days)\n  managementToken: '',          \u002F\u002F bearer for management endpoints\n  adminEmails: '',              \u002F\u002F comma-separated list\n\n  \u002F\u002F Identity\n  issuer: '',                   \u002F\u002F OAuth `iss` claim; falls back to request origin\n  rpName: '',                   \u002F\u002F WebAuthn RP display name\n  rpID: '',                     \u002F\u002F WebAuthn RP ID; falls back to request host\n  rpOrigin: '',                 \u002F\u002F WebAuthn origin; falls back to request origin\n  rpHostAllowList: '',          \u002F\u002F comma-separated; see Multi-Tenant below\n\n  \u002F\u002F WebAuthn policy\n  requireUserVerification: false,\n  residentKey: 'preferred',     \u002F\u002F 'preferred' | 'required' | 'discouraged'\n  attestationType: 'none',      \u002F\u002F 'none' | 'indirect' | 'direct' | 'enterprise'\n\n  \u002F\u002F Routes (which groups to register)\n  routes: true,                 \u002F\u002F or { auth, oauth, grants, admin, agent }\n  pages: true,                  \u002F\u002F register \u002Flogin, \u002Fregister, \u002Faccount, \u002Fadmin etc.\n\n  \u002F\u002F Grants\n  grants: {\n    enablePages: true,          \u002F\u002F register \u002Fgrants, \u002Fgrant-approval, \u002Fenroll pages\n    storageKey: 'openape-grants',\n  },\n\n  \u002F\u002F Federation\n  federationProviders: '',      \u002F\u002F JSON string — see Federation below\n\n  \u002F\u002F Embedding\n  allowedFrameAncestors: '',    \u002F\u002F space-separated origins; defaults to frame-ancestors 'none'\n\n  \u002F\u002F Storage namespace (used by the default in-memory store)\n  storageKey: 'openape-idp',\n}\n",[123,554,555,564,569,583,599,613,627,631,636,650,664,678,692,706,710,715,728,747,766,770,775,791,806,811,817,827,842,859,864,869,875,890,895,901,916,921,927,944],{"__ignoreMap":152},[156,556,557,560,562],{"class":158,"line":159},[156,558,559],{"class":162},"openapeIdp",[156,561,215],{"class":204},[156,563,242],{"class":204},[156,565,566],{"class":158,"line":208},[156,567,568],{"class":294},"  \u002F\u002F Security\n",[156,570,571,574,576,578,580],{"class":158,"line":234},[156,572,573],{"class":162},"  sessionSecret",[156,575,215],{"class":204},[156,577,288],{"class":204},[156,579,291],{"class":204},[156,581,582],{"class":294},"            \u002F\u002F 32+ char secret (required in prod)\n",[156,584,585,588,590,594,596],{"class":158,"line":245},[156,586,587],{"class":162},"  sessionMaxAge",[156,589,215],{"class":204},[156,591,593],{"class":592},"sbssI"," 604800",[156,595,291],{"class":204},[156,597,598],{"class":294},"        \u002F\u002F session cookie TTL in seconds (7 days)\n",[156,600,601,604,606,608,610],{"class":158,"line":263},[156,602,603],{"class":162},"  managementToken",[156,605,215],{"class":204},[156,607,288],{"class":204},[156,609,291],{"class":204},[156,611,612],{"class":294},"          \u002F\u002F bearer for management endpoints\n",[156,614,615,618,620,622,624],{"class":158,"line":280},[156,616,617],{"class":162},"  adminEmails",[156,619,215],{"class":204},[156,621,288],{"class":204},[156,623,291],{"class":204},[156,625,626],{"class":294},"              \u002F\u002F comma-separated list\n",[156,628,629],{"class":158,"line":298},[156,630,463],{"emptyLinePlaceholder":462},[156,632,633],{"class":158,"line":304},[156,634,635],{"class":294},"  \u002F\u002F Identity\n",[156,637,638,641,643,645,647],{"class":158,"line":403},[156,639,640],{"class":162},"  issuer",[156,642,215],{"class":204},[156,644,288],{"class":204},[156,646,291],{"class":204},[156,648,649],{"class":294},"                   \u002F\u002F OAuth `iss` claim; falls back to request origin\n",[156,651,652,655,657,659,661],{"class":158,"line":411},[156,653,654],{"class":162},"  rpName",[156,656,215],{"class":204},[156,658,288],{"class":204},[156,660,291],{"class":204},[156,662,663],{"class":294},"                   \u002F\u002F WebAuthn RP display name\n",[156,665,666,669,671,673,675],{"class":158,"line":419},[156,667,668],{"class":162},"  rpID",[156,670,215],{"class":204},[156,672,288],{"class":204},[156,674,291],{"class":204},[156,676,677],{"class":294},"                     \u002F\u002F WebAuthn RP ID; falls back to request host\n",[156,679,680,683,685,687,689],{"class":158,"line":427},[156,681,682],{"class":162},"  rpOrigin",[156,684,215],{"class":204},[156,686,288],{"class":204},[156,688,291],{"class":204},[156,690,691],{"class":294},"                 \u002F\u002F WebAuthn origin; falls back to request origin\n",[156,693,694,697,699,701,703],{"class":158,"line":435},[156,695,696],{"class":162},"  rpHostAllowList",[156,698,215],{"class":204},[156,700,288],{"class":204},[156,702,291],{"class":204},[156,704,705],{"class":294},"          \u002F\u002F comma-separated; see Multi-Tenant below\n",[156,707,708],{"class":158,"line":443},[156,709,463],{"emptyLinePlaceholder":462},[156,711,712],{"class":158,"line":459},[156,713,714],{"class":294},"  \u002F\u002F WebAuthn policy\n",[156,716,717,720,722,726],{"class":158,"line":466},[156,718,719],{"class":162},"  requireUserVerification",[156,721,215],{"class":204},[156,723,725],{"class":724},"sfNiH"," false",[156,727,231],{"class":204},[156,729,730,733,735,737,740,742,744],{"class":158,"line":487},[156,731,732],{"class":162},"  residentKey",[156,734,215],{"class":204},[156,736,253],{"class":204},[156,738,739],{"class":166},"preferred",[156,741,221],{"class":204},[156,743,291],{"class":204},[156,745,746],{"class":294},"     \u002F\u002F 'preferred' | 'required' | 'discouraged'\n",[156,748,749,752,754,756,759,761,763],{"class":158,"line":503},[156,750,751],{"class":162},"  attestationType",[156,753,215],{"class":204},[156,755,253],{"class":204},[156,757,758],{"class":166},"none",[156,760,221],{"class":204},[156,762,291],{"class":204},[156,764,765],{"class":294},"      \u002F\u002F 'none' | 'indirect' | 'direct' | 'enterprise'\n",[156,767,768],{"class":158,"line":519},[156,769,463],{"emptyLinePlaceholder":462},[156,771,772],{"class":158,"line":525},[156,773,774],{"class":294},"  \u002F\u002F Routes (which groups to register)\n",[156,776,778,781,783,786,788],{"class":158,"line":777},21,[156,779,780],{"class":162},"  routes",[156,782,215],{"class":204},[156,784,785],{"class":724}," true",[156,787,291],{"class":204},[156,789,790],{"class":294},"                 \u002F\u002F or { auth, oauth, grants, admin, agent }\n",[156,792,794,797,799,801,803],{"class":158,"line":793},22,[156,795,796],{"class":162},"  pages",[156,798,215],{"class":204},[156,800,785],{"class":724},[156,802,291],{"class":204},[156,804,805],{"class":294},"                  \u002F\u002F register \u002Flogin, \u002Fregister, \u002Faccount, \u002Fadmin etc.\n",[156,807,809],{"class":158,"line":808},23,[156,810,463],{"emptyLinePlaceholder":462},[156,812,814],{"class":158,"line":813},24,[156,815,816],{"class":294},"  \u002F\u002F Grants\n",[156,818,820,823,825],{"class":158,"line":819},25,[156,821,822],{"class":162},"  grants",[156,824,215],{"class":204},[156,826,242],{"class":204},[156,828,830,833,835,837,839],{"class":158,"line":829},26,[156,831,832],{"class":162},"    enablePages",[156,834,215],{"class":204},[156,836,785],{"class":724},[156,838,291],{"class":204},[156,840,841],{"class":294},"          \u002F\u002F register \u002Fgrants, \u002Fgrant-approval, \u002Fenroll pages\n",[156,843,845,848,850,852,855,857],{"class":158,"line":844},27,[156,846,847],{"class":162},"    storageKey",[156,849,215],{"class":204},[156,851,253],{"class":204},[156,853,854],{"class":166},"openape-grants",[156,856,221],{"class":204},[156,858,231],{"class":204},[156,860,862],{"class":158,"line":861},28,[156,863,301],{"class":204},[156,865,867],{"class":158,"line":866},29,[156,868,463],{"emptyLinePlaceholder":462},[156,870,872],{"class":158,"line":871},30,[156,873,874],{"class":294},"  \u002F\u002F Federation\n",[156,876,878,881,883,885,887],{"class":158,"line":877},31,[156,879,880],{"class":162},"  federationProviders",[156,882,215],{"class":204},[156,884,288],{"class":204},[156,886,291],{"class":204},[156,888,889],{"class":294},"      \u002F\u002F JSON string — see Federation below\n",[156,891,893],{"class":158,"line":892},32,[156,894,463],{"emptyLinePlaceholder":462},[156,896,898],{"class":158,"line":897},33,[156,899,900],{"class":294},"  \u002F\u002F Embedding\n",[156,902,904,907,909,911,913],{"class":158,"line":903},34,[156,905,906],{"class":162},"  allowedFrameAncestors",[156,908,215],{"class":204},[156,910,288],{"class":204},[156,912,291],{"class":204},[156,914,915],{"class":294},"    \u002F\u002F space-separated origins; defaults to frame-ancestors 'none'\n",[156,917,919],{"class":158,"line":918},35,[156,920,463],{"emptyLinePlaceholder":462},[156,922,924],{"class":158,"line":923},36,[156,925,926],{"class":294},"  \u002F\u002F Storage namespace (used by the default in-memory store)\n",[156,928,930,933,935,937,940,942],{"class":158,"line":929},37,[156,931,932],{"class":162},"  storageKey",[156,934,215],{"class":204},[156,936,253],{"class":204},[156,938,939],{"class":166},"openape-idp",[156,941,221],{"class":204},[156,943,231],{"class":204},[156,945,947],{"class":158,"line":946},38,[156,948,949],{"class":204},"}\n",[116,951,952,953,339],{},"All options are settable via environment variables following Nuxt's runtimeConfig convention (",[123,954,955],{},"NUXT_OPENAPE_IDP_*",[957,958,959,972],"table",{},[960,961,962],"thead",{},[963,964,965,969],"tr",{},[966,967,968],"th",{},"Variable",[966,970,971],{},"Config key",[973,974,975,987,999,1011,1022,1034,1046,1057,1069,1081,1093,1105,1117,1129],"tbody",{},[963,976,977,983],{},[978,979,980],"td",{},[123,981,982],{},"NUXT_OPENAPE_IDP_SESSION_SECRET",[978,984,985],{},[123,986,316],{},[963,988,989,994],{},[978,990,991],{},[123,992,993],{},"NUXT_OPENAPE_IDP_SESSION_MAX_AGE",[978,995,996],{},[123,997,998],{},"sessionMaxAge",[963,1000,1001,1006],{},[978,1002,1003],{},[123,1004,1005],{},"NUXT_OPENAPE_IDP_MANAGEMENT_TOKEN",[978,1007,1008],{},[123,1009,1010],{},"managementToken",[963,1012,1013,1018],{},[978,1014,1015],{},[123,1016,1017],{},"NUXT_OPENAPE_IDP_ADMIN_EMAILS",[978,1019,1020],{},[123,1021,327],{},[963,1023,1024,1029],{},[978,1025,1026],{},[123,1027,1028],{},"NUXT_OPENAPE_IDP_ISSUER",[978,1030,1031],{},[123,1032,1033],{},"issuer",[963,1035,1036,1041],{},[978,1037,1038],{},[123,1039,1040],{},"NUXT_OPENAPE_IDP_RP_NAME",[978,1042,1043],{},[123,1044,1045],{},"rpName",[963,1047,1048,1053],{},[978,1049,1050],{},[123,1051,1052],{},"NUXT_OPENAPE_IDP_RP_ID",[978,1054,1055],{},[123,1056,320],{},[963,1058,1059,1064],{},[978,1060,1061],{},[123,1062,1063],{},"NUXT_OPENAPE_IDP_RP_ORIGIN",[978,1065,1066],{},[123,1067,1068],{},"rpOrigin",[963,1070,1071,1076],{},[978,1072,1073],{},[123,1074,1075],{},"NUXT_OPENAPE_IDP_RP_HOST_ALLOW_LIST",[978,1077,1078],{},[123,1079,1080],{},"rpHostAllowList",[963,1082,1083,1088],{},[978,1084,1085],{},[123,1086,1087],{},"NUXT_OPENAPE_IDP_REQUIRE_USER_VERIFICATION",[978,1089,1090],{},[123,1091,1092],{},"requireUserVerification",[963,1094,1095,1100],{},[978,1096,1097],{},[123,1098,1099],{},"NUXT_OPENAPE_IDP_RESIDENT_KEY",[978,1101,1102],{},[123,1103,1104],{},"residentKey",[963,1106,1107,1112],{},[978,1108,1109],{},[123,1110,1111],{},"NUXT_OPENAPE_IDP_ATTESTATION_TYPE",[978,1113,1114],{},[123,1115,1116],{},"attestationType",[963,1118,1119,1124],{},[978,1120,1121],{},[123,1122,1123],{},"NUXT_OPENAPE_IDP_FEDERATION_PROVIDERS",[978,1125,1126],{},[123,1127,1128],{},"federationProviders",[963,1130,1131,1136],{},[978,1132,1133],{},[123,1134,1135],{},"NUXT_OPENAPE_IDP_ALLOWED_FRAME_ANCESTORS",[978,1137,1138],{},[123,1139,1140],{},"allowedFrameAncestors",[138,1142,1144],{"id":1143},"server-api-routes","Server API Routes",[116,1146,1147,1148,1151],{},"The module auto-registers the following routes (gated by the ",[123,1149,1150],{},"routes"," option):",[142,1153,1155,1156,1159],{"id":1154},"auth-routesauth","Auth (",[123,1157,1158],{},"routes.auth",")",[1161,1162,1163,1170,1175,1181,1187,1192,1197],"ul",{},[1164,1165,1166,1169],"li",{},[123,1167,1168],{},"POST \u002Fapi\u002Fsession\u002Flogin"," — cookie-session login",[1164,1171,1172],{},[123,1173,1174],{},"POST \u002Fapi\u002Fsession\u002Flogout",[1164,1176,1177,1180],{},[123,1178,1179],{},"GET \u002Fapi\u002Fsession\u002Fssh-keys"," — list caller's SSH keys",[1164,1182,1183,1186],{},[123,1184,1185],{},"POST \u002Fapi\u002Fsession\u002Fssh-keys"," — add an SSH key for the authenticated user",[1164,1188,1189],{},[123,1190,1191],{},"DELETE \u002Fapi\u002Fsession\u002Fssh-keys\u002F:keyId",[1164,1193,1194],{},[123,1195,1196],{},"POST \u002Fapi\u002Flogout",[1164,1198,1199,1202,1203,1206],{},[123,1200,1201],{},"GET \u002Fapi\u002Fme"," — returns ",[123,1204,1205],{},"{ email, name, isAdmin }"," for the cookie session",[142,1208,1210,1211,1159],{"id":1209},"webauthn-under-routesauth","WebAuthn (under ",[123,1212,1158],{},[1161,1214,1215,1224,1232,1238,1246],{},[1164,1216,1217,1220,1221],{},[123,1218,1219],{},"POST \u002Fapi\u002Fwebauthn\u002Fregister\u002Foptions"," · ",[123,1222,1223],{},"POST \u002Fapi\u002Fwebauthn\u002Fregister\u002Fverify",[1164,1225,1226,1220,1229],{},[123,1227,1228],{},"POST \u002Fapi\u002Fwebauthn\u002Flogin\u002Foptions",[123,1230,1231],{},"POST \u002Fapi\u002Fwebauthn\u002Flogin\u002Fverify",[1164,1233,1234,1237],{},[123,1235,1236],{},"GET \u002Fapi\u002Fwebauthn\u002Fcredentials"," — list the caller's registered credentials",[1164,1239,1240,1220,1243],{},[123,1241,1242],{},"POST \u002Fapi\u002Fwebauthn\u002Fcredentials\u002Fadd\u002Foptions",[123,1244,1245],{},"POST \u002Fapi\u002Fwebauthn\u002Fcredentials\u002Fadd\u002Fverify",[1164,1247,1248],{},[123,1249,1250],{},"DELETE \u002Fapi\u002Fwebauthn\u002Fcredentials\u002F:id",[142,1252,1254,1255,1159],{"id":1253},"oauth-oidc-routesoauth","OAuth \u002F OIDC (",[123,1256,1257],{},"routes.oauth",[1161,1259,1260,1266,1272,1277,1282,1287],{},[1164,1261,1262,1265],{},[123,1263,1264],{},"GET \u002Fauthorize"," — OAuth authorization endpoint",[1164,1267,1268,1271],{},[123,1269,1270],{},"POST \u002Ftoken"," — token exchange",[1164,1273,1274],{},[123,1275,1276],{},"POST \u002Frevoke",[1164,1278,1279],{},[123,1280,1281],{},"GET \u002Fuserinfo",[1164,1283,1284],{},[123,1285,1286],{},"GET \u002F.well-known\u002Fopenid-configuration",[1164,1288,1289],{},[123,1290,1291],{},"GET \u002F.well-known\u002Fjwks.json",[142,1293,1295,1296,1159],{"id":1294},"grants-routesgrants","Grants (",[123,1297,1298],{},"routes.grants",[1161,1300,1301,1312,1317,1323,1328,1339,1350,1358],{},[1164,1302,1303,1220,1306,1220,1309],{},[123,1304,1305],{},"GET \u002Fapi\u002Fgrants",[123,1307,1308],{},"POST \u002Fapi\u002Fgrants",[123,1310,1311],{},"GET \u002Fapi\u002Fgrants\u002F:id",[1164,1313,1314],{},[123,1315,1316],{},"POST \u002Fapi\u002Fgrants\u002F:id\u002Fapprove|deny|revoke|token|consume",[1164,1318,1319,1322],{},[123,1320,1321],{},"POST \u002Fapi\u002Fgrants\u002Fverify"," — verify an AuthZ-JWT",[1164,1324,1325],{},[123,1326,1327],{},"POST \u002Fapi\u002Fgrants\u002Fbatch",[1164,1329,1330,1220,1333,1220,1336],{},[123,1331,1332],{},"GET|POST \u002Fapi\u002Fdelegations",[123,1334,1335],{},"DELETE \u002Fapi\u002Fdelegations\u002F:id",[123,1337,1338],{},"POST \u002Fapi\u002Fdelegations\u002F:id\u002Fvalidate",[1164,1340,1341,1220,1344,1220,1347],{},[123,1342,1343],{},"GET \u002Fapi\u002Fshapes",[123,1345,1346],{},"GET \u002Fapi\u002Fshapes\u002F:cliId",[123,1348,1349],{},"POST \u002Fapi\u002Fshapes\u002Fresolve",[1164,1351,1352,1220,1355],{},[123,1353,1354],{},"GET|POST \u002Fapi\u002Fstanding-grants",[123,1356,1357],{},"DELETE \u002Fapi\u002Fstanding-grants\u002F:id",[1164,1359,1360],{},[123,1361,1362],{},"GET \u002Fapi\u002Fusers\u002F:email\u002Fagents",[142,1364,1366,1367,1159],{"id":1365},"agents-routesagent","Agents (",[123,1368,1369],{},"routes.agent",[1161,1371,1372,1383],{},[1164,1373,1374,1220,1377,1220,1380],{},[123,1375,1376],{},"POST \u002Fapi\u002Fagent\u002Fchallenge",[123,1378,1379],{},"POST \u002Fapi\u002Fagent\u002Fauthenticate",[123,1381,1382],{},"POST \u002Fapi\u002Fagent\u002Fenroll",[1164,1384,1385,1220,1388,1220,1391,1394],{},[123,1386,1387],{},"POST \u002Fapi\u002Fauth\u002Fchallenge",[123,1389,1390],{},"POST \u002Fapi\u002Fauth\u002Fauthenticate",[123,1392,1393],{},"POST \u002Fapi\u002Fauth\u002Fenroll"," — unified endpoints that work for agents and humans with SSH keys",[142,1396,1398,1399,1402,1403,1159],{"id":1397},"admin-routesadmin-requires-isadmin","Admin (",[123,1400,1401],{},"routes.admin",", requires ",[123,1404,1405],{},"isAdmin",[1161,1407,1408,1419,1427,1438],{},[1164,1409,1410,1220,1413,1220,1416],{},[123,1411,1412],{},"\u002Fapi\u002Fadmin\u002Fusers",[123,1414,1415],{},"\u002Fapi\u002Fadmin\u002Fusers\u002F:email",[123,1417,1418],{},"\u002Fapi\u002Fadmin\u002Fusers\u002F:email\u002Fcredentials|ssh-keys",[1164,1420,1421,1220,1424],{},[123,1422,1423],{},"\u002Fapi\u002Fadmin\u002Fagents",[123,1425,1426],{},"\u002Fapi\u002Fadmin\u002Fagents\u002F:id",[1164,1428,1429,1220,1432,1220,1435],{},[123,1430,1431],{},"\u002Fapi\u002Fadmin\u002Fsessions",[123,1433,1434],{},"\u002Fapi\u002Fadmin\u002Fsessions\u002F:familyId",[123,1436,1437],{},"\u002Fapi\u002Fadmin\u002Fsessions\u002Fuser\u002F:email",[1164,1439,1440,1220,1443],{},[123,1441,1442],{},"\u002Fapi\u002Fadmin\u002Fregistration-urls",[123,1444,1445],{},"\u002Fapi\u002Fadmin\u002Fregistration-urls\u002F:token",[142,1447,1449,1450,1452],{"id":1448},"federation-if-federationproviders-is-set","Federation (if ",[123,1451,1128],{}," is set)",[1161,1454,1455,1463],{},[1164,1456,1457,1220,1460],{},[123,1458,1459],{},"GET \u002Fauth\u002Ffederated\u002F:providerId",[123,1461,1462],{},"\u002Fauth\u002Ffederated\u002F:providerId\u002Fcallback",[1164,1464,1465],{},[123,1466,1467],{},"GET \u002Fapi\u002Ffederation\u002Fproviders",[138,1469,1471],{"id":1470},"built-in-pages","Built-in Pages",[116,1473,1474,1475,1478],{},"When ",[123,1476,1477],{},"pages: true"," (default), the module registers these Vue pages. A consuming app can override any by defining its own page with the same path:",[1161,1480,1481,1496,1511],{},[1164,1482,1483,1486,1487,1486,1490,1486,1493],{},[123,1484,1485],{},"\u002Flogin",", ",[123,1488,1489],{},"\u002Fregister",[123,1491,1492],{},"\u002Faccount",[123,1494,1495],{},"\u002Fadmin",[1164,1497,1498,1486,1501,1486,1504,1507,1508,1159],{},[123,1499,1500],{},"\u002Fgrants",[123,1502,1503],{},"\u002Fgrant-approval",[123,1505,1506],{},"\u002Fenroll"," (when ",[123,1509,1510],{},"grants.enablePages: true",[1164,1512,1513,1486,1516],{},[123,1514,1515],{},"\u002Fagents",[123,1517,1518],{},"\u002Fagents\u002F:email",[138,1520,1522],{"id":1521},"composables","Composables",[142,1524,1526],{"id":1525},"useidpauth",[123,1527,1528],{},"useIdpAuth()",[147,1530,1532],{"className":180,"code":1531,"language":182,"meta":152,"style":152},"const { user, loading, fetchUser, logout } = useIdpAuth()\n",[123,1533,1534],{"__ignoreMap":152},[156,1535,1536,1539,1542,1545,1547,1550,1552,1555,1557,1560,1562,1565,1568],{"class":158,"line":159},[156,1537,1538],{"class":481},"const",[156,1540,1541],{"class":204}," {",[156,1543,1544],{"class":200}," user",[156,1546,291],{"class":204},[156,1548,1549],{"class":200}," loading",[156,1551,291],{"class":204},[156,1553,1554],{"class":200}," fetchUser",[156,1556,291],{"class":204},[156,1558,1559],{"class":200}," logout ",[156,1561,307],{"class":204},[156,1563,1564],{"class":204}," =",[156,1566,1567],{"class":196}," useIdpAuth",[156,1569,1570],{"class":200},"()\n",[957,1572,1573,1586],{},[960,1574,1575],{},[963,1576,1577,1580,1583],{},[966,1578,1579],{},"Property",[966,1581,1582],{},"Type",[966,1584,1585],{},"Description",[973,1587,1588,1603,1622,1642],{},[963,1589,1590,1595,1600],{},[978,1591,1592],{},[123,1593,1594],{},"user",[978,1596,1597],{},[123,1598,1599],{},"Ref\u003C{ email, name, isAdmin } | null>",[978,1601,1602],{},"Cookie-session claims for the current user",[963,1604,1605,1610,1615],{},[978,1606,1607],{},[123,1608,1609],{},"loading",[978,1611,1612],{},[123,1613,1614],{},"Ref\u003Cboolean>",[978,1616,1617,1618,1621],{},"Whether ",[123,1619,1620],{},"fetchUser()"," is in flight",[963,1623,1624,1628,1633],{},[978,1625,1626],{},[123,1627,1620],{},[978,1629,1630],{},[123,1631,1632],{},"() => Promise\u003Cvoid>",[978,1634,1635,1636,1638,1639],{},"Hydrate ",[123,1637,1594],{}," from ",[123,1640,1641],{},"\u002Fapi\u002Fme",[963,1643,1644,1649,1653],{},[978,1645,1646],{},[123,1647,1648],{},"logout()",[978,1650,1651],{},[123,1652,1632],{},[978,1654,1655],{},"Destroy the cookie session",[142,1657,1659],{"id":1658},"usewebauthn",[123,1660,1661],{},"useWebAuthn()",[116,1663,1664,1665,1668],{},"Helper for browser-side passkey enrollment and login flows (wraps ",[123,1666,1667],{},"@simplewebauthn\u002Fbrowser","). Used by the built-in pages; available for custom UIs.",[138,1670,1672],{"id":1671},"multi-tenant-host-derived-rp","Multi-Tenant (Host-Derived RP)",[116,1674,1675,1676,1679,1680,1682,1683,1685,1686,1685,1688,1690],{},"The module supports hosting multiple IdP domains from a single deployment. RP config is resolved per request: if the incoming ",[123,1677,1678],{},"Host"," header is in ",[123,1681,1080],{},", the module overrides the static ",[123,1684,320],{},"\u002F",[123,1687,1068],{},[123,1689,1033],{}," for that request.",[147,1692,1694],{"className":180,"code":1693,"language":182,"meta":152,"style":152},"openapeIdp: {\n  rpHostAllowList: 'id.example.com,id.example.at',\n  \u002F\u002F rpID \u002F rpOrigin \u002F issuer are vestigial when the allow-list covers every host\n}\n",[123,1695,1696,1704,1719,1724],{"__ignoreMap":152},[156,1697,1698,1700,1702],{"class":158,"line":159},[156,1699,559],{"class":162},[156,1701,215],{"class":204},[156,1703,242],{"class":204},[156,1705,1706,1708,1710,1712,1715,1717],{"class":158,"line":208},[156,1707,696],{"class":162},[156,1709,215],{"class":204},[156,1711,253],{"class":204},[156,1713,1714],{"class":166},"id.example.com,id.example.at",[156,1716,221],{"class":204},[156,1718,231],{"class":204},[156,1720,1721],{"class":158,"line":234},[156,1722,1723],{"class":294},"  \u002F\u002F rpID \u002F rpOrigin \u002F issuer are vestigial when the allow-list covers every host\n",[156,1725,1726],{"class":158,"line":245},[156,1727,949],{"class":204},[116,1729,1730,1731,1734,1735,540],{},"The consuming app supplies a middleware that populates ",[123,1732,1733],{},"event.context.openapeRpConfig"," — all WebAuthn handlers read from that seam first before falling back to the static module config. See the full walkthrough in ",[120,1736,72],{"href":73},[138,1738,1740],{"id":1739},"storage-backend-interfaces","Storage Backend Interfaces",[116,1742,1743,1744,1747,1748,1751,1752,1755,1756,1759],{},"Each ",[123,1745,1746],{},"define\u003CName>Store()"," accepts a factory that receives the current ",[123,1749,1750],{},"H3Event"," and returns an instance of the matching interface from ",[123,1753,1754],{},"@openape\u002Fauth"," (user, credential, key, code, refresh-token, jti, webauthn-challenge, registration-url) or ",[123,1757,1758],{},"@openape\u002Fgrants"," (shape). The IdP module only imports the shape — you control persistence.",[116,1761,1762,1763,1766],{},"The reference ",[120,1764,135],{"href":132,"rel":1765},[134]," implements each store against Drizzle + libsql (Turso or local SQLite); fork that pattern if you want a persistent IdP quickly, or ship your own backend (Postgres, DynamoDB, etc).",[138,1768,1770],{"id":1769},"security-headers","Security Headers",[116,1772,1773],{},"The module installs these headers on every request:",[1161,1775,1776,1781,1786],{},[1164,1777,1778],{},[123,1779,1780],{},"X-Content-Type-Options: nosniff",[1164,1782,1783],{},[123,1784,1785],{},"Referrer-Policy: strict-origin-when-cross-origin",[1164,1787,1788,1791,1792,1795,1796,1798,1799,540],{},[123,1789,1790],{},"X-Frame-Options: DENY"," + ",[123,1793,1794],{},"Content-Security-Policy: frame-ancestors 'none'"," — unless ",[123,1797,1140],{}," is set, in which case X-Frame-Options is dropped and CSP carries ",[123,1800,1801],{},"frame-ancestors 'self' \u003Corigins>",[116,1803,1804,1805,540],{},"Session, auth, and admin routes additionally receive ",[123,1806,1807],{},"Cache-Control: no-store",[138,1809,1811],{"id":1810},"related","Related",[1161,1813,1814,1821,1827],{},[1164,1815,1816,1820],{},[120,1817,1818],{"href":61},[123,1819,125],{}," — Service-provider counterpart",[1164,1822,1823,1826],{},[120,1824,1825],{"href":57},"Grants"," — Grant model and AuthZ-JWT structure",[1164,1828,1829,1831],{},[120,1830,72],{"href":73}," — Host-derived RP config",[1833,1834,1835],"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 .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 .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":152,"searchDepth":159,"depth":208,"links":1837},[1838,1844,1845,1861,1862,1866,1867,1868,1869],{"id":140,"depth":208,"text":24,"children":1839},[1840,1841,1843],{"id":144,"depth":234,"text":145},{"id":173,"depth":234,"text":1842},"2. Add to nuxt.config.ts",{"id":331,"depth":234,"text":332},{"id":543,"depth":208,"text":544},{"id":1143,"depth":208,"text":1144,"children":1846},[1847,1849,1851,1853,1855,1857,1859],{"id":1154,"depth":234,"text":1848},"Auth (routes.auth)",{"id":1209,"depth":234,"text":1850},"WebAuthn (under routes.auth)",{"id":1253,"depth":234,"text":1852},"OAuth \u002F OIDC (routes.oauth)",{"id":1294,"depth":234,"text":1854},"Grants (routes.grants)",{"id":1365,"depth":234,"text":1856},"Agents (routes.agent)",{"id":1397,"depth":234,"text":1858},"Admin (routes.admin, requires isAdmin)",{"id":1448,"depth":234,"text":1860},"Federation (if federationProviders is set)",{"id":1470,"depth":208,"text":1471},{"id":1521,"depth":208,"text":1522,"children":1863},[1864,1865],{"id":1525,"depth":234,"text":1528},{"id":1658,"depth":234,"text":1661},{"id":1671,"depth":208,"text":1672},{"id":1739,"depth":208,"text":1740},{"id":1769,"depth":208,"text":1770},{"id":1810,"depth":208,"text":1811},"Build your own OpenApe Identity Provider as a Nuxt app.","md",null,{},{"title":68,"description":1870},"Hrbt9maTP-Ax8taxxbpKm5OmCLPntA_2XYPZGBJzQ5Q",[1877,1879],{"title":64,"path":65,"stem":66,"description":1878,"children":-1},"Privilege escalation with grant verification.",{"title":72,"path":73,"stem":74,"description":1880,"children":-1},"Serve multiple OpenApe IdP domains from a single Nuxt process.",1781287647231]