[{"data":1,"prerenderedAt":4431},["ShallowReactive",2],{"navLinks":3,"sidebar_docs_navigation_\u002Fdocs\u002Fiam":64,"navigation":257,"navLinks_footer":837,"\u002Fdocs\u002Fiam\u002Fessentials\u002Faccess-tokens_page":850,"\u002Fdocs\u002Fiam\u002Fessentials\u002Faccess-tokens_surround":2846,"\u002Fdocs\u002Fiam\u002Fessentials\u002Faccess-tokens":2849},{"id":4,"extension":5,"links":6,"meta":61,"stem":62,"__hash__":63},"navigationMenu\u002Fnavigation.json","json",[7,52,57],{"nested":8,"label":9,"icon":10,"to":11,"children":12},true,"Docs","i-lucide-book-open","\u002Fdocs\u002Fgetting-started",[13,19,26,32,39,45],{"label":14,"icon":15,"to":11,"description":16,"github":17,"badge":18},"Getting Started","i-lucide-rocket","An introduction to help you understand the core components.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fdocshub","Start Here",{"label":20,"icon":21,"to":22,"description":23,"github":24,"badge":25},"Auth H3 Client","i-lucide-key-round","\u002Fdocs\u002Fauth-h3client","Seamlessly enforce OAuth 2.0 authentication and session management integrated directly as the client of the IAM module.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fauth-h3client","Core",{"label":27,"icon":28,"to":29,"description":30,"github":31,"badge":25},"IAM","i-lucide-shield-check","\u002Fdocs\u002Fiam","Identity and Access Management featuring granular roles, permissions, and security policies.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fauth",{"label":33,"icon":34,"to":35,"description":36,"github":37,"badge":38},"Bot Detection","i-lucide-cpu","\u002Fdocs\u002Fbot-detection","Advanced behavioral analysis and request fingerprinting to stop malicious automated traffic.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fbot-detector","Security",{"label":40,"icon":41,"to":42,"description":43,"github":44,"badge":38},"Shield Base","i-lucide-database-zap","\u002Fdocs\u002Fshield-base","CLI and programmatic toolkit for compiling offline-ready IP intelligence databases from BGP, GeoIP, Tor, FireHOL, and other public threat feeds.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Fshield-base-cli",{"label":46,"icon":47,"to":48,"description":49,"github":50,"badge":51},"Utils","i-lucide-wrench","\u002Fdocs\u002Futils","A standard library of highly optimized helpers for formatting, validation, and core logic.","https:\u002F\u002Fgithub.com\u002FSergo706\u002Futils","Library",{"nested":53,"label":54,"icon":55,"to":56},false,"Blog","i-lucide-pen-line","\u002Fblog",{"nested":53,"label":58,"icon":59,"to":60},"Website","lucide:app-window-mac","https:\u002F\u002Friavzon.com",{},"navigation","gkaQ0xRGxSLrLyM3kttLe0oBwkrR1EBjlepF8LSbwF8",[65],{"title":9,"path":66,"stem":67,"children":68,"page":53},"\u002Fdocs","docs",[69],{"title":27,"path":29,"stem":70,"children":71},"docs\u002Fiam\u002Findex",[72,73,76,216,219,236,240],{"title":27,"path":29,"stem":70},{"title":14,"path":74,"stem":75},"\u002Fdocs\u002Fiam\u002Fgetting-started","docs\u002Fiam\u002F00.getting-started",{"title":77,"path":78,"stem":79,"children":80},"Essentials","\u002Fdocs\u002Fiam\u002Fessentials","docs\u002Fiam\u002F01.essentials\u002Findex",[81,82,86,90,94,98,102,106,110,114,118,122,126,130,134,138,142,146,150,154,158,162,166],{"title":77,"path":78,"stem":79},{"title":83,"path":84,"stem":85},"Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Ftokens","docs\u002Fiam\u002F01.essentials\u002F00.tokens",{"title":87,"path":88,"stem":89},"Access Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Faccess-tokens","docs\u002Fiam\u002F01.essentials\u002F01.access-tokens",{"title":91,"path":92,"stem":93},"Refresh Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Frefresh-tokens","docs\u002Fiam\u002F01.essentials\u002F02.refresh-tokens",{"title":95,"path":96,"stem":97},"Anomaly Detection","\u002Fdocs\u002Fiam\u002Fessentials\u002Fanomalies","docs\u002Fiam\u002F01.essentials\u002F03.anomalies",{"title":99,"path":100,"stem":101},"Signup","\u002Fdocs\u002Fiam\u002Fessentials\u002Fsignup","docs\u002Fiam\u002F01.essentials\u002F04.signup",{"title":103,"path":104,"stem":105},"Login","\u002Fdocs\u002Fiam\u002Fessentials\u002Flogin","docs\u002Fiam\u002F01.essentials\u002F05.login",{"title":107,"path":108,"stem":109},"Logout","\u002Fdocs\u002Fiam\u002Fessentials\u002Flogout","docs\u002Fiam\u002F01.essentials\u002F06.logout",{"title":111,"path":112,"stem":113},"OAuth","\u002Fdocs\u002Fiam\u002Fessentials\u002Foauth","docs\u002Fiam\u002F01.essentials\u002F07.oauth",{"title":115,"path":116,"stem":117},"Magic Links","\u002Fdocs\u002Fiam\u002Fessentials\u002Fmagic-links","docs\u002Fiam\u002F01.essentials\u002F08.magic-links",{"title":119,"path":120,"stem":121},"Emails","\u002Fdocs\u002Fiam\u002Fessentials\u002Femails","docs\u002Fiam\u002F01.essentials\u002F09.emails",{"title":123,"path":124,"stem":125},"MFA","\u002Fdocs\u002Fiam\u002Fessentials\u002Fmfa","docs\u002Fiam\u002F01.essentials\u002F10.mfa",{"title":127,"path":128,"stem":129},"Fingerprinting","\u002Fdocs\u002Fiam\u002Fessentials\u002Ffingerprinting","docs\u002Fiam\u002F01.essentials\u002F11.fingerprinting",{"title":131,"path":132,"stem":133},"Backend for Frontend","\u002Fdocs\u002Fiam\u002Fessentials\u002Fbff","docs\u002Fiam\u002F01.essentials\u002F12.bff",{"title":135,"path":136,"stem":137},"HMAC Authentication","\u002Fdocs\u002Fiam\u002Fessentials\u002Fhmac","docs\u002Fiam\u002F01.essentials\u002F13.hmac",{"title":139,"path":140,"stem":141},"XSS Protection","\u002Fdocs\u002Fiam\u002Fessentials\u002Fxss","docs\u002Fiam\u002F01.essentials\u002F14.xss",{"title":143,"path":144,"stem":145},"Logging","\u002Fdocs\u002Fiam\u002Fessentials\u002Flogging","docs\u002Fiam\u002F01.essentials\u002F15.logging",{"title":147,"path":148,"stem":149},"Rate Limiting","\u002Fdocs\u002Fiam\u002Fessentials\u002Frate-limiting","docs\u002Fiam\u002F01.essentials\u002F16.rate-limiting",{"title":151,"path":152,"stem":153},"Database","\u002Fdocs\u002Fiam\u002Fessentials\u002Fdatabase","docs\u002Fiam\u002F01.essentials\u002F17.database",{"title":155,"path":156,"stem":157},"Cookies","\u002Fdocs\u002Fiam\u002Fessentials\u002Fcookies","docs\u002Fiam\u002F01.essentials\u002F18.cookies",{"title":159,"path":160,"stem":161},"Service Startup","\u002Fdocs\u002Fiam\u002Fessentials\u002Fservice","docs\u002Fiam\u002F01.essentials\u002F19.service",{"title":163,"path":164,"stem":165},"Password Reset","\u002Fdocs\u002Fiam\u002Fessentials\u002Fpassword-reset","docs\u002Fiam\u002F01.essentials\u002F20.password-reset",{"title":167,"path":168,"stem":169,"children":170},"API Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi","docs\u002Fiam\u002F01.essentials\u002F21.api\u002Findex",[171,172,176,180,210,213],{"title":167,"path":168,"stem":169},{"title":173,"path":174,"stem":175},"Creating Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fcreation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F00.creation",{"title":177,"path":178,"stem":179},"Verifying Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fverification","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F01.verification",{"title":181,"path":182,"stem":183,"children":184},"Manage Tokens","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002Findex",[185,186,190,194,198,202,206],{"title":181,"path":182,"stem":183},{"title":187,"path":188,"stem":189},"Privileges","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fprivilege","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F00.privilege",{"title":191,"path":192,"stem":193},"Revocation","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Frevocation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F01.revocation",{"title":195,"path":196,"stem":197},"Rotation","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Frotation","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F02.rotation",{"title":199,"path":200,"stem":201},"IP Restriction","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fip-updates","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F03.ip-updates",{"title":203,"path":204,"stem":205},"Metadata","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Fmetadata","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F04.metadata",{"title":207,"path":208,"stem":209},"Token Listing","\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fmanagement\u002Flist","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F02.management\u002F05.list",{"title":147,"path":211,"stem":212},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Frate-limiting","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F03.rate-limiting",{"title":38,"path":214,"stem":215},"\u002Fdocs\u002Fiam\u002Fessentials\u002Fapi\u002Fsecurity","docs\u002Fiam\u002F01.essentials\u002F21.api\u002F04.security",{"title":38,"path":217,"stem":218},"\u002Fdocs\u002Fiam\u002Fsecurity","docs\u002Fiam\u002F02.security",{"title":220,"path":221,"stem":222,"children":223,"page":53},"Guides","\u002Fdocs\u002Fiam\u002Fguides","docs\u002Fiam\u002F03.guides",[224,228,232],{"title":225,"path":226,"stem":227},"Deployment","\u002Fdocs\u002Fiam\u002Fguides\u002Fdeployment","docs\u002Fiam\u002F03.guides\u002Fdeployment",{"title":229,"path":230,"stem":231},"Operation Scripts","\u002Fdocs\u002Fiam\u002Fguides\u002Foperation-scripts","docs\u002Fiam\u002F03.guides\u002Foperation-scripts",{"title":233,"path":234,"stem":235},"Role-Based Access Control","\u002Fdocs\u002Fiam\u002Fguides\u002Frbac","docs\u002Fiam\u002F03.guides\u002Frbac",{"title":237,"path":238,"stem":239},"Configuration","\u002Fdocs\u002Fiam\u002Fconfiguration","docs\u002Fiam\u002F04.configuration",{"title":241,"path":242,"stem":243,"children":244,"page":53},"Api","\u002Fdocs\u002Fiam\u002Fapi","docs\u002Fiam\u002F05.API",[245,249,253],{"title":246,"path":247,"stem":248},"API Reference","\u002Fdocs\u002Fiam\u002Fapi\u002Fapi","docs\u002Fiam\u002F05.API\u002F00.api",{"title":250,"path":251,"stem":252},"Middleware Reference","\u002Fdocs\u002Fiam\u002Fapi\u002Fmiddlewares","docs\u002Fiam\u002F05.API\u002F02.middlewares",{"title":254,"path":255,"stem":256},"Routes Reference","\u002Fdocs\u002Fiam\u002Fapi\u002Froutes","docs\u002Fiam\u002F05.API\u002F03.routes",[258],{"title":9,"path":66,"stem":67,"children":259,"page":53},[260,398,516,521,577,644],{"title":20,"path":22,"stem":261,"children":262},"docs\u002Fauth-h3client\u002Findex",[263,264,273,307,331,353,356,376,379],{"title":20,"path":22,"stem":261},{"title":14,"path":265,"stem":266,"children":267},"\u002Fdocs\u002Fauth-h3client\u002Fgetting-started","docs\u002Fauth-h3client\u002F00.getting-started\u002Findex",[268,269],{"title":14,"path":265,"stem":266},{"title":270,"path":271,"stem":272},"Nuxt Module","\u002Fdocs\u002Fauth-h3client\u002Fgetting-started\u002Fnuxt","docs\u002Fauth-h3client\u002F00.getting-started\u002F00.nuxt",{"title":77,"path":274,"stem":275,"children":276},"\u002Fdocs\u002Fauth-h3client\u002Fessentials","docs\u002Fauth-h3client\u002F01.essentials\u002Findex",[277,278,282,286,290,294,298,301,304],{"title":77,"path":274,"stem":275},{"title":279,"path":280,"stem":281},"Session Management","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fsession","docs\u002Fauth-h3client\u002F01.essentials\u002F00.session",{"title":283,"path":284,"stem":285},"Route Protection","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Froute-protection","docs\u002Fauth-h3client\u002F01.essentials\u002F01.route-protection",{"title":287,"path":288,"stem":289},"CSRF Protection","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fcsrf","docs\u002Fauth-h3client\u002F01.essentials\u002F02.csrf",{"title":291,"path":292,"stem":293},"Auth Flows","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fauth-flows","docs\u002Fauth-h3client\u002F01.essentials\u002F03.auth-flows",{"title":295,"path":296,"stem":297},"OAuth and OIDC","\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Foauth","docs\u002Fauth-h3client\u002F01.essentials\u002F04.oauth",{"title":33,"path":299,"stem":300},"\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fbot-detection","docs\u002Fauth-h3client\u002F01.essentials\u002F05.bot-detection",{"title":155,"path":302,"stem":303},"\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Fcookies","docs\u002Fauth-h3client\u002F01.essentials\u002F06.cookies",{"title":143,"path":305,"stem":306},"\u002Fdocs\u002Fauth-h3client\u002Fessentials\u002Flogging","docs\u002Fauth-h3client\u002F01.essentials\u002F07.logging",{"title":123,"path":308,"stem":309,"children":310},"\u002Fdocs\u002Fauth-h3client\u002Fmfa","docs\u002Fauth-h3client\u002F02.mfa\u002Findex",[311,312,316,319,323,327],{"title":123,"path":308,"stem":309},{"title":313,"path":314,"stem":315},"Built-in MFA","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fbuilt-in-flow","docs\u002Fauth-h3client\u002F02.mfa\u002F01.built-in-flow",{"title":163,"path":317,"stem":318},"\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fpassword-reset","docs\u002Fauth-h3client\u002F02.mfa\u002F02.password-reset",{"title":320,"path":321,"stem":322},"Email Change","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Femail-change","docs\u002Fauth-h3client\u002F02.mfa\u002F03.email-change",{"title":324,"path":325,"stem":326},"Custom MFA Flow","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fcustom-flow","docs\u002Fauth-h3client\u002F02.mfa\u002F04.custom-flow",{"title":328,"path":329,"stem":330},"Client-Side MFA","\u002Fdocs\u002Fauth-h3client\u002Fmfa\u002Fclient-side","docs\u002Fauth-h3client\u002F02.mfa\u002F05.client-side",{"title":332,"path":333,"stem":334,"children":335},"Client-side","\u002Fdocs\u002Fauth-h3client\u002Fclient","docs\u002Fauth-h3client\u002F03.client\u002Findex",[336,337,341,345,349],{"title":332,"path":333,"stem":334},{"title":338,"path":339,"stem":340},"useAuthData","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fuse-auth-data","docs\u002Fauth-h3client\u002F03.client\u002F00.use-auth-data",{"title":342,"path":343,"stem":344},"useMagicLink","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fuse-magic-link","docs\u002Fauth-h3client\u002F03.client\u002F01.use-magic-link",{"title":346,"path":347,"stem":348},"executeRequest","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fexecute-request","docs\u002Fauth-h3client\u002F03.client\u002F02.execute-request",{"title":350,"path":351,"stem":352},"getCsrfToken","\u002Fdocs\u002Fauth-h3client\u002Fclient\u002Fget-csrf-token","docs\u002Fauth-h3client\u002F03.client\u002F03.get-csrf-token",{"title":38,"path":354,"stem":355},"\u002Fdocs\u002Fauth-h3client\u002Fsecurity","docs\u002Fauth-h3client\u002F04.security",{"title":220,"path":357,"stem":358,"children":359,"page":53},"\u002Fdocs\u002Fauth-h3client\u002Fguides","docs\u002Fauth-h3client\u002F05.guides",[360,364,368,372],{"title":361,"path":362,"stem":363},"H3 and Nitro Setup","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fh3-nitro","docs\u002Fauth-h3client\u002F05.guides\u002F00.h3-nitro",{"title":365,"path":366,"stem":367},"HMAC Inter-service Auth","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fhmac","docs\u002Fauth-h3client\u002F05.guides\u002Fhmac",{"title":369,"path":370,"stem":371},"Image Upload","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fimage-upload","docs\u002Fauth-h3client\u002F05.guides\u002Fimage-upload",{"title":373,"path":374,"stem":375},"mTLS Configuration","\u002Fdocs\u002Fauth-h3client\u002Fguides\u002Fmtls","docs\u002Fauth-h3client\u002F05.guides\u002Fmtls",{"title":237,"path":377,"stem":378},"\u002Fdocs\u002Fauth-h3client\u002Fconfiguration","docs\u002Fauth-h3client\u002F06.configuration",{"title":246,"path":380,"stem":381,"children":382},"\u002Fdocs\u002Fauth-h3client\u002Fapi","docs\u002Fauth-h3client\u002F07.api\u002Findex",[383,384,387,390,394],{"title":246,"path":380,"stem":381},{"title":254,"path":385,"stem":386},"\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fcontrollers","docs\u002Fauth-h3client\u002F07.api\u002F00.controllers",{"title":250,"path":388,"stem":389},"\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fmiddleware","docs\u002Fauth-h3client\u002F07.api\u002F01.middleware",{"title":391,"path":392,"stem":393},"Client-side Reference","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Fcomposables","docs\u002Fauth-h3client\u002F07.api\u002F02.composables",{"title":395,"path":396,"stem":397},"Utilities","\u002Fdocs\u002Fauth-h3client\u002Fapi\u002Futilities","docs\u002Fauth-h3client\u002F07.api\u002F03.utilities",{"title":399,"path":35,"stem":400,"children":401},"Bot Detector","docs\u002Fbot-detection\u002Findex",[402,403,406,410,414,433,507,510,513],{"title":399,"path":35,"stem":400},{"title":14,"path":404,"stem":405},"\u002Fdocs\u002Fbot-detection\u002Fgetting-started","docs\u002Fbot-detection\u002F00.getting-started",{"title":407,"path":408,"stem":409},"CLI","\u002Fdocs\u002Fbot-detection\u002Fcli","docs\u002Fbot-detection\u002F01.cli",{"title":411,"path":412,"stem":413},"Data Sources","\u002Fdocs\u002Fbot-detection\u002Fdata-sources","docs\u002Fbot-detection\u002F02.data-sources",{"title":220,"path":415,"stem":416,"children":417,"page":53},"\u002Fdocs\u002Fbot-detection\u002Fguides","docs\u002Fbot-detection\u002F03.guides",[418,422,426,429],{"title":419,"path":420,"stem":421},"Custom Checkers","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fcustom","docs\u002Fbot-detection\u002F03.guides\u002FCUSTOM",{"title":423,"path":424,"stem":425},"Scheduling Database Generation","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fgenerate","docs\u002Fbot-detection\u002F03.guides\u002FGENERATE",{"title":143,"path":427,"stem":428},"\u002Fdocs\u002Fbot-detection\u002Fguides\u002Flogging","docs\u002Fbot-detection\u002F03.guides\u002FLOGGING",{"title":430,"path":431,"stem":432},"Score Modes and Reputation Healing","\u002Fdocs\u002Fbot-detection\u002Fguides\u002Fscore","docs\u002Fbot-detection\u002F03.guides\u002FSCORE",{"title":434,"path":435,"stem":436,"children":437},"Checkers","\u002Fdocs\u002Fbot-detection\u002Fcheckers","docs\u002Fbot-detection\u002F04.checkers\u002Findex",[438,439,443,447,451,455,459,463,467,471,475,479,483,487,491,495,499,503],{"title":434,"path":435,"stem":436},{"title":440,"path":441,"stem":442},"IP Validation","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fip-validation","docs\u002Fbot-detection\u002F04.checkers\u002F01.ip-validation",{"title":444,"path":445,"stem":446},"Good \u002F Bad Bot Verification","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fgood-bots","docs\u002Fbot-detection\u002F04.checkers\u002F02.good-bots",{"title":448,"path":449,"stem":450},"Browser & Device Fingerprint","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fbrowser-device","docs\u002Fbot-detection\u002F04.checkers\u002F03.browser-device",{"title":452,"path":453,"stem":454},"Locale Map","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Flocale-map","docs\u002Fbot-detection\u002F04.checkers\u002F04.locale-map",{"title":456,"path":457,"stem":458},"Known Threats","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-threats","docs\u002Fbot-detection\u002F04.checkers\u002F05.known-threats",{"title":460,"path":461,"stem":462},"ASN Classification","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fasn-classification","docs\u002Fbot-detection\u002F04.checkers\u002F06.asn-classification",{"title":464,"path":465,"stem":466},"Tor Analysis","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Ftor-analysis","docs\u002Fbot-detection\u002F04.checkers\u002F07.tor-analysis",{"title":468,"path":469,"stem":470},"Timezone Consistency","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Ftimezone-consistency","docs\u002Fbot-detection\u002F04.checkers\u002F08.timezone-consistency",{"title":472,"path":473,"stem":474},"Honeypot","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fhoneypot","docs\u002Fbot-detection\u002F04.checkers\u002F09.honeypot",{"title":476,"path":477,"stem":478},"Known Bad IPs","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-bad-ips","docs\u002Fbot-detection\u002F04.checkers\u002F10.known-bad-ips",{"title":480,"path":481,"stem":482},"Behavior Rate","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fbehavior-rate","docs\u002Fbot-detection\u002F04.checkers\u002F11.behavior-rate",{"title":484,"path":485,"stem":486},"Proxy \u002F ISP \u002F Cookie","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fproxy-isp-cookies","docs\u002Fbot-detection\u002F04.checkers\u002F12.proxy-isp-cookies",{"title":488,"path":489,"stem":490},"Session Coherence","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fsession-coherence","docs\u002Fbot-detection\u002F04.checkers\u002F13.session-coherence",{"title":492,"path":493,"stem":494},"Velocity Fingerprint","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fvelocity-fingerprint","docs\u002Fbot-detection\u002F04.checkers\u002F14.velocity-fingerprint",{"title":496,"path":497,"stem":498},"UA & Header Analysis","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fua-header","docs\u002Fbot-detection\u002F04.checkers\u002F15.ua-header",{"title":500,"path":501,"stem":502},"Geolocation","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fgeolocation","docs\u002Fbot-detection\u002F04.checkers\u002F16.geolocation",{"title":504,"path":505,"stem":506},"Known Bad User-Agents","\u002Fdocs\u002Fbot-detection\u002Fcheckers\u002Fknown-bad-ua","docs\u002Fbot-detection\u002F04.checkers\u002F17.known-bad-ua",{"title":38,"path":508,"stem":509},"\u002Fdocs\u002Fbot-detection\u002Fsecurity","docs\u002Fbot-detection\u002F04.security",{"title":246,"path":511,"stem":512},"\u002Fdocs\u002Fbot-detection\u002Fapi","docs\u002Fbot-detection\u002F05.api",{"title":237,"path":514,"stem":515},"\u002Fdocs\u002Fbot-detection\u002Fconfiguration","docs\u002Fbot-detection\u002F06.configuration",{"title":517,"path":11,"stem":518,"children":519},"Introduction","docs\u002Fgetting-started\u002Findex",[520],{"title":517,"path":11,"stem":518},{"title":27,"path":29,"stem":70,"children":522},[523,524,525,565,566,571,572],{"title":27,"path":29,"stem":70},{"title":14,"path":74,"stem":75},{"title":77,"path":78,"stem":79,"children":526},[527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549],{"title":77,"path":78,"stem":79},{"title":83,"path":84,"stem":85},{"title":87,"path":88,"stem":89},{"title":91,"path":92,"stem":93},{"title":95,"path":96,"stem":97},{"title":99,"path":100,"stem":101},{"title":103,"path":104,"stem":105},{"title":107,"path":108,"stem":109},{"title":111,"path":112,"stem":113},{"title":115,"path":116,"stem":117},{"title":119,"path":120,"stem":121},{"title":123,"path":124,"stem":125},{"title":127,"path":128,"stem":129},{"title":131,"path":132,"stem":133},{"title":135,"path":136,"stem":137},{"title":139,"path":140,"stem":141},{"title":143,"path":144,"stem":145},{"title":147,"path":148,"stem":149},{"title":151,"path":152,"stem":153},{"title":155,"path":156,"stem":157},{"title":159,"path":160,"stem":161},{"title":163,"path":164,"stem":165},{"title":167,"path":168,"stem":169,"children":550},[551,552,553,554,563,564],{"title":167,"path":168,"stem":169},{"title":173,"path":174,"stem":175},{"title":177,"path":178,"stem":179},{"title":181,"path":182,"stem":183,"children":555},[556,557,558,559,560,561,562],{"title":181,"path":182,"stem":183},{"title":187,"path":188,"stem":189},{"title":191,"path":192,"stem":193},{"title":195,"path":196,"stem":197},{"title":199,"path":200,"stem":201},{"title":203,"path":204,"stem":205},{"title":207,"path":208,"stem":209},{"title":147,"path":211,"stem":212},{"title":38,"path":214,"stem":215},{"title":38,"path":217,"stem":218},{"title":220,"path":221,"stem":222,"children":567,"page":53},[568,569,570],{"title":225,"path":226,"stem":227},{"title":229,"path":230,"stem":231},{"title":233,"path":234,"stem":235},{"title":237,"path":238,"stem":239},{"title":241,"path":242,"stem":243,"children":573,"page":53},[574,575,576],{"title":246,"path":247,"stem":248},{"title":250,"path":251,"stem":252},{"title":254,"path":255,"stem":256},{"title":40,"path":42,"stem":578,"children":579},"docs\u002Fshield-base\u002Findex",[580,581,584,588,629,633,637,641],{"title":40,"path":42,"stem":578},{"title":14,"path":582,"stem":583},"\u002Fdocs\u002Fshield-base\u002Fgetting-started","docs\u002Fshield-base\u002F00.getting-started",{"title":585,"path":586,"stem":587},"CLI Reference","\u002Fdocs\u002Fshield-base\u002Fcli","docs\u002Fshield-base\u002F01.cli",{"title":411,"path":589,"stem":590,"children":591},"\u002Fdocs\u002Fshield-base\u002Fdata-sources","docs\u002Fshield-base\u002F02.data-sources\u002Findex",[592,593,597,601,605,609,613,617,621,625],{"title":411,"path":589,"stem":590},{"title":594,"path":595,"stem":596},"BGP \u002F ASN","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fbgp","docs\u002Fshield-base\u002F02.data-sources\u002Fbgp",{"title":598,"path":599,"stem":600},"City Geolocation","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcity","docs\u002Fshield-base\u002F02.data-sources\u002Fcity",{"title":602,"path":603,"stem":604},"Country Geolocation","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcountry","docs\u002Fshield-base\u002F02.data-sources\u002Fcountry",{"title":606,"path":607,"stem":608},"Verified Crawlers","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fcrawlers","docs\u002Fshield-base\u002F02.data-sources\u002Fcrawlers",{"title":610,"path":611,"stem":612},"Disposable Emails","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Femail","docs\u002Fshield-base\u002F02.data-sources\u002Femail",{"title":614,"path":615,"stem":616},"FireHOL Threat Intelligence","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Ffirehol","docs\u002Fshield-base\u002F02.data-sources\u002Ffirehol",{"title":618,"path":619,"stem":620},"Proxy Detection","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fproxy","docs\u002Fshield-base\u002F02.data-sources\u002Fproxy",{"title":622,"path":623,"stem":624},"Tor Nodes","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Ftor","docs\u002Fshield-base\u002F02.data-sources\u002Ftor",{"title":626,"path":627,"stem":628},"Suspicious User-Agents","\u002Fdocs\u002Fshield-base\u002Fdata-sources\u002Fuseragent","docs\u002Fshield-base\u002F02.data-sources\u002Fuseragent",{"title":630,"path":631,"stem":632},"Programmatic Usage","\u002Fdocs\u002Fshield-base\u002Fusage","docs\u002Fshield-base\u002F03.usage",{"title":634,"path":635,"stem":636},"Custom Data Sources","\u002Fdocs\u002Fshield-base\u002Fcustom-data-sources","docs\u002Fshield-base\u002F04.custom-data-sources",{"title":638,"path":639,"stem":640},"TypeScript Types","\u002Fdocs\u002Fshield-base\u002Ftypes","docs\u002Fshield-base\u002F05.types",{"title":246,"path":642,"stem":643},"\u002Fdocs\u002Fshield-base\u002Fapi","docs\u002Fshield-base\u002F06.api",{"title":395,"path":48,"stem":645,"children":646},"docs\u002Futils\u002Findex",[647,648,665,698,795],{"title":395,"path":48,"stem":645},{"title":649,"path":650,"stem":651,"children":652,"page":53},"Eslint","\u002Fdocs\u002Futils\u002Feslint","docs\u002Futils\u002Feslint",[653,657,661],{"title":654,"path":655,"stem":656},"React Config","\u002Fdocs\u002Futils\u002Feslint\u002Freact","docs\u002Futils\u002Feslint\u002Freact",{"title":658,"path":659,"stem":660},"TypeScript Config","\u002Fdocs\u002Futils\u002Feslint\u002Ftypescript","docs\u002Futils\u002Feslint\u002Ftypescript",{"title":662,"path":663,"stem":664},"Vue Config","\u002Fdocs\u002Futils\u002Feslint\u002Fvue","docs\u002Futils\u002Feslint\u002Fvue",{"title":666,"path":667,"stem":668,"children":669,"page":53},"Server","\u002Fdocs\u002Futils\u002Fserver","docs\u002Futils\u002Fserver",[670,674,678,682,686,690,694],{"title":671,"path":672,"stem":673},"Encryption","\u002Fdocs\u002Futils\u002Fserver\u002Fencryption","docs\u002Futils\u002Fserver\u002Fencryption",{"title":675,"path":676,"stem":677},"Path Resolver","\u002Fdocs\u002Futils\u002Fserver\u002Fpathresolver","docs\u002Futils\u002Fserver\u002FpathResolver",{"title":679,"path":680,"stem":681},"File Replacements","\u002Fdocs\u002Futils\u002Fserver\u002Freplace","docs\u002Futils\u002Fserver\u002Freplace",{"title":683,"path":684,"stem":685},"run","\u002Fdocs\u002Futils\u002Fserver\u002Frun","docs\u002Futils\u002Fserver\u002Frun",{"title":687,"path":688,"stem":689},"scheduleTask","\u002Fdocs\u002Futils\u002Fserver\u002Fscheduletask","docs\u002Futils\u002Fserver\u002FscheduleTask",{"title":691,"path":692,"stem":693},"spawnRun","\u002Fdocs\u002Futils\u002Fserver\u002Fspawnrun","docs\u002Futils\u002Fserver\u002FspawnRun",{"title":695,"path":696,"stem":697},"uploadCsv","\u002Fdocs\u002Futils\u002Fserver\u002Fuploadcsv","docs\u002Futils\u002Fserver\u002FuploadCsv",{"title":699,"path":700,"stem":701,"children":702,"page":53},"Shared","\u002Fdocs\u002Futils\u002Fshared","docs\u002Futils\u002Fshared",[703,707,711,715,719,723,727,731,735,739,743,747,751,755,759,763,767,771,775,779,783,787,791],{"title":704,"path":705,"stem":706},"BatchQueue","\u002Fdocs\u002Futils\u002Fshared\u002Fbatchqueue","docs\u002Futils\u002Fshared\u002FbatchQueue",{"title":708,"path":709,"stem":710},"capitalize","\u002Fdocs\u002Futils\u002Fshared\u002Fcapitalize","docs\u002Futils\u002Fshared\u002Fcapitalize",{"title":712,"path":713,"stem":714},"chunkProcess","\u002Fdocs\u002Futils\u002Fshared\u002Fchunkprocess","docs\u002Futils\u002Fshared\u002FchunkProcess",{"title":716,"path":717,"stem":718},"cleanObject","\u002Fdocs\u002Futils\u002Fshared\u002Fcleanobject","docs\u002Futils\u002Fshared\u002FcleanObject",{"title":720,"path":721,"stem":722},"createConfigManager","\u002Fdocs\u002Futils\u002Fshared\u002Fconfigurationdefiner","docs\u002Futils\u002Fshared\u002FconfigurationDefiner",{"title":724,"path":725,"stem":726},"debounce","\u002Fdocs\u002Futils\u002Fshared\u002Fdebounce","docs\u002Futils\u002Fshared\u002Fdebounce",{"title":728,"path":729,"stem":730},"ensureArray","\u002Fdocs\u002Futils\u002Fshared\u002Fensurearray","docs\u002Futils\u002Fshared\u002FensureArray",{"title":732,"path":733,"stem":734},"fetchWithRetry","\u002Fdocs\u002Futils\u002Fshared\u002Ffetchwithretry","docs\u002Futils\u002Fshared\u002FfetchWithRetry",{"title":736,"path":737,"stem":738},"filterEmptyValues","\u002Fdocs\u002Futils\u002Fshared\u002Ffilteremptyvalues","docs\u002Futils\u002Fshared\u002FfilterEmptyValues",{"title":740,"path":741,"stem":742},"findStringsInObject","\u002Fdocs\u002Futils\u002Fshared\u002Ffindobjectvalues","docs\u002Futils\u002Fshared\u002FfindObjectValues",{"title":744,"path":745,"stem":746},"fisherYatesShuffle","\u002Fdocs\u002Futils\u002Fshared\u002Ffisheryatesshuffle","docs\u002Futils\u002Fshared\u002FfisherYatesShuffle",{"title":748,"path":749,"stem":750},"getRandomImage","\u002Fdocs\u002Futils\u002Fshared\u002Fgetrandomimage","docs\u002Futils\u002Fshared\u002FgetRandomImage",{"title":752,"path":753,"stem":754},"isObjectHasValues","\u002Fdocs\u002Futils\u002Fshared\u002Fisobjecthasvalues","docs\u002Futils\u002Fshared\u002FisObjectHasValues",{"title":756,"path":757,"stem":758},"isAsyncOrPromise","\u002Fdocs\u002Futils\u002Fshared\u002Fispromise","docs\u002Futils\u002Fshared\u002FisPromise",{"title":760,"path":761,"stem":762},"MiniCache","\u002Fdocs\u002Futils\u002Fshared\u002Fminicache","docs\u002Futils\u002Fshared\u002FminiCache",{"title":764,"path":765,"stem":766},"parseCookies","\u002Fdocs\u002Futils\u002Fshared\u002Fparserawcookies","docs\u002Futils\u002Fshared\u002FparseRawCookies",{"title":768,"path":769,"stem":770},"safeAction","\u002Fdocs\u002Futils\u002Fshared\u002Fpromiselocker","docs\u002Futils\u002Fshared\u002FpromiseLocker",{"title":772,"path":773,"stem":774},"Random","\u002Fdocs\u002Futils\u002Fshared\u002Frandom","docs\u002Futils\u002Fshared\u002Frandom",{"title":776,"path":777,"stem":778},"range","\u002Fdocs\u002Futils\u002Fshared\u002Frange","docs\u002Futils\u002Fshared\u002Frange",{"title":780,"path":781,"stem":782},"rateLimiters","\u002Fdocs\u002Futils\u002Fshared\u002Fratelimiters","docs\u002Futils\u002Fshared\u002FrateLimiters",{"title":784,"path":785,"stem":786},"safeObjectMerge","\u002Fdocs\u002Futils\u002Fshared\u002Fsafemerge","docs\u002Futils\u002Fshared\u002FsafeMerge",{"title":788,"path":789,"stem":790},"textTruncation","\u002Fdocs\u002Futils\u002Fshared\u002Ftexttruncation","docs\u002Futils\u002Fshared\u002FtextTruncation",{"title":792,"path":793,"stem":794},"validateZodSchema","\u002Fdocs\u002Futils\u002Fshared\u002Fvalidatezodschema","docs\u002Futils\u002Fshared\u002FvalidateZodSchema",{"title":796,"path":797,"stem":798,"children":799},"Utility Types","\u002Fdocs\u002Futils\u002Ftypes","docs\u002Futils\u002Ftypes\u002Findex",[800,801,805,809,813,817,821,825,829,833],{"title":796,"path":797,"stem":798},{"title":802,"path":803,"stem":804},"Brand","\u002Fdocs\u002Futils\u002Ftypes\u002Fbrand","docs\u002Futils\u002Ftypes\u002FBrand",{"title":806,"path":807,"stem":808},"DeepPartial","\u002Fdocs\u002Futils\u002Ftypes\u002Fdeeppartial","docs\u002Futils\u002Ftypes\u002FDeepPartial",{"title":810,"path":811,"stem":812},"Merge","\u002Fdocs\u002Futils\u002Ftypes\u002Fmerge","docs\u002Futils\u002Ftypes\u002FMerge",{"title":814,"path":815,"stem":816},"NonNullable","\u002Fdocs\u002Futils\u002Ftypes\u002Fnonnullable","docs\u002Futils\u002Ftypes\u002FNonNullable",{"title":818,"path":819,"stem":820},"Prettify","\u002Fdocs\u002Futils\u002Ftypes\u002Fprettify","docs\u002Futils\u002Ftypes\u002FPrettify",{"title":822,"path":823,"stem":824},"PromiseType","\u002Fdocs\u002Futils\u002Ftypes\u002Fpromisetype","docs\u002Futils\u002Ftypes\u002FPromiseType",{"title":826,"path":827,"stem":828},"RequireKeys","\u002Fdocs\u002Futils\u002Ftypes\u002Frequirekeys","docs\u002Futils\u002Ftypes\u002FRequireKeys",{"title":830,"path":831,"stem":832},"StandardResponse","\u002Fdocs\u002Futils\u002Ftypes\u002Fstandardresponse","docs\u002Futils\u002Ftypes\u002FStandardResponse",{"title":834,"path":835,"stem":836},"ValueOf","\u002Fdocs\u002Futils\u002Ftypes\u002Fvalueof","docs\u002Futils\u002Ftypes\u002FValueOf",{"id":4,"extension":5,"links":838,"meta":849,"stem":62,"__hash__":63},[839,847,848],{"nested":8,"label":9,"icon":10,"to":11,"children":840},[841,842,843,844,845,846],{"label":14,"icon":15,"to":11,"description":16,"github":17,"badge":18},{"label":20,"icon":21,"to":22,"description":23,"github":24,"badge":25},{"label":27,"icon":28,"to":29,"description":30,"github":31,"badge":25},{"label":33,"icon":34,"to":35,"description":36,"github":37,"badge":38},{"label":40,"icon":41,"to":42,"description":43,"github":44,"badge":38},{"label":46,"icon":47,"to":48,"description":49,"github":50,"badge":51},{"nested":53,"label":54,"icon":55,"to":56},{"nested":53,"label":58,"icon":59,"to":60},{},{"id":851,"title":87,"body":852,"description":2839,"extension":2840,"icon":28,"meta":2841,"module":2842,"navigation":8,"path":88,"rawbody":2843,"seo":2844,"stem":89,"__hash__":2845},"docs\u002Fdocs\u002Fiam\u002F01.essentials\u002F01.access-tokens.md",{"type":853,"value":854,"toc":2818},"minimark",[855,864,876,879,884,895,1059,1160,1166,1168,1172,1333,1358,1364,1366,1370,1472,1530,1533,1607,1613,1709,1711,1715,1722,1753,1760,1852,1855,1857,1860,1867,1876,1879,1913,2131,2139,2227,2248,2252,2259,2300,2309,2406,2409,2416,2418,2421,2427,2431,2444,2540,2546,2550,2558,2566,2569,2585,2587,2591,2601,2797,2814],[856,857,858,859,863],"p",{},"Access tokens are short-lived signed JWTs. The service uses them as the primary credential for protected routes. Every access token is paired with a refresh token and a ",[860,861,862],"code",{},"canary_id"," cookie, none of the three work in isolation.",[856,865,866,867,870,871,875],{},"The service signs tokens with ",[860,868,869],{},"jwt.jwt_secret_key"," and caches every verified token in an LRU cache. Verification requires the token to both pass the cryptographic check ",[872,873,874],"strong",{},"and"," exist in that cache. This design gives you a cheap revocation path without touching the database.",[877,878],"hr",{},[880,881,883],"h2",{"id":882},"payload","Payload",[856,885,886,887,890,891,894],{},"When you call ",[860,888,889],{},"generateAccessToken",", the service builds the payload from three sources merged in order: the fixed identity fields, your ",[860,892,893],{},"jwt.access_tokens.payload"," config object, and the token-specific claims the JWT library adds.",[896,897,901],"pre",{"className":898,"code":899,"language":5,"meta":900,"style":900},"language-json shiki shiki-themes light-plus light-plus dracula","{\n  \"visitor\": \"vis_abc123\",\n  \"roles\": [\"user\", \"admin\"],\n  \"sub\": \"42\",\n  \"jti\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"iat\": 1710000000,\n  \"exp\": 1710000900\n}\n","",[860,902,903,912,943,978,999,1020,1038,1053],{"__ignoreMap":900},[904,905,908],"span",{"class":906,"line":907},"line",1,[904,909,911],{"class":910},"sDd4n","{\n",[904,913,915,919,923,926,930,934,938,940],{"class":906,"line":914},2,[904,916,918],{"class":917},"saJyd","  \"",[904,920,922],{"class":921},"s_W10","visitor",[904,924,925],{"class":917},"\"",[904,927,929],{"class":928},"saOXh",":",[904,931,933],{"class":932},"sFkSl"," \"",[904,935,937],{"class":936},"sFB1V","vis_abc123",[904,939,925],{"class":932},[904,941,942],{"class":910},",\n",[904,944,946,948,951,953,955,958,960,963,965,968,970,973,975],{"class":906,"line":945},3,[904,947,918],{"class":917},[904,949,950],{"class":921},"roles",[904,952,925],{"class":917},[904,954,929],{"class":928},[904,956,957],{"class":910}," [",[904,959,925],{"class":932},[904,961,962],{"class":936},"user",[904,964,925],{"class":932},[904,966,967],{"class":910},", ",[904,969,925],{"class":932},[904,971,972],{"class":936},"admin",[904,974,925],{"class":932},[904,976,977],{"class":910},"],\n",[904,979,981,983,986,988,990,992,995,997],{"class":906,"line":980},4,[904,982,918],{"class":917},[904,984,985],{"class":921},"sub",[904,987,925],{"class":917},[904,989,929],{"class":928},[904,991,933],{"class":932},[904,993,994],{"class":936},"42",[904,996,925],{"class":932},[904,998,942],{"class":910},[904,1000,1002,1004,1007,1009,1011,1013,1016,1018],{"class":906,"line":1001},5,[904,1003,918],{"class":917},[904,1005,1006],{"class":921},"jti",[904,1008,925],{"class":917},[904,1010,929],{"class":928},[904,1012,933],{"class":932},[904,1014,1015],{"class":936},"550e8400-e29b-41d4-a716-446655440000",[904,1017,925],{"class":932},[904,1019,942],{"class":910},[904,1021,1023,1025,1028,1030,1032,1036],{"class":906,"line":1022},6,[904,1024,918],{"class":917},[904,1026,1027],{"class":921},"iat",[904,1029,925],{"class":917},[904,1031,929],{"class":928},[904,1033,1035],{"class":1034},"spgvN"," 1710000000",[904,1037,942],{"class":910},[904,1039,1041,1043,1046,1048,1050],{"class":906,"line":1040},7,[904,1042,918],{"class":917},[904,1044,1045],{"class":921},"exp",[904,1047,925],{"class":917},[904,1049,929],{"class":928},[904,1051,1052],{"class":1034}," 1710000900\n",[904,1054,1056],{"class":906,"line":1055},8,[904,1057,1058],{"class":910},"}\n",[1060,1061,1062,1078],"table",{},[1063,1064,1065],"thead",{},[1066,1067,1068,1072,1075],"tr",{},[1069,1070,1071],"th",{},"Claim",[1069,1073,1074],{},"Source",[1069,1076,1077],{},"Description",[1079,1080,1081,1097,1111,1125,1139],"tbody",{},[1066,1082,1083,1088,1094],{},[1084,1085,1086],"td",{},[860,1087,922],{},[1084,1089,1090,1093],{},[860,1091,1092],{},"user.visitor_id"," argument",[1084,1095,1096],{},"Visitor session identifier, validated on every verify call",[1066,1098,1099,1103,1108],{},[1084,1100,1101],{},[860,1102,950],{},[1084,1104,1105,1093],{},[860,1106,1107],{},"user.role",[1084,1109,1110],{},"Role array embedded at signing time",[1066,1112,1113,1117,1122],{},[1084,1114,1115],{},[860,1116,985],{},[1084,1118,1119,1093],{},[860,1120,1121],{},"user.id",[1084,1123,1124],{},"Numeric user ID as a string",[1066,1126,1127,1131,1136],{},[1084,1128,1129],{},[860,1130,1006],{},[1084,1132,1133,1093],{},[860,1134,1135],{},"user.jti",[1084,1137,1138],{},"UUID, used by the cache and blacklist",[1066,1140,1141,1148,1154],{},[1084,1142,1143,1145,1146],{},[860,1144,1027],{}," \u002F ",[860,1147,1045],{},[1084,1149,1150,1153],{},[860,1151,1152],{},"jsonwebtoken"," library",[1084,1155,1156,1157],{},"Issued-at and expiry, driven by ",[860,1158,1159],{},"access_tokens.expiresIn",[856,1161,1162,1163,1165],{},"Any keys you place in ",[860,1164,893],{}," in the configuration are added into the payload before signing.",[877,1167],{},[880,1169,1171],{"id":1170},"generating-a-token","Generating a Token",[896,1173,1177],{"className":1174,"code":1175,"language":1176,"meta":900,"style":900},"language-ts shiki shiki-themes light-plus light-plus dracula","import { generateAccessToken } from '@riavzon\u002Fauth'\nimport crypto from 'crypto'\n\nconst token = generateAccessToken({\n  id: user.id,\n  visitor_id: user.visitor_id,\n  jti: crypto.randomUUID(),\n  role: ['user', 'admin']\n})\n","ts",[860,1178,1179,1206,1223,1228,1248,1267,1283,1300,1327],{"__ignoreMap":900},[904,1180,1181,1185,1188,1191,1194,1197,1200,1203],{"class":906,"line":907},[904,1182,1184],{"class":1183},"sZ328","import",[904,1186,1187],{"class":910}," { ",[904,1189,889],{"class":1190},"sjsA6",[904,1192,1193],{"class":910}," } ",[904,1195,1196],{"class":1183},"from",[904,1198,1199],{"class":932}," '",[904,1201,1202],{"class":936},"@riavzon\u002Fauth",[904,1204,1205],{"class":932},"'\n",[904,1207,1208,1210,1213,1216,1218,1221],{"class":906,"line":914},[904,1209,1184],{"class":1183},[904,1211,1212],{"class":1190}," crypto",[904,1214,1215],{"class":1183}," from",[904,1217,1199],{"class":932},[904,1219,1220],{"class":936},"crypto",[904,1222,1205],{"class":932},[904,1224,1225],{"class":906,"line":945},[904,1226,1227],{"emptyLinePlaceholder":8},"\n",[904,1229,1230,1234,1238,1241,1245],{"class":906,"line":980},[904,1231,1233],{"class":1232},"sl46w","const",[904,1235,1237],{"class":1236},"s3JHE"," token",[904,1239,1240],{"class":928}," =",[904,1242,1244],{"class":1243},"sHOzp"," generateAccessToken",[904,1246,1247],{"class":910},"({\n",[904,1249,1250,1253,1256,1259,1262,1265],{"class":906,"line":1001},[904,1251,1252],{"class":1190},"  id",[904,1254,929],{"class":1255},"s34zl",[904,1257,1258],{"class":1190}," user",[904,1260,1261],{"class":910},".",[904,1263,1264],{"class":1190},"id",[904,1266,942],{"class":910},[904,1268,1269,1272,1274,1276,1278,1281],{"class":906,"line":1022},[904,1270,1271],{"class":1190},"  visitor_id",[904,1273,929],{"class":1255},[904,1275,1258],{"class":1190},[904,1277,1261],{"class":910},[904,1279,1280],{"class":1190},"visitor_id",[904,1282,942],{"class":910},[904,1284,1285,1288,1290,1292,1294,1297],{"class":906,"line":1040},[904,1286,1287],{"class":1190},"  jti",[904,1289,929],{"class":1255},[904,1291,1212],{"class":1190},[904,1293,1261],{"class":910},[904,1295,1296],{"class":1243},"randomUUID",[904,1298,1299],{"class":910},"(),\n",[904,1301,1302,1305,1307,1309,1312,1314,1316,1318,1320,1322,1324],{"class":906,"line":1055},[904,1303,1304],{"class":1190},"  role",[904,1306,929],{"class":1255},[904,1308,957],{"class":910},[904,1310,1311],{"class":932},"'",[904,1313,962],{"class":936},[904,1315,1311],{"class":932},[904,1317,967],{"class":910},[904,1319,1311],{"class":932},[904,1321,972],{"class":936},[904,1323,1311],{"class":932},[904,1325,1326],{"class":910},"]\n",[904,1328,1330],{"class":906,"line":1329},9,[904,1331,1332],{"class":910},"})\n",[856,1334,1335,1337,1338,967,1340,967,1343,1346,1347,1349,1350,1353,1354,1357],{},[860,1336,889],{}," signs the token, then immediately writes a cache entry keyed by the raw token string. The cache entry stores ",[860,1339,1006],{},[860,1341,1342],{},"visitorId",[860,1344,1345],{},"userId",", and ",[860,1348,950],{}," alongside a ",[860,1351,1352],{},"valid: true"," flag. Any route calling ",[860,1355,1356],{},"verifyAccessToken"," later checks this entry before running the cryptographic verification.",[856,1359,1360,1361,1363],{},"When using the standalone service, the service generates and sends access tokens automatically on signup, login, MFA completion, and token rotation. You do not call ",[860,1362,889],{}," directly in that mode.",[877,1365],{},[880,1367,1369],{"id":1368},"verifying-a-token","Verifying a Token",[896,1371,1373],{"className":1174,"code":1372,"language":1176,"meta":900,"style":900},"import { verifyAccessToken } from '@riavzon\u002Fauth'\n\nconst { valid, payload, errorType } = verifyAccessToken(token)\n\nif (!valid) {\n    console.log(errorType)\n}\n",[860,1374,1375,1393,1397,1432,1436,1452,1468],{"__ignoreMap":900},[904,1376,1377,1379,1381,1383,1385,1387,1389,1391],{"class":906,"line":907},[904,1378,1184],{"class":1183},[904,1380,1187],{"class":910},[904,1382,1356],{"class":1190},[904,1384,1193],{"class":910},[904,1386,1196],{"class":1183},[904,1388,1199],{"class":932},[904,1390,1202],{"class":936},[904,1392,1205],{"class":932},[904,1394,1395],{"class":906,"line":914},[904,1396,1227],{"emptyLinePlaceholder":8},[904,1398,1399,1401,1403,1406,1408,1410,1412,1415,1417,1420,1423,1426,1429],{"class":906,"line":945},[904,1400,1233],{"class":1232},[904,1402,1187],{"class":910},[904,1404,1405],{"class":1236},"valid",[904,1407,967],{"class":910},[904,1409,882],{"class":1236},[904,1411,967],{"class":910},[904,1413,1414],{"class":1236},"errorType",[904,1416,1193],{"class":910},[904,1418,1419],{"class":928},"=",[904,1421,1422],{"class":1243}," verifyAccessToken",[904,1424,1425],{"class":910},"(",[904,1427,1428],{"class":1190},"token",[904,1430,1431],{"class":910},")\n",[904,1433,1434],{"class":906,"line":980},[904,1435,1227],{"emptyLinePlaceholder":8},[904,1437,1438,1441,1444,1447,1449],{"class":906,"line":1001},[904,1439,1440],{"class":1183},"if",[904,1442,1443],{"class":910}," (",[904,1445,1446],{"class":928},"!",[904,1448,1405],{"class":1190},[904,1450,1451],{"class":910},") {\n",[904,1453,1454,1457,1459,1462,1464,1466],{"class":906,"line":1022},[904,1455,1456],{"class":1190},"    console",[904,1458,1261],{"class":910},[904,1460,1461],{"class":1243},"log",[904,1463,1425],{"class":910},[904,1465,1414],{"class":1190},[904,1467,1431],{"class":910},[904,1469,1470],{"class":906,"line":1040},[904,1471,1058],{"class":910},[1060,1473,1474,1486],{},[1063,1475,1476],{},[1066,1477,1478,1481,1484],{},[1069,1479,1480],{},"Field",[1069,1482,1483],{},"Type",[1069,1485,1077],{},[1079,1487,1488,1502,1516],{},[1066,1489,1490,1494,1499],{},[1084,1491,1492],{},[860,1493,1405],{},[1084,1495,1496],{},[860,1497,1498],{},"boolean",[1084,1500,1501],{},"True when both the cache check and cryptographic check pass",[1066,1503,1504,1508,1513],{},[1084,1505,1506],{},[860,1507,882],{},[1084,1509,1510],{},[860,1511,1512],{},"JwtPayload | undefined",[1084,1514,1515],{},"Decoded claims, present only when valid",[1066,1517,1518,1522,1527],{},[1084,1519,1520],{},[860,1521,1414],{},[1084,1523,1524],{},[860,1525,1526],{},"string | undefined",[1084,1528,1529],{},"Failure description when invalid",[856,1531,1532],{},"Verification runs in this order:",[1534,1535,1537,1542,1555,1559,1578,1582,1591,1595],"steps",{"level":1536},"3",[1538,1539,1541],"h3",{"id":1540},"cache-lookup","Cache lookup",[856,1543,1544,1545,1547,1548,1551,1552,1261],{},"The function reads the cache entry for the token string. If no entry exists, or if ",[860,1546,1405],{}," is ",[860,1549,1550],{},"false",", it returns immediately with ",[860,1553,1554],{},"InvalidPayloadType",[1538,1556,1558],{"id":1557},"cryptographic-verification","Cryptographic verification",[856,1560,1561,1562,967,1565,967,1568,967,1571,1346,1574,1577],{},"Runs with the configured ",[860,1563,1564],{},"algorithm",[860,1566,1567],{},"audience",[860,1569,1570],{},"issuer",[860,1572,1573],{},"subject",[860,1575,1576],{},"jwtid",". A mismatch on any of those claims fails verification.",[1538,1579,1581],{"id":1580},"visitor-binding","Visitor binding",[856,1583,1584,1585,1587,1588,1590],{},"The ",[860,1586,922],{}," claim in the decoded payload is compared against the ",[860,1589,1342],{}," stored in the cache entry. This catches tokens that have been tampered with or replayed in a different session.",[1538,1592,1594],{"id":1593},"role-comparison","Role comparison",[856,1596,1597,1600,1601,1603,1604,1606],{},[860,1598,1599],{},"compareRoles"," runs against the ",[860,1602,950],{}," array in the cache and the ",[860,1605,950],{}," array in the decoded claim. Both must match exactly, no extra roles, no missing roles. This prevents tokens from gaining permissions they were not issued with.",[856,1608,1609,1610,1612],{},"The possible ",[860,1611,1414],{}," values are:",[1060,1614,1615,1625],{},[1063,1616,1617],{},[1066,1618,1619,1622],{},[1069,1620,1621],{},"Value",[1069,1623,1624],{},"Cause",[1079,1626,1627,1639,1649,1663,1675,1690],{},[1066,1628,1629,1633],{},[1084,1630,1631],{},[860,1632,1554],{},[1084,1634,1635,1636,1638],{},"Token not in cache, or ",[860,1637,1405],{}," flag is false",[1066,1640,1641,1646],{},[1084,1642,1643],{},[860,1644,1645],{},"TokenExpiredError",[1084,1647,1648],{},"Token has expired; the cache entry is deleted automatically",[1066,1650,1651,1656],{},[1084,1652,1653],{},[860,1654,1655],{},"Invalid visitor id",[1084,1657,1658,1660,1661],{},[860,1659,922],{}," claim does not match the cached ",[860,1662,1342],{},[1066,1664,1665,1670],{},[1084,1666,1667],{},[860,1668,1669],{},"MalformedPayload",[1084,1671,1672,1674],{},[860,1673,950],{}," in the token or cache is not a valid string array, or contains duplicates",[1066,1676,1677,1682],{},[1084,1678,1679],{},[860,1680,1681],{},"InvalidRoles",[1084,1683,1684,1686,1687,1689],{},[860,1685,950],{}," in the token do not exactly match the ",[860,1688,950],{}," in the cache",[1066,1691,1692,1703],{},[1084,1693,1694,1145,1697,1145,1700],{},[860,1695,1696],{},"invalid token",[860,1698,1699],{},"jwt malformed",[860,1701,1702],{},"invalid signature",[1084,1704,1705,1706,1708],{},"Standard ",[860,1707,1152],{}," failures",[877,1710],{},[880,1712,1714],{"id":1713},"cache","Cache",[856,1716,1717,1718,1721],{},"The access token cache is an LRU cache, ",[860,1719,1720],{},"lru-cache"," keyed by the raw token string. Its maximum size and TTL are driven by configuration:",[896,1723,1725],{"className":1174,"code":1724,"language":1176,"meta":900,"style":900},"{\n  maxCacheEntries: 500,\n  expiresInMs: 900000\n}\n",[860,1726,1727,1731,1741,1749],{"__ignoreMap":900},[904,1728,1729],{"class":906,"line":907},[904,1730,911],{"class":910},[904,1732,1733,1736,1739],{"class":906,"line":914},[904,1734,1735],{"class":910},"  maxCacheEntries: ",[904,1737,1738],{"class":1034},"500",[904,1740,942],{"class":910},[904,1742,1743,1746],{"class":906,"line":945},[904,1744,1745],{"class":910},"  expiresInMs: ",[904,1747,1748],{"class":1034},"900000\n",[904,1750,1751],{"class":906,"line":980},[904,1752,1058],{"class":910},[856,1754,1755,1756,1759],{},"You can read or write the cache directly through the exported ",[860,1757,1758],{},"tokenCache"," function:",[896,1761,1763],{"className":1174,"code":1762,"language":1176,"meta":900,"style":900},"import { tokenCache } from '@riavzon\u002Fauth'\n\nconst cache = tokenCache()\n\n\ncache.delete(rawToken)\n\nconst entry = cache.get(rawToken)\n",[860,1764,1765,1783,1787,1802,1806,1810,1826,1830],{"__ignoreMap":900},[904,1766,1767,1769,1771,1773,1775,1777,1779,1781],{"class":906,"line":907},[904,1768,1184],{"class":1183},[904,1770,1187],{"class":910},[904,1772,1758],{"class":1190},[904,1774,1193],{"class":910},[904,1776,1196],{"class":1183},[904,1778,1199],{"class":932},[904,1780,1202],{"class":936},[904,1782,1205],{"class":932},[904,1784,1785],{"class":906,"line":914},[904,1786,1227],{"emptyLinePlaceholder":8},[904,1788,1789,1791,1794,1796,1799],{"class":906,"line":945},[904,1790,1233],{"class":1232},[904,1792,1793],{"class":1236}," cache",[904,1795,1240],{"class":928},[904,1797,1798],{"class":1243}," tokenCache",[904,1800,1801],{"class":910},"()\n",[904,1803,1804],{"class":906,"line":980},[904,1805,1227],{"emptyLinePlaceholder":8},[904,1807,1808],{"class":906,"line":1001},[904,1809,1227],{"emptyLinePlaceholder":8},[904,1811,1812,1814,1816,1819,1821,1824],{"class":906,"line":1022},[904,1813,1713],{"class":1190},[904,1815,1261],{"class":910},[904,1817,1818],{"class":1243},"delete",[904,1820,1425],{"class":910},[904,1822,1823],{"class":1190},"rawToken",[904,1825,1431],{"class":910},[904,1827,1828],{"class":906,"line":1040},[904,1829,1227],{"emptyLinePlaceholder":8},[904,1831,1832,1834,1837,1839,1841,1843,1846,1848,1850],{"class":906,"line":1055},[904,1833,1233],{"class":1232},[904,1835,1836],{"class":1236}," entry",[904,1838,1240],{"class":928},[904,1840,1793],{"class":1190},[904,1842,1261],{"class":910},[904,1844,1845],{"class":1243},"get",[904,1847,1425],{"class":910},[904,1849,1823],{"class":1190},[904,1851,1431],{"class":910},[856,1853,1854],{},"Deleting a cache entry is enough to revoke an access token. The next verification call for that token will fail at the cache step before any cryptographic work happens.",[877,1856],{},[880,1858,283],{"id":1859},"route-protection",[1538,1861,1584,1863,1866],{"id":1862},"the-protectroute-middleware",[860,1864,1865],{},"protectRoute"," Middleware",[856,1868,1869,1871,1872,1875],{},[860,1870,1865],{}," is the middleware that ties together access token verification, anomaly detection, and ",[860,1873,1874],{},"req.user"," population.",[856,1877,1878],{},"Mount it in this order:",[1880,1881,1882,1888,1893,1898,1904,1908],"ul",{},[1883,1884,1885],"li",{},[860,1886,1887],{},"requireAccessToken",[1883,1889,1890],{},[860,1891,1892],{},"requireRefreshToken",[1883,1894,1895],{},[860,1896,1897],{},"getFingerPrint",[1883,1899,1900,1903],{},[860,1901,1902],{},"checkForActiveMfa",",",[1883,1905,1906,1903],{},[860,1907,1865],{},[1883,1909,1910],{},[860,1911,1912],{},"\u003Cyour-route>",[896,1914,1916],{"className":1174,"code":1915,"language":1176,"meta":900,"style":900},"import {\n  requireAccessToken,\n  requireRefreshToken,\n  getFingerPrint,\n  checkForActiveMfa,\n  protectRoute\n} from '@riavzon\u002Fauth'\n\nrouter.get(\n  '\u002Fyour\u002Fprotected\u002Froute',\n  requireAccessToken,\n  requireRefreshToken,\n  getFingerPrint,\n  checkForActiveMfa,\n  protectRoute,\n  async (req, res) => {\n    const { userId, visitor_id, roles, accessTokenId } = req.user!\n    res.json({ userId, roles })\n  }\n)\n",[860,1917,1918,1925,1932,1939,1946,1953,1958,1971,1975,1987,2000,2007,2014,2021,2028,2036,2061,2098,2120,2126],{"__ignoreMap":900},[904,1919,1920,1922],{"class":906,"line":907},[904,1921,1184],{"class":1183},[904,1923,1924],{"class":910}," {\n",[904,1926,1927,1930],{"class":906,"line":914},[904,1928,1929],{"class":1190},"  requireAccessToken",[904,1931,942],{"class":910},[904,1933,1934,1937],{"class":906,"line":945},[904,1935,1936],{"class":1190},"  requireRefreshToken",[904,1938,942],{"class":910},[904,1940,1941,1944],{"class":906,"line":980},[904,1942,1943],{"class":1190},"  getFingerPrint",[904,1945,942],{"class":910},[904,1947,1948,1951],{"class":906,"line":1001},[904,1949,1950],{"class":1190},"  checkForActiveMfa",[904,1952,942],{"class":910},[904,1954,1955],{"class":906,"line":1022},[904,1956,1957],{"class":1190},"  protectRoute\n",[904,1959,1960,1963,1965,1967,1969],{"class":906,"line":1040},[904,1961,1962],{"class":910},"} ",[904,1964,1196],{"class":1183},[904,1966,1199],{"class":932},[904,1968,1202],{"class":936},[904,1970,1205],{"class":932},[904,1972,1973],{"class":906,"line":1055},[904,1974,1227],{"emptyLinePlaceholder":8},[904,1976,1977,1980,1982,1984],{"class":906,"line":1329},[904,1978,1979],{"class":1190},"router",[904,1981,1261],{"class":910},[904,1983,1845],{"class":1243},[904,1985,1986],{"class":910},"(\n",[904,1988,1990,1993,1996,1998],{"class":906,"line":1989},10,[904,1991,1992],{"class":932},"  '",[904,1994,1995],{"class":936},"\u002Fyour\u002Fprotected\u002Froute",[904,1997,1311],{"class":932},[904,1999,942],{"class":910},[904,2001,2003,2005],{"class":906,"line":2002},11,[904,2004,1929],{"class":1190},[904,2006,942],{"class":910},[904,2008,2010,2012],{"class":906,"line":2009},12,[904,2011,1936],{"class":1190},[904,2013,942],{"class":910},[904,2015,2017,2019],{"class":906,"line":2016},13,[904,2018,1943],{"class":1190},[904,2020,942],{"class":910},[904,2022,2024,2026],{"class":906,"line":2023},14,[904,2025,1950],{"class":1190},[904,2027,942],{"class":910},[904,2029,2031,2034],{"class":906,"line":2030},15,[904,2032,2033],{"class":1190},"  protectRoute",[904,2035,942],{"class":910},[904,2037,2039,2042,2044,2048,2050,2053,2056,2059],{"class":906,"line":2038},16,[904,2040,2041],{"class":1232},"  async",[904,2043,1443],{"class":910},[904,2045,2047],{"class":2046},"sygFZ","req",[904,2049,967],{"class":910},[904,2051,2052],{"class":2046},"res",[904,2054,2055],{"class":910},") ",[904,2057,2058],{"class":1232},"=>",[904,2060,1924],{"class":910},[904,2062,2064,2067,2069,2071,2073,2075,2077,2079,2081,2084,2086,2088,2091,2093,2095],{"class":906,"line":2063},17,[904,2065,2066],{"class":1232},"    const",[904,2068,1187],{"class":910},[904,2070,1345],{"class":1236},[904,2072,967],{"class":910},[904,2074,1280],{"class":1236},[904,2076,967],{"class":910},[904,2078,950],{"class":1236},[904,2080,967],{"class":910},[904,2082,2083],{"class":1236},"accessTokenId",[904,2085,1193],{"class":910},[904,2087,1419],{"class":928},[904,2089,2090],{"class":1190}," req",[904,2092,1261],{"class":910},[904,2094,962],{"class":1190},[904,2096,2097],{"class":928},"!\n",[904,2099,2101,2104,2106,2108,2111,2113,2115,2117],{"class":906,"line":2100},18,[904,2102,2103],{"class":1190},"    res",[904,2105,1261],{"class":910},[904,2107,5],{"class":1243},[904,2109,2110],{"class":910},"({ ",[904,2112,1345],{"class":1190},[904,2114,967],{"class":910},[904,2116,950],{"class":1190},[904,2118,2119],{"class":910}," })\n",[904,2121,2123],{"class":906,"line":2122},19,[904,2124,2125],{"class":910},"  }\n",[904,2127,2129],{"class":906,"line":2128},20,[904,2130,1431],{"class":910},[856,2132,2133,2134,2136,2137,929],{},"When ",[860,2135,1865],{}," completes successfully it attaches the following to ",[860,2138,1874],{},[1060,2140,2141,2151],{},[1063,2142,2143],{},[1066,2144,2145,2147,2149],{},[1069,2146,1480],{},[1069,2148,1483],{},[1069,2150,1077],{},[1079,2152,2153,2169,2184,2199,2213],{},[1066,2154,2155,2159,2164],{},[1084,2156,2157],{},[860,2158,1345],{},[1084,2160,2161],{},[860,2162,2163],{},"string",[1084,2165,1584,2166,2168],{},[860,2167,985],{}," claim from the token",[1066,2170,2171,2175,2179],{},[1084,2172,2173],{},[860,2174,1280],{},[1084,2176,2177],{},[860,2178,2163],{},[1084,2180,1584,2181,2183],{},[860,2182,922],{}," claim",[1066,2185,2186,2190,2194],{},[1084,2187,2188],{},[860,2189,2083],{},[1084,2191,2192],{},[860,2193,2163],{},[1084,2195,1584,2196,2198],{},[860,2197,1006],{}," claim, use this to blacklist the token early",[1066,2200,2201,2205,2210],{},[1084,2202,2203],{},[860,2204,950],{},[1084,2206,2207],{},[860,2208,2209],{},"string[]",[1084,2211,2212],{},"Roles from the verified payload",[1066,2214,2215,2219,2224],{},[1084,2216,2217],{},[860,2218,882],{},[1084,2220,2221],{},[860,2222,2223],{},"JwtPayload",[1084,2225,2226],{},"The full decoded payload",[856,2228,2229,2231,2232,2234,2235,2238,2239,2242,2243,2247],{},[860,2230,1865],{}," also runs anomalies checks against the refresh token and ",[860,2233,862],{}," cookie. If the anomaly engine flags the session, the middleware either triggers an MFA challenge (",[860,2236,2237],{},"202",") or demands re-login (",[860,2240,2241],{},"401",") before your handler is reached. See ",[2244,2245,2246],"a",{"href":96},"anomalies"," for details.",[1538,2249,2251],{"id":2250},"the-bff-route","The BFF Route",[856,2253,2254,2255,2258],{},"When running the standalone service, the ",[860,2256,2257],{},"bffAccessRoute"," router exposes two GET endpoints that perform access-checking on behalf of a backend-for-frontend:",[1060,2260,2261,2270],{},[1063,2262,2263],{},[1066,2264,2265,2268],{},[1069,2266,2267],{},"Route",[1069,2269,1077],{},[1079,2271,2272,2286],{},[1066,2273,2274,2279],{},[1084,2275,2276],{},[860,2277,2278],{},"GET \u002Fsecret\u002Fdata",[1084,2280,2281,2282,2285],{},"Returns ",[860,2283,2284],{},"{ authorized, userId, ipAddress, userAgent, date, roles }"," after full token and anomaly verification",[1066,2287,2288,2293],{},[1084,2289,2290],{},[860,2291,2292],{},"GET \u002Fsecret\u002Faccesstoken\u002Fmetadata",[1084,2294,2295,2296,2299],{},"Returns the decoded payload, milliseconds until expiry, and a ",[860,2297,2298],{},"shouldRotate"," boolean",[856,2301,2302,2303,1547,2305,2308],{},"The metadata endpoint calculates a refresh threshold at 25% of the configured TTL. When ",[860,2304,2298],{},[860,2306,2307],{},"true",", the client should call the rotation endpoint before the token expires:",[896,2310,2312],{"className":898,"code":2311,"language":5,"meta":900,"style":900},"{\n  \"authorized\": true,\n  \"payload\": { \"decoded claims\" },\n  \"msUntilExp\": 210000,\n  \"refreshThreshold\": 225000,\n  \"shouldRotate\": true\n}\n",[860,2313,2314,2318,2335,2357,2373,2389,2402],{"__ignoreMap":900},[904,2315,2316],{"class":906,"line":907},[904,2317,911],{"class":910},[904,2319,2320,2322,2325,2327,2329,2333],{"class":906,"line":914},[904,2321,918],{"class":917},[904,2323,2324],{"class":921},"authorized",[904,2326,925],{"class":917},[904,2328,929],{"class":928},[904,2330,2332],{"class":2331},"sjR7W"," true",[904,2334,942],{"class":910},[904,2336,2337,2339,2341,2343,2345,2347,2349,2352,2354],{"class":906,"line":945},[904,2338,918],{"class":917},[904,2340,882],{"class":921},[904,2342,925],{"class":917},[904,2344,929],{"class":928},[904,2346,1187],{"class":910},[904,2348,925],{"class":917},[904,2350,2351],{"class":921},"decoded claims",[904,2353,925],{"class":917},[904,2355,2356],{"class":910}," },\n",[904,2358,2359,2361,2364,2366,2368,2371],{"class":906,"line":980},[904,2360,918],{"class":917},[904,2362,2363],{"class":921},"msUntilExp",[904,2365,925],{"class":917},[904,2367,929],{"class":928},[904,2369,2370],{"class":1034}," 210000",[904,2372,942],{"class":910},[904,2374,2375,2377,2380,2382,2384,2387],{"class":906,"line":1001},[904,2376,918],{"class":917},[904,2378,2379],{"class":921},"refreshThreshold",[904,2381,925],{"class":917},[904,2383,929],{"class":928},[904,2385,2386],{"class":1034}," 225000",[904,2388,942],{"class":910},[904,2390,2391,2393,2395,2397,2399],{"class":906,"line":1022},[904,2392,918],{"class":917},[904,2394,2298],{"class":921},[904,2396,925],{"class":917},[904,2398,929],{"class":928},[904,2400,2401],{"class":2331}," true\n",[904,2403,2404],{"class":906,"line":1040},[904,2405,1058],{"class":910},[856,2407,2408],{},"You need to call both with the access token header, the canary_id and the refresh token cookie.",[856,2410,2411,2412],{},"Learn more at ",[2244,2413,2415],{"href":2414},"\u002Fdocs\u002Fiam\u002Fbff","Backend for frontend",[877,2417],{},[880,2419,2420],{"id":950},"Roles",[856,2422,2423,2424,2426],{},"Roles are embedded in the token at generation time and verified cryptographically on every call to ",[860,2425,1356],{},". The roles array in the cache must equal the roles array in the token claim, with no extras and no missing entries.",[1538,2428,2430],{"id":2429},"embedding-roles","Embedding Roles",[856,2432,2433,2434,2437,2438,2440,2441,2443],{},"Pass an array of role strings as the ",[860,2435,2436],{},"role"," field when calling ",[860,2439,889],{},". The service stores that array in the LRU cache entry and embeds it as the ",[860,2442,950],{}," claim in the signed token.",[896,2445,2447],{"className":1174,"code":2446,"language":1176,"meta":900,"style":900},"const token = generateAccessToken({\n  id: user.id,\n  visitor_id: user.visitor_id,\n  jti: crypto.randomUUID(),\n  role: ['user', 'admin', 'editor']\n})\n",[860,2448,2449,2461,2475,2489,2503,2536],{"__ignoreMap":900},[904,2450,2451,2453,2455,2457,2459],{"class":906,"line":907},[904,2452,1233],{"class":1232},[904,2454,1237],{"class":1236},[904,2456,1240],{"class":928},[904,2458,1244],{"class":1243},[904,2460,1247],{"class":910},[904,2462,2463,2465,2467,2469,2471,2473],{"class":906,"line":914},[904,2464,1252],{"class":1190},[904,2466,929],{"class":1255},[904,2468,1258],{"class":1190},[904,2470,1261],{"class":910},[904,2472,1264],{"class":1190},[904,2474,942],{"class":910},[904,2476,2477,2479,2481,2483,2485,2487],{"class":906,"line":945},[904,2478,1271],{"class":1190},[904,2480,929],{"class":1255},[904,2482,1258],{"class":1190},[904,2484,1261],{"class":910},[904,2486,1280],{"class":1190},[904,2488,942],{"class":910},[904,2490,2491,2493,2495,2497,2499,2501],{"class":906,"line":980},[904,2492,1287],{"class":1190},[904,2494,929],{"class":1255},[904,2496,1212],{"class":1190},[904,2498,1261],{"class":910},[904,2500,1296],{"class":1243},[904,2502,1299],{"class":910},[904,2504,2505,2507,2509,2511,2513,2515,2517,2519,2521,2523,2525,2527,2529,2532,2534],{"class":906,"line":1001},[904,2506,1304],{"class":1190},[904,2508,929],{"class":1255},[904,2510,957],{"class":910},[904,2512,1311],{"class":932},[904,2514,962],{"class":936},[904,2516,1311],{"class":932},[904,2518,967],{"class":910},[904,2520,1311],{"class":932},[904,2522,972],{"class":936},[904,2524,1311],{"class":932},[904,2526,967],{"class":910},[904,2528,1311],{"class":932},[904,2530,2531],{"class":936},"editor",[904,2533,1311],{"class":932},[904,2535,1326],{"class":910},[904,2537,2538],{"class":906,"line":1022},[904,2539,1332],{"class":910},[856,2541,2542,2543,2545],{},"The standalone service generates tokens without any roles by default. To attach roles, call ",[860,2544,889],{}," directly, after user authentication.",[1538,2547,2549],{"id":2548},"role-validation","Role Validation",[856,2551,2552,2554,2555,2557],{},[860,2553,1599],{}," runs inside ",[860,2556,1356],{}," automatically. It normalizes both arrays with a trimming pass, checks for duplicates before and after normalization, then compares the sets:",[896,2559,2564],{"className":2560,"code":2562,"language":2563},[2561],"language-text","required (from cache) = ['user', 'admin']\nprovided (from token) = ['user', 'admin'] passes\n\nprovided = ['user', 'admin', 'editor'] InvalidRoles\nprovided = ['user'] InvalidRoles\n","text",[860,2565,2562],{"__ignoreMap":900},[856,2567,2568],{},"If you need different roles per route, generate separate tokens for each role context rather than relying on runtime role filtering, the library treats the embedded role array as an identity commitment, not a permission mask.",[2570,2571,2572],"tip",{},[856,2573,1584,2574,1443,2576,2578,2579,2581,2582,2584],{},[860,2575,2083],{},[860,2577,1006],{},") attached to ",[860,2580,1874],{}," by ",[860,2583,1865],{}," can be passed to the rate limiter blacklist to revoke a specific token mid-session without touching the database. This is the recommended approach for forced logout of individual sessions.",[877,2586],{},[880,2588,2590],{"id":2589},"configuration-reference","Configuration Reference",[856,2592,2593,2594,2597,2598,1261],{},"All access token options live under ",[860,2595,2596],{},"jwt.access_tokens"," in the object passed to ",[860,2599,2600],{},"configuration()",[1060,2602,2603,2617],{},[1063,2604,2605],{},[1066,2606,2607,2610,2612,2615],{},[1069,2608,2609],{},"Option",[1069,2611,1483],{},[1069,2613,2614],{},"Default",[1069,2616,1077],{},[1079,2618,2619,2639,2662,2682,2703,2722,2742,2760,2778],{},[1066,2620,2621,2626,2631,2636],{},[1084,2622,2623],{},[860,2624,2625],{},"expiresIn",[1084,2627,2628],{},[860,2629,2630],{},"string | number",[1084,2632,2633],{},[860,2634,2635],{},"'15m'",[1084,2637,2638],{},"Token lifetime. Accepts vercel\u002Fms strings or seconds",[1066,2640,2641,2646,2651,2656],{},[1084,2642,2643],{},[860,2644,2645],{},"expiresInMs",[1084,2647,2648],{},[860,2649,2650],{},"number",[1084,2652,2653],{},[860,2654,2655],{},"900000",[1084,2657,2658,2659,2661],{},"Used for cache TTL and metadata endpoint calculations. Should match ",[860,2660,2625],{}," in milliseconds",[1066,2663,2664,2668,2672,2677],{},[1084,2665,2666],{},[860,2667,1564],{},[1084,2669,2670],{},[860,2671,2163],{},[1084,2673,2674],{},[860,2675,2676],{},"'HS512'",[1084,2678,2679,2680],{},"HMAC or RSA\u002FEC algorithm. Accepts any algorithm supported by ",[860,2681,1152],{},[1066,2683,2684,2688,2692,2697],{},[1084,2685,2686],{},[860,2687,1567],{},[1084,2689,2690],{},[860,2691,2163],{},[1084,2693,2694],{},[860,2695,2696],{},"refresh_tokens.domain",[1084,2698,2699,2700,2183],{},"JWT ",[860,2701,2702],{},"aud",[1066,2704,2705,2709,2713,2717],{},[1084,2706,2707],{},[860,2708,1570],{},[1084,2710,2711],{},[860,2712,2163],{},[1084,2714,2715],{},[860,2716,2696],{},[1084,2718,2699,2719,2183],{},[860,2720,2721],{},"iss",[1066,2723,2724,2728,2732,2737],{},[1084,2725,2726],{},[860,2727,1573],{},[1084,2729,2730],{},[860,2731,2163],{},[1084,2733,2734],{},[860,2735,2736],{},"user.id.toString()",[1084,2738,2699,2739,2741],{},[860,2740,985],{}," claim override",[1066,2743,2744,2748,2752,2756],{},[1084,2745,2746],{},[860,2747,1576],{},[1084,2749,2750],{},[860,2751,2163],{},[1084,2753,2754],{},[860,2755,1135],{},[1084,2757,2699,2758,2741],{},[860,2759,1006],{},[1066,2761,2762,2767,2771,2775],{},[1084,2763,2764],{},[860,2765,2766],{},"maxCacheEntries",[1084,2768,2769],{},[860,2770,2650],{},[1084,2772,2773],{},[860,2774,1738],{},[1084,2776,2777],{},"LRU cache maximum size",[1066,2779,2780,2784,2789,2794],{},[1084,2781,2782],{},[860,2783,882],{},[1084,2785,2786],{},[860,2787,2788],{},"Record\u003Cstring, unknown>",[1084,2790,2791],{},[860,2792,2793],{},"{}",[1084,2795,2796],{},"Static custom claims spread into every token payload",[2798,2799,2800],"warning",{},[856,2801,2802,2804,2805,2807,2808,2810,2811,2813],{},[860,2803,2625],{}," and ",[860,2806,2645],{}," must be kept in sync manually. The library uses ",[860,2809,2625],{}," for the JWT signature and ",[860,2812,2645],{}," for the LRU cache TTL and the metadata endpoint threshold calculation. A mismatch causes the cache to evict tokens before they expire, or hold them after, breaking the two-gate verification model.",[2815,2816,2817],"style",{},"html pre.shiki code .sDd4n, html code.shiki .sDd4n{--shiki-light:#000000;--shiki-default:#000000;--shiki-dark:#F8F8F2}html pre.shiki code .saJyd, html code.shiki .saJyd{--shiki-light:#0451A5;--shiki-default:#0451A5;--shiki-dark:#8BE9FE}html pre.shiki code .s_W10, html code.shiki .s_W10{--shiki-light:#0451A5;--shiki-default:#0451A5;--shiki-dark:#8BE9FD}html pre.shiki code .saOXh, html code.shiki .saOXh{--shiki-light:#000000;--shiki-default:#000000;--shiki-dark:#FF79C6}html pre.shiki code .sFkSl, html code.shiki .sFkSl{--shiki-light:#A31515;--shiki-default:#A31515;--shiki-dark:#E9F284}html pre.shiki code .sFB1V, html code.shiki .sFB1V{--shiki-light:#A31515;--shiki-default:#A31515;--shiki-dark:#F1FA8C}html pre.shiki code .spgvN, html code.shiki .spgvN{--shiki-light:#098658;--shiki-default:#098658;--shiki-dark:#BD93F9}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 .sZ328, html code.shiki .sZ328{--shiki-light:#AF00DB;--shiki-default:#AF00DB;--shiki-dark:#FF79C6}html pre.shiki code .sjsA6, html code.shiki .sjsA6{--shiki-light:#001080;--shiki-default:#001080;--shiki-dark:#F8F8F2}html pre.shiki code .sl46w, html code.shiki .sl46w{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#FF79C6}html pre.shiki code .s3JHE, html code.shiki .s3JHE{--shiki-light:#0070C1;--shiki-default:#0070C1;--shiki-dark:#F8F8F2}html pre.shiki code .sHOzp, html code.shiki .sHOzp{--shiki-light:#795E26;--shiki-default:#795E26;--shiki-dark:#50FA7B}html pre.shiki code .s34zl, html code.shiki .s34zl{--shiki-light:#001080;--shiki-default:#001080;--shiki-dark:#FF79C6}html pre.shiki code .sygFZ, html code.shiki .sygFZ{--shiki-light:#001080;--shiki-light-font-style:inherit;--shiki-default:#001080;--shiki-default-font-style:inherit;--shiki-dark:#FFB86C;--shiki-dark-font-style:italic}html pre.shiki code .sjR7W, html code.shiki .sjR7W{--shiki-light:#0000FF;--shiki-default:#0000FF;--shiki-dark:#BD93F9}",{"title":900,"searchDepth":914,"depth":914,"links":2819},[2820,2821,2822,2828,2829,2834,2838],{"id":882,"depth":914,"text":883},{"id":1170,"depth":914,"text":1171},{"id":1368,"depth":914,"text":1369,"children":2823},[2824,2825,2826,2827],{"id":1540,"depth":945,"text":1541},{"id":1557,"depth":945,"text":1558},{"id":1580,"depth":945,"text":1581},{"id":1593,"depth":945,"text":1594},{"id":1713,"depth":914,"text":1714},{"id":1859,"depth":914,"text":283,"children":2830},[2831,2833],{"id":1862,"depth":945,"text":2832},"The protectRoute Middleware",{"id":2250,"depth":945,"text":2251},{"id":950,"depth":914,"text":2420,"children":2835},[2836,2837],{"id":2429,"depth":945,"text":2430},{"id":2548,"depth":945,"text":2549},{"id":2589,"depth":914,"text":2590},"How the IAM service generates, caches, verifies, and revokes access tokens - and how library users wire roles and route protection.","md",{},null,"---\ntitle: Access Tokens\ndescription: How the IAM service generates, caches, verifies, and revokes access tokens - and how library users wire roles and route protection.\nicon: i-lucide-shield-check\n---\n\nAccess tokens are short-lived signed JWTs. The service uses them as the primary credential for protected routes. Every access token is paired with a refresh token and a `canary_id` cookie, none of the three work in isolation.\n\nThe service signs tokens with `jwt.jwt_secret_key` and caches every verified token in an LRU cache. Verification requires the token to both pass the cryptographic check **and** exist in that cache. This design gives you a cheap revocation path without touching the database.\n\n---\n\n## Payload\n\nWhen you call `generateAccessToken`, the service builds the payload from three sources merged in order: the fixed identity fields, your `jwt.access_tokens.payload` config object, and the token-specific claims the JWT library adds.\n\n```json\n{\n  \"visitor\": \"vis_abc123\",\n  \"roles\": [\"user\", \"admin\"],\n  \"sub\": \"42\",\n  \"jti\": \"550e8400-e29b-41d4-a716-446655440000\",\n  \"iat\": 1710000000,\n  \"exp\": 1710000900\n}\n```\n\n| Claim | Source | Description |\n|---|---|---|\n| `visitor` | `user.visitor_id` argument | Visitor session identifier, validated on every verify call |\n| `roles` | `user.role` argument | Role array embedded at signing time |\n| `sub` | `user.id` argument | Numeric user ID as a string |\n| `jti` | `user.jti` argument | UUID, used by the cache and blacklist |\n| `iat` \u002F `exp` | `jsonwebtoken` library | Issued-at and expiry, driven by `access_tokens.expiresIn` |\n\nAny keys you place in `jwt.access_tokens.payload` in the configuration are added into the payload before signing.\n\n---\n\n## Generating a Token\n\n```ts\nimport { generateAccessToken } from '@riavzon\u002Fauth'\nimport crypto from 'crypto'\n\nconst token = generateAccessToken({\n  id: user.id,\n  visitor_id: user.visitor_id,\n  jti: crypto.randomUUID(),\n  role: ['user', 'admin']\n})\n```\n\n`generateAccessToken` signs the token, then immediately writes a cache entry keyed by the raw token string. The cache entry stores `jti`, `visitorId`, `userId`, and `roles` alongside a `valid: true` flag. Any route calling `verifyAccessToken` later checks this entry before running the cryptographic verification.\n\nWhen using the standalone service, the service generates and sends access tokens automatically on signup, login, MFA completion, and token rotation. You do not call `generateAccessToken` directly in that mode.\n\n---\n\n## Verifying a Token\n\n```ts\nimport { verifyAccessToken } from '@riavzon\u002Fauth'\n\nconst { valid, payload, errorType } = verifyAccessToken(token)\n\nif (!valid) {\n    console.log(errorType)\n}\n```\n\n| Field | Type | Description |\n|---|---|---|\n| `valid` | `boolean` | True when both the cache check and cryptographic check pass |\n| `payload` | `JwtPayload \\| undefined` | Decoded claims, present only when valid |\n| `errorType` | `string \\| undefined` | Failure description when invalid |\n\nVerification runs in this order:\n\n::steps{level=\"3\"}\n### Cache lookup\nThe function reads the cache entry for the token string. If no entry exists, or if `valid` is `false`, it returns immediately with `InvalidPayloadType`.\n\n### Cryptographic verification\nRuns with the configured `algorithm`, `audience`, `issuer`, `subject`, and `jwtid`. A mismatch on any of those claims fails verification.\n\n### Visitor binding\nThe `visitor` claim in the decoded payload is compared against the `visitorId` stored in the cache entry. This catches tokens that have been tampered with or replayed in a different session.\n\n### Role comparison\n`compareRoles` runs against the `roles` array in the cache and the `roles` array in the decoded claim. Both must match exactly, no extra roles, no missing roles. This prevents tokens from gaining permissions they were not issued with.\n::\n\nThe possible `errorType` values are:\n\n| Value | Cause |\n|---|---|\n| `InvalidPayloadType` | Token not in cache, or `valid` flag is false |\n| `TokenExpiredError` | Token has expired; the cache entry is deleted automatically |\n| `Invalid visitor id` | `visitor` claim does not match the cached `visitorId` |\n| `MalformedPayload` | `roles` in the token or cache is not a valid string array, or contains duplicates |\n| `InvalidRoles` | `roles` in the token do not exactly match the `roles` in the cache |\n| `invalid token` \u002F `jwt malformed` \u002F `invalid signature` | Standard `jsonwebtoken` failures |\n\n---\n\n## Cache\n\nThe access token cache is an LRU cache, `lru-cache` keyed by the raw token string. Its maximum size and TTL are driven by configuration:\n\n```ts\n{\n  maxCacheEntries: 500,\n  expiresInMs: 900000\n}\n```\n\nYou can read or write the cache directly through the exported `tokenCache` function:\n\n```ts\nimport { tokenCache } from '@riavzon\u002Fauth'\n\nconst cache = tokenCache()\n\n\ncache.delete(rawToken)\n\nconst entry = cache.get(rawToken)\n```\n\nDeleting a cache entry is enough to revoke an access token. The next verification call for that token will fail at the cache step before any cryptographic work happens.\n\n---\n\n## Route Protection\n\n### The `protectRoute` Middleware\n\n`protectRoute` is the middleware that ties together access token verification, anomaly detection, and `req.user` population. \n\nMount it in this order:\n\n - `requireAccessToken`\n - `requireRefreshToken`\n - `getFingerPrint`\n - `checkForActiveMfa`,\n - `protectRoute`,\n - `\u003Cyour-route>`\n\n```ts\nimport {\n  requireAccessToken,\n  requireRefreshToken,\n  getFingerPrint,\n  checkForActiveMfa,\n  protectRoute\n} from '@riavzon\u002Fauth'\n\nrouter.get(\n  '\u002Fyour\u002Fprotected\u002Froute',\n  requireAccessToken,\n  requireRefreshToken,\n  getFingerPrint,\n  checkForActiveMfa,\n  protectRoute,\n  async (req, res) => {\n    const { userId, visitor_id, roles, accessTokenId } = req.user!\n    res.json({ userId, roles })\n  }\n)\n```\n\nWhen `protectRoute` completes successfully it attaches the following to `req.user`:\n\n| Field | Type | Description |\n|---|---|---|\n| `userId` | `string` | The `sub` claim from the token |\n| `visitor_id` | `string` | The `visitor` claim |\n| `accessTokenId` | `string` | The `jti` claim, use this to blacklist the token early |\n| `roles` | `string[]` | Roles from the verified payload |\n| `payload` | `JwtPayload` | The full decoded payload |\n\n`protectRoute` also runs anomalies checks against the refresh token and `canary_id` cookie. If the anomaly engine flags the session, the middleware either triggers an MFA challenge (`202`) or demands re-login (`401`) before your handler is reached. See [anomalies](\u002Fdocs\u002Fiam\u002Fessentials\u002Fanomalies) for details.\n\n### The BFF Route\n\nWhen running the standalone service, the `bffAccessRoute` router exposes two GET endpoints that perform access-checking on behalf of a backend-for-frontend:\n\n| Route | Description |\n|---|---|\n| `GET \u002Fsecret\u002Fdata` | Returns `{ authorized, userId, ipAddress, userAgent, date, roles }` after full token and anomaly verification |\n| `GET \u002Fsecret\u002Faccesstoken\u002Fmetadata` | Returns the decoded payload, milliseconds until expiry, and a `shouldRotate` boolean |\n\nThe metadata endpoint calculates a refresh threshold at 25% of the configured TTL. When `shouldRotate` is `true`, the client should call the rotation endpoint before the token expires:\n\n```json\n{\n  \"authorized\": true,\n  \"payload\": { \"decoded claims\" },\n  \"msUntilExp\": 210000,\n  \"refreshThreshold\": 225000,\n  \"shouldRotate\": true\n}\n```\nYou need to call both with the access token header, the canary_id and the refresh token cookie.\n\nLearn more at [Backend for frontend](\u002Fdocs\u002Fiam\u002Fbff)\n\n---\n\n## Roles\n\nRoles are embedded in the token at generation time and verified cryptographically on every call to `verifyAccessToken`. The roles array in the cache must equal the roles array in the token claim, with no extras and no missing entries.\n\n### Embedding Roles\n\nPass an array of role strings as the `role` field when calling `generateAccessToken`. The service stores that array in the LRU cache entry and embeds it as the `roles` claim in the signed token.\n\n```ts\nconst token = generateAccessToken({\n  id: user.id,\n  visitor_id: user.visitor_id,\n  jti: crypto.randomUUID(),\n  role: ['user', 'admin', 'editor']\n})\n```\n\nThe standalone service generates tokens without any roles by default. To attach roles, call `generateAccessToken` directly, after user authentication.\n\n### Role Validation\n\n`compareRoles` runs inside `verifyAccessToken` automatically. It normalizes both arrays with a trimming pass, checks for duplicates before and after normalization, then compares the sets:\n\n```\nrequired (from cache) = ['user', 'admin']\nprovided (from token) = ['user', 'admin'] passes\n\nprovided = ['user', 'admin', 'editor'] InvalidRoles\nprovided = ['user'] InvalidRoles\n```\n\nIf you need different roles per route, generate separate tokens for each role context rather than relying on runtime role filtering, the library treats the embedded role array as an identity commitment, not a permission mask.\n\n::tip\nThe `accessTokenId` (`jti`) attached to `req.user` by `protectRoute` can be passed to the rate limiter blacklist to revoke a specific token mid-session without touching the database. This is the recommended approach for forced logout of individual sessions.\n::\n\n---\n\n## Configuration Reference\n\nAll access token options live under `jwt.access_tokens` in the object passed to `configuration()`.\n\n| Option | Type | Default | Description |\n|---|---|---|---|\n| `expiresIn` | `string \\| number` | `'15m'` | Token lifetime. Accepts vercel\u002Fms strings or seconds |\n| `expiresInMs` | `number` | `900000` | Used for cache TTL and metadata endpoint calculations. Should match `expiresIn` in milliseconds |\n| `algorithm` | `string` | `'HS512'` | HMAC or RSA\u002FEC algorithm. Accepts any algorithm supported by `jsonwebtoken` |\n| `audience` | `string` | `refresh_tokens.domain` | JWT `aud` claim |\n| `issuer` | `string` | `refresh_tokens.domain` | JWT `iss` claim |\n| `subject` | `string` | `user.id.toString()` | JWT `sub` claim override |\n| `jwtid` | `string` | `user.jti` | JWT `jti` claim override |\n| `maxCacheEntries` | `number` | `500` | LRU cache maximum size |\n| `payload` | `Record\u003Cstring, unknown>` | `{}` | Static custom claims spread into every token payload |\n\n::warning\n`expiresIn` and `expiresInMs` must be kept in sync manually. The library uses `expiresIn` for the JWT signature and `expiresInMs` for the LRU cache TTL and the metadata endpoint threshold calculation. A mismatch causes the cache to evict tokens before they expire, or hold them after, breaking the two-gate verification model.\n::\n\n",{"title":87,"description":2839},"7HnLw-bh-9tL8JkQToboFdIDaxGWiv0Ys8g8K6TlPT0",[2847,2848],{"title":83,"path":84,"stem":85,"children":-1},{"title":91,"path":92,"stem":93,"children":-1},{"id":851,"title":87,"body":2850,"description":2839,"extension":2840,"icon":28,"meta":4429,"module":2842,"navigation":8,"path":88,"rawbody":2843,"seo":4430,"stem":89,"__hash__":2845},{"type":853,"value":2851,"toc":4409},[2852,2856,2862,2864,2866,2872,2992,3070,3074,3076,3078,3200,3216,3220,3222,3224,3312,3362,3364,3408,3412,3490,3492,3494,3498,3524,3528,3612,3614,3616,3618,3622,3628,3630,3656,3836,3842,3922,3934,3936,3940,3972,3978,4064,4066,4070,4072,4074,4078,4080,4088,4182,4186,4188,4194,4199,4201,4213,4215,4217,4223,4395,4407],[856,2853,858,2854,863],{},[860,2855,862],{},[856,2857,866,2858,870,2860,875],{},[860,2859,869],{},[872,2861,874],{},[877,2863],{},[880,2865,883],{"id":882},[856,2867,886,2868,890,2870,894],{},[860,2869,889],{},[860,2871,893],{},[896,2873,2874],{"className":898,"code":899,"language":5,"meta":900,"style":900},[860,2875,2876,2880,2898,2926,2944,2962,2976,2988],{"__ignoreMap":900},[904,2877,2878],{"class":906,"line":907},[904,2879,911],{"class":910},[904,2881,2882,2884,2886,2888,2890,2892,2894,2896],{"class":906,"line":914},[904,2883,918],{"class":917},[904,2885,922],{"class":921},[904,2887,925],{"class":917},[904,2889,929],{"class":928},[904,2891,933],{"class":932},[904,2893,937],{"class":936},[904,2895,925],{"class":932},[904,2897,942],{"class":910},[904,2899,2900,2902,2904,2906,2908,2910,2912,2914,2916,2918,2920,2922,2924],{"class":906,"line":945},[904,2901,918],{"class":917},[904,2903,950],{"class":921},[904,2905,925],{"class":917},[904,2907,929],{"class":928},[904,2909,957],{"class":910},[904,2911,925],{"class":932},[904,2913,962],{"class":936},[904,2915,925],{"class":932},[904,2917,967],{"class":910},[904,2919,925],{"class":932},[904,2921,972],{"class":936},[904,2923,925],{"class":932},[904,2925,977],{"class":910},[904,2927,2928,2930,2932,2934,2936,2938,2940,2942],{"class":906,"line":980},[904,2929,918],{"class":917},[904,2931,985],{"class":921},[904,2933,925],{"class":917},[904,2935,929],{"class":928},[904,2937,933],{"class":932},[904,2939,994],{"class":936},[904,2941,925],{"class":932},[904,2943,942],{"class":910},[904,2945,2946,2948,2950,2952,2954,2956,2958,2960],{"class":906,"line":1001},[904,2947,918],{"class":917},[904,2949,1006],{"class":921},[904,2951,925],{"class":917},[904,2953,929],{"class":928},[904,2955,933],{"class":932},[904,2957,1015],{"class":936},[904,2959,925],{"class":932},[904,2961,942],{"class":910},[904,2963,2964,2966,2968,2970,2972,2974],{"class":906,"line":1022},[904,2965,918],{"class":917},[904,2967,1027],{"class":921},[904,2969,925],{"class":917},[904,2971,929],{"class":928},[904,2973,1035],{"class":1034},[904,2975,942],{"class":910},[904,2977,2978,2980,2982,2984,2986],{"class":906,"line":1040},[904,2979,918],{"class":917},[904,2981,1045],{"class":921},[904,2983,925],{"class":917},[904,2985,929],{"class":928},[904,2987,1052],{"class":1034},[904,2989,2990],{"class":906,"line":1055},[904,2991,1058],{"class":910},[1060,2993,2994,3004],{},[1063,2995,2996],{},[1066,2997,2998,3000,3002],{},[1069,2999,1071],{},[1069,3001,1074],{},[1069,3003,1077],{},[1079,3005,3006,3018,3030,3042,3054],{},[1066,3007,3008,3012,3016],{},[1084,3009,3010],{},[860,3011,922],{},[1084,3013,3014,1093],{},[860,3015,1092],{},[1084,3017,1096],{},[1066,3019,3020,3024,3028],{},[1084,3021,3022],{},[860,3023,950],{},[1084,3025,3026,1093],{},[860,3027,1107],{},[1084,3029,1110],{},[1066,3031,3032,3036,3040],{},[1084,3033,3034],{},[860,3035,985],{},[1084,3037,3038,1093],{},[860,3039,1121],{},[1084,3041,1124],{},[1066,3043,3044,3048,3052],{},[1084,3045,3046],{},[860,3047,1006],{},[1084,3049,3050,1093],{},[860,3051,1135],{},[1084,3053,1138],{},[1066,3055,3056,3062,3066],{},[1084,3057,3058,1145,3060],{},[860,3059,1027],{},[860,3061,1045],{},[1084,3063,3064,1153],{},[860,3065,1152],{},[1084,3067,1156,3068],{},[860,3069,1159],{},[856,3071,1162,3072,1165],{},[860,3073,893],{},[877,3075],{},[880,3077,1171],{"id":1170},[896,3079,3080],{"className":1174,"code":1175,"language":1176,"meta":900,"style":900},[860,3081,3082,3100,3114,3118,3130,3144,3158,3172,3196],{"__ignoreMap":900},[904,3083,3084,3086,3088,3090,3092,3094,3096,3098],{"class":906,"line":907},[904,3085,1184],{"class":1183},[904,3087,1187],{"class":910},[904,3089,889],{"class":1190},[904,3091,1193],{"class":910},[904,3093,1196],{"class":1183},[904,3095,1199],{"class":932},[904,3097,1202],{"class":936},[904,3099,1205],{"class":932},[904,3101,3102,3104,3106,3108,3110,3112],{"class":906,"line":914},[904,3103,1184],{"class":1183},[904,3105,1212],{"class":1190},[904,3107,1215],{"class":1183},[904,3109,1199],{"class":932},[904,3111,1220],{"class":936},[904,3113,1205],{"class":932},[904,3115,3116],{"class":906,"line":945},[904,3117,1227],{"emptyLinePlaceholder":8},[904,3119,3120,3122,3124,3126,3128],{"class":906,"line":980},[904,3121,1233],{"class":1232},[904,3123,1237],{"class":1236},[904,3125,1240],{"class":928},[904,3127,1244],{"class":1243},[904,3129,1247],{"class":910},[904,3131,3132,3134,3136,3138,3140,3142],{"class":906,"line":1001},[904,3133,1252],{"class":1190},[904,3135,929],{"class":1255},[904,3137,1258],{"class":1190},[904,3139,1261],{"class":910},[904,3141,1264],{"class":1190},[904,3143,942],{"class":910},[904,3145,3146,3148,3150,3152,3154,3156],{"class":906,"line":1022},[904,3147,1271],{"class":1190},[904,3149,929],{"class":1255},[904,3151,1258],{"class":1190},[904,3153,1261],{"class":910},[904,3155,1280],{"class":1190},[904,3157,942],{"class":910},[904,3159,3160,3162,3164,3166,3168,3170],{"class":906,"line":1040},[904,3161,1287],{"class":1190},[904,3163,929],{"class":1255},[904,3165,1212],{"class":1190},[904,3167,1261],{"class":910},[904,3169,1296],{"class":1243},[904,3171,1299],{"class":910},[904,3173,3174,3176,3178,3180,3182,3184,3186,3188,3190,3192,3194],{"class":906,"line":1055},[904,3175,1304],{"class":1190},[904,3177,929],{"class":1255},[904,3179,957],{"class":910},[904,3181,1311],{"class":932},[904,3183,962],{"class":936},[904,3185,1311],{"class":932},[904,3187,967],{"class":910},[904,3189,1311],{"class":932},[904,3191,972],{"class":936},[904,3193,1311],{"class":932},[904,3195,1326],{"class":910},[904,3197,3198],{"class":906,"line":1329},[904,3199,1332],{"class":910},[856,3201,3202,1337,3204,967,3206,967,3208,1346,3210,1349,3212,1353,3214,1357],{},[860,3203,889],{},[860,3205,1006],{},[860,3207,1342],{},[860,3209,1345],{},[860,3211,950],{},[860,3213,1352],{},[860,3215,1356],{},[856,3217,1360,3218,1363],{},[860,3219,889],{},[877,3221],{},[880,3223,1369],{"id":1368},[896,3225,3226],{"className":1174,"code":1372,"language":1176,"meta":900,"style":900},[860,3227,3228,3246,3250,3278,3282,3294,3308],{"__ignoreMap":900},[904,3229,3230,3232,3234,3236,3238,3240,3242,3244],{"class":906,"line":907},[904,3231,1184],{"class":1183},[904,3233,1187],{"class":910},[904,3235,1356],{"class":1190},[904,3237,1193],{"class":910},[904,3239,1196],{"class":1183},[904,3241,1199],{"class":932},[904,3243,1202],{"class":936},[904,3245,1205],{"class":932},[904,3247,3248],{"class":906,"line":914},[904,3249,1227],{"emptyLinePlaceholder":8},[904,3251,3252,3254,3256,3258,3260,3262,3264,3266,3268,3270,3272,3274,3276],{"class":906,"line":945},[904,3253,1233],{"class":1232},[904,3255,1187],{"class":910},[904,3257,1405],{"class":1236},[904,3259,967],{"class":910},[904,3261,882],{"class":1236},[904,3263,967],{"class":910},[904,3265,1414],{"class":1236},[904,3267,1193],{"class":910},[904,3269,1419],{"class":928},[904,3271,1422],{"class":1243},[904,3273,1425],{"class":910},[904,3275,1428],{"class":1190},[904,3277,1431],{"class":910},[904,3279,3280],{"class":906,"line":980},[904,3281,1227],{"emptyLinePlaceholder":8},[904,3283,3284,3286,3288,3290,3292],{"class":906,"line":1001},[904,3285,1440],{"class":1183},[904,3287,1443],{"class":910},[904,3289,1446],{"class":928},[904,3291,1405],{"class":1190},[904,3293,1451],{"class":910},[904,3295,3296,3298,3300,3302,3304,3306],{"class":906,"line":1022},[904,3297,1456],{"class":1190},[904,3299,1261],{"class":910},[904,3301,1461],{"class":1243},[904,3303,1425],{"class":910},[904,3305,1414],{"class":1190},[904,3307,1431],{"class":910},[904,3309,3310],{"class":906,"line":1040},[904,3311,1058],{"class":910},[1060,3313,3314,3324],{},[1063,3315,3316],{},[1066,3317,3318,3320,3322],{},[1069,3319,1480],{},[1069,3321,1483],{},[1069,3323,1077],{},[1079,3325,3326,3338,3350],{},[1066,3327,3328,3332,3336],{},[1084,3329,3330],{},[860,3331,1405],{},[1084,3333,3334],{},[860,3335,1498],{},[1084,3337,1501],{},[1066,3339,3340,3344,3348],{},[1084,3341,3342],{},[860,3343,882],{},[1084,3345,3346],{},[860,3347,1512],{},[1084,3349,1515],{},[1066,3351,3352,3356,3360],{},[1084,3353,3354],{},[860,3355,1414],{},[1084,3357,3358],{},[860,3359,1526],{},[1084,3361,1529],{},[856,3363,1532],{},[1534,3365,3366,3368,3376,3378,3390,3392,3398,3400],{"level":1536},[1538,3367,1541],{"id":1540},[856,3369,1544,3370,1547,3372,1551,3374,1261],{},[860,3371,1405],{},[860,3373,1550],{},[860,3375,1554],{},[1538,3377,1558],{"id":1557},[856,3379,1561,3380,967,3382,967,3384,967,3386,1346,3388,1577],{},[860,3381,1564],{},[860,3383,1567],{},[860,3385,1570],{},[860,3387,1573],{},[860,3389,1576],{},[1538,3391,1581],{"id":1580},[856,3393,1584,3394,1587,3396,1590],{},[860,3395,922],{},[860,3397,1342],{},[1538,3399,1594],{"id":1593},[856,3401,3402,1600,3404,1603,3406,1606],{},[860,3403,1599],{},[860,3405,950],{},[860,3407,950],{},[856,3409,1609,3410,1612],{},[860,3411,1414],{},[1060,3413,3414,3422],{},[1063,3415,3416],{},[1066,3417,3418,3420],{},[1069,3419,1621],{},[1069,3421,1624],{},[1079,3423,3424,3434,3442,3454,3464,3476],{},[1066,3425,3426,3430],{},[1084,3427,3428],{},[860,3429,1554],{},[1084,3431,1635,3432,1638],{},[860,3433,1405],{},[1066,3435,3436,3440],{},[1084,3437,3438],{},[860,3439,1645],{},[1084,3441,1648],{},[1066,3443,3444,3448],{},[1084,3445,3446],{},[860,3447,1655],{},[1084,3449,3450,1660,3452],{},[860,3451,922],{},[860,3453,1342],{},[1066,3455,3456,3460],{},[1084,3457,3458],{},[860,3459,1669],{},[1084,3461,3462,1674],{},[860,3463,950],{},[1066,3465,3466,3470],{},[1084,3467,3468],{},[860,3469,1681],{},[1084,3471,3472,1686,3474,1689],{},[860,3473,950],{},[860,3475,950],{},[1066,3477,3478,3486],{},[1084,3479,3480,1145,3482,1145,3484],{},[860,3481,1696],{},[860,3483,1699],{},[860,3485,1702],{},[1084,3487,1705,3488,1708],{},[860,3489,1152],{},[877,3491],{},[880,3493,1714],{"id":1713},[856,3495,1717,3496,1721],{},[860,3497,1720],{},[896,3499,3500],{"className":1174,"code":1724,"language":1176,"meta":900,"style":900},[860,3501,3502,3506,3514,3520],{"__ignoreMap":900},[904,3503,3504],{"class":906,"line":907},[904,3505,911],{"class":910},[904,3507,3508,3510,3512],{"class":906,"line":914},[904,3509,1735],{"class":910},[904,3511,1738],{"class":1034},[904,3513,942],{"class":910},[904,3515,3516,3518],{"class":906,"line":945},[904,3517,1745],{"class":910},[904,3519,1748],{"class":1034},[904,3521,3522],{"class":906,"line":980},[904,3523,1058],{"class":910},[856,3525,1755,3526,1759],{},[860,3527,1758],{},[896,3529,3530],{"className":1174,"code":1762,"language":1176,"meta":900,"style":900},[860,3531,3532,3550,3554,3566,3570,3574,3588,3592],{"__ignoreMap":900},[904,3533,3534,3536,3538,3540,3542,3544,3546,3548],{"class":906,"line":907},[904,3535,1184],{"class":1183},[904,3537,1187],{"class":910},[904,3539,1758],{"class":1190},[904,3541,1193],{"class":910},[904,3543,1196],{"class":1183},[904,3545,1199],{"class":932},[904,3547,1202],{"class":936},[904,3549,1205],{"class":932},[904,3551,3552],{"class":906,"line":914},[904,3553,1227],{"emptyLinePlaceholder":8},[904,3555,3556,3558,3560,3562,3564],{"class":906,"line":945},[904,3557,1233],{"class":1232},[904,3559,1793],{"class":1236},[904,3561,1240],{"class":928},[904,3563,1798],{"class":1243},[904,3565,1801],{"class":910},[904,3567,3568],{"class":906,"line":980},[904,3569,1227],{"emptyLinePlaceholder":8},[904,3571,3572],{"class":906,"line":1001},[904,3573,1227],{"emptyLinePlaceholder":8},[904,3575,3576,3578,3580,3582,3584,3586],{"class":906,"line":1022},[904,3577,1713],{"class":1190},[904,3579,1261],{"class":910},[904,3581,1818],{"class":1243},[904,3583,1425],{"class":910},[904,3585,1823],{"class":1190},[904,3587,1431],{"class":910},[904,3589,3590],{"class":906,"line":1040},[904,3591,1227],{"emptyLinePlaceholder":8},[904,3593,3594,3596,3598,3600,3602,3604,3606,3608,3610],{"class":906,"line":1055},[904,3595,1233],{"class":1232},[904,3597,1836],{"class":1236},[904,3599,1240],{"class":928},[904,3601,1793],{"class":1190},[904,3603,1261],{"class":910},[904,3605,1845],{"class":1243},[904,3607,1425],{"class":910},[904,3609,1823],{"class":1190},[904,3611,1431],{"class":910},[856,3613,1854],{},[877,3615],{},[880,3617,283],{"id":1859},[1538,3619,1584,3620,1866],{"id":1862},[860,3621,1865],{},[856,3623,3624,1871,3626,1875],{},[860,3625,1865],{},[860,3627,1874],{},[856,3629,1878],{},[1880,3631,3632,3636,3640,3644,3648,3652],{},[1883,3633,3634],{},[860,3635,1887],{},[1883,3637,3638],{},[860,3639,1892],{},[1883,3641,3642],{},[860,3643,1897],{},[1883,3645,3646,1903],{},[860,3647,1902],{},[1883,3649,3650,1903],{},[860,3651,1865],{},[1883,3653,3654],{},[860,3655,1912],{},[896,3657,3658],{"className":1174,"code":1915,"language":1176,"meta":900,"style":900},[860,3659,3660,3666,3672,3678,3684,3690,3694,3706,3710,3720,3730,3736,3742,3748,3754,3760,3778,3810,3828,3832],{"__ignoreMap":900},[904,3661,3662,3664],{"class":906,"line":907},[904,3663,1184],{"class":1183},[904,3665,1924],{"class":910},[904,3667,3668,3670],{"class":906,"line":914},[904,3669,1929],{"class":1190},[904,3671,942],{"class":910},[904,3673,3674,3676],{"class":906,"line":945},[904,3675,1936],{"class":1190},[904,3677,942],{"class":910},[904,3679,3680,3682],{"class":906,"line":980},[904,3681,1943],{"class":1190},[904,3683,942],{"class":910},[904,3685,3686,3688],{"class":906,"line":1001},[904,3687,1950],{"class":1190},[904,3689,942],{"class":910},[904,3691,3692],{"class":906,"line":1022},[904,3693,1957],{"class":1190},[904,3695,3696,3698,3700,3702,3704],{"class":906,"line":1040},[904,3697,1962],{"class":910},[904,3699,1196],{"class":1183},[904,3701,1199],{"class":932},[904,3703,1202],{"class":936},[904,3705,1205],{"class":932},[904,3707,3708],{"class":906,"line":1055},[904,3709,1227],{"emptyLinePlaceholder":8},[904,3711,3712,3714,3716,3718],{"class":906,"line":1329},[904,3713,1979],{"class":1190},[904,3715,1261],{"class":910},[904,3717,1845],{"class":1243},[904,3719,1986],{"class":910},[904,3721,3722,3724,3726,3728],{"class":906,"line":1989},[904,3723,1992],{"class":932},[904,3725,1995],{"class":936},[904,3727,1311],{"class":932},[904,3729,942],{"class":910},[904,3731,3732,3734],{"class":906,"line":2002},[904,3733,1929],{"class":1190},[904,3735,942],{"class":910},[904,3737,3738,3740],{"class":906,"line":2009},[904,3739,1936],{"class":1190},[904,3741,942],{"class":910},[904,3743,3744,3746],{"class":906,"line":2016},[904,3745,1943],{"class":1190},[904,3747,942],{"class":910},[904,3749,3750,3752],{"class":906,"line":2023},[904,3751,1950],{"class":1190},[904,3753,942],{"class":910},[904,3755,3756,3758],{"class":906,"line":2030},[904,3757,2033],{"class":1190},[904,3759,942],{"class":910},[904,3761,3762,3764,3766,3768,3770,3772,3774,3776],{"class":906,"line":2038},[904,3763,2041],{"class":1232},[904,3765,1443],{"class":910},[904,3767,2047],{"class":2046},[904,3769,967],{"class":910},[904,3771,2052],{"class":2046},[904,3773,2055],{"class":910},[904,3775,2058],{"class":1232},[904,3777,1924],{"class":910},[904,3779,3780,3782,3784,3786,3788,3790,3792,3794,3796,3798,3800,3802,3804,3806,3808],{"class":906,"line":2063},[904,3781,2066],{"class":1232},[904,3783,1187],{"class":910},[904,3785,1345],{"class":1236},[904,3787,967],{"class":910},[904,3789,1280],{"class":1236},[904,3791,967],{"class":910},[904,3793,950],{"class":1236},[904,3795,967],{"class":910},[904,3797,2083],{"class":1236},[904,3799,1193],{"class":910},[904,3801,1419],{"class":928},[904,3803,2090],{"class":1190},[904,3805,1261],{"class":910},[904,3807,962],{"class":1190},[904,3809,2097],{"class":928},[904,3811,3812,3814,3816,3818,3820,3822,3824,3826],{"class":906,"line":2100},[904,3813,2103],{"class":1190},[904,3815,1261],{"class":910},[904,3817,5],{"class":1243},[904,3819,2110],{"class":910},[904,3821,1345],{"class":1190},[904,3823,967],{"class":910},[904,3825,950],{"class":1190},[904,3827,2119],{"class":910},[904,3829,3830],{"class":906,"line":2122},[904,3831,2125],{"class":910},[904,3833,3834],{"class":906,"line":2128},[904,3835,1431],{"class":910},[856,3837,2133,3838,2136,3840,929],{},[860,3839,1865],{},[860,3841,1874],{},[1060,3843,3844,3854],{},[1063,3845,3846],{},[1066,3847,3848,3850,3852],{},[1069,3849,1480],{},[1069,3851,1483],{},[1069,3853,1077],{},[1079,3855,3856,3870,3884,3898,3910],{},[1066,3857,3858,3862,3866],{},[1084,3859,3860],{},[860,3861,1345],{},[1084,3863,3864],{},[860,3865,2163],{},[1084,3867,1584,3868,2168],{},[860,3869,985],{},[1066,3871,3872,3876,3880],{},[1084,3873,3874],{},[860,3875,1280],{},[1084,3877,3878],{},[860,3879,2163],{},[1084,3881,1584,3882,2183],{},[860,3883,922],{},[1066,3885,3886,3890,3894],{},[1084,3887,3888],{},[860,3889,2083],{},[1084,3891,3892],{},[860,3893,2163],{},[1084,3895,1584,3896,2198],{},[860,3897,1006],{},[1066,3899,3900,3904,3908],{},[1084,3901,3902],{},[860,3903,950],{},[1084,3905,3906],{},[860,3907,2209],{},[1084,3909,2212],{},[1066,3911,3912,3916,3920],{},[1084,3913,3914],{},[860,3915,882],{},[1084,3917,3918],{},[860,3919,2223],{},[1084,3921,2226],{},[856,3923,3924,2231,3926,2234,3928,2238,3930,2242,3932,2247],{},[860,3925,1865],{},[860,3927,862],{},[860,3929,2237],{},[860,3931,2241],{},[2244,3933,2246],{"href":96},[1538,3935,2251],{"id":2250},[856,3937,2254,3938,2258],{},[860,3939,2257],{},[1060,3941,3942,3950],{},[1063,3943,3944],{},[1066,3945,3946,3948],{},[1069,3947,2267],{},[1069,3949,1077],{},[1079,3951,3952,3962],{},[1066,3953,3954,3958],{},[1084,3955,3956],{},[860,3957,2278],{},[1084,3959,2281,3960,2285],{},[860,3961,2284],{},[1066,3963,3964,3968],{},[1084,3965,3966],{},[860,3967,2292],{},[1084,3969,2295,3970,2299],{},[860,3971,2298],{},[856,3973,2302,3974,1547,3976,2308],{},[860,3975,2298],{},[860,3977,2307],{},[896,3979,3980],{"className":898,"code":2311,"language":5,"meta":900,"style":900},[860,3981,3982,3986,4000,4020,4034,4048,4060],{"__ignoreMap":900},[904,3983,3984],{"class":906,"line":907},[904,3985,911],{"class":910},[904,3987,3988,3990,3992,3994,3996,3998],{"class":906,"line":914},[904,3989,918],{"class":917},[904,3991,2324],{"class":921},[904,3993,925],{"class":917},[904,3995,929],{"class":928},[904,3997,2332],{"class":2331},[904,3999,942],{"class":910},[904,4001,4002,4004,4006,4008,4010,4012,4014,4016,4018],{"class":906,"line":945},[904,4003,918],{"class":917},[904,4005,882],{"class":921},[904,4007,925],{"class":917},[904,4009,929],{"class":928},[904,4011,1187],{"class":910},[904,4013,925],{"class":917},[904,4015,2351],{"class":921},[904,4017,925],{"class":917},[904,4019,2356],{"class":910},[904,4021,4022,4024,4026,4028,4030,4032],{"class":906,"line":980},[904,4023,918],{"class":917},[904,4025,2363],{"class":921},[904,4027,925],{"class":917},[904,4029,929],{"class":928},[904,4031,2370],{"class":1034},[904,4033,942],{"class":910},[904,4035,4036,4038,4040,4042,4044,4046],{"class":906,"line":1001},[904,4037,918],{"class":917},[904,4039,2379],{"class":921},[904,4041,925],{"class":917},[904,4043,929],{"class":928},[904,4045,2386],{"class":1034},[904,4047,942],{"class":910},[904,4049,4050,4052,4054,4056,4058],{"class":906,"line":1022},[904,4051,918],{"class":917},[904,4053,2298],{"class":921},[904,4055,925],{"class":917},[904,4057,929],{"class":928},[904,4059,2401],{"class":2331},[904,4061,4062],{"class":906,"line":1040},[904,4063,1058],{"class":910},[856,4065,2408],{},[856,4067,2411,4068],{},[2244,4069,2415],{"href":2414},[877,4071],{},[880,4073,2420],{"id":950},[856,4075,2423,4076,2426],{},[860,4077,1356],{},[1538,4079,2430],{"id":2429},[856,4081,2433,4082,2437,4084,2440,4086,2443],{},[860,4083,2436],{},[860,4085,889],{},[860,4087,950],{},[896,4089,4090],{"className":1174,"code":2446,"language":1176,"meta":900,"style":900},[860,4091,4092,4104,4118,4132,4146,4178],{"__ignoreMap":900},[904,4093,4094,4096,4098,4100,4102],{"class":906,"line":907},[904,4095,1233],{"class":1232},[904,4097,1237],{"class":1236},[904,4099,1240],{"class":928},[904,4101,1244],{"class":1243},[904,4103,1247],{"class":910},[904,4105,4106,4108,4110,4112,4114,4116],{"class":906,"line":914},[904,4107,1252],{"class":1190},[904,4109,929],{"class":1255},[904,4111,1258],{"class":1190},[904,4113,1261],{"class":910},[904,4115,1264],{"class":1190},[904,4117,942],{"class":910},[904,4119,4120,4122,4124,4126,4128,4130],{"class":906,"line":945},[904,4121,1271],{"class":1190},[904,4123,929],{"class":1255},[904,4125,1258],{"class":1190},[904,4127,1261],{"class":910},[904,4129,1280],{"class":1190},[904,4131,942],{"class":910},[904,4133,4134,4136,4138,4140,4142,4144],{"class":906,"line":980},[904,4135,1287],{"class":1190},[904,4137,929],{"class":1255},[904,4139,1212],{"class":1190},[904,4141,1261],{"class":910},[904,4143,1296],{"class":1243},[904,4145,1299],{"class":910},[904,4147,4148,4150,4152,4154,4156,4158,4160,4162,4164,4166,4168,4170,4172,4174,4176],{"class":906,"line":1001},[904,4149,1304],{"class":1190},[904,4151,929],{"class":1255},[904,4153,957],{"class":910},[904,4155,1311],{"class":932},[904,4157,962],{"class":936},[904,4159,1311],{"class":932},[904,4161,967],{"class":910},[904,4163,1311],{"class":932},[904,4165,972],{"class":936},[904,4167,1311],{"class":932},[904,4169,967],{"class":910},[904,4171,1311],{"class":932},[904,4173,2531],{"class":936},[904,4175,1311],{"class":932},[904,4177,1326],{"class":910},[904,4179,4180],{"class":906,"line":1022},[904,4181,1332],{"class":910},[856,4183,2542,4184,2545],{},[860,4185,889],{},[1538,4187,2549],{"id":2548},[856,4189,4190,2554,4192,2557],{},[860,4191,1599],{},[860,4193,1356],{},[896,4195,4197],{"className":4196,"code":2562,"language":2563},[2561],[860,4198,2562],{"__ignoreMap":900},[856,4200,2568],{},[2570,4202,4203],{},[856,4204,1584,4205,1443,4207,2578,4209,2581,4211,2584],{},[860,4206,2083],{},[860,4208,1006],{},[860,4210,1874],{},[860,4212,1865],{},[877,4214],{},[880,4216,2590],{"id":2589},[856,4218,2593,4219,2597,4221,1261],{},[860,4220,2596],{},[860,4222,2600],{},[1060,4224,4225,4237],{},[1063,4226,4227],{},[1066,4228,4229,4231,4233,4235],{},[1069,4230,2609],{},[1069,4232,1483],{},[1069,4234,2614],{},[1069,4236,1077],{},[1079,4238,4239,4255,4273,4291,4309,4327,4345,4363,4379],{},[1066,4240,4241,4245,4249,4253],{},[1084,4242,4243],{},[860,4244,2625],{},[1084,4246,4247],{},[860,4248,2630],{},[1084,4250,4251],{},[860,4252,2635],{},[1084,4254,2638],{},[1066,4256,4257,4261,4265,4269],{},[1084,4258,4259],{},[860,4260,2645],{},[1084,4262,4263],{},[860,4264,2650],{},[1084,4266,4267],{},[860,4268,2655],{},[1084,4270,2658,4271,2661],{},[860,4272,2625],{},[1066,4274,4275,4279,4283,4287],{},[1084,4276,4277],{},[860,4278,1564],{},[1084,4280,4281],{},[860,4282,2163],{},[1084,4284,4285],{},[860,4286,2676],{},[1084,4288,2679,4289],{},[860,4290,1152],{},[1066,4292,4293,4297,4301,4305],{},[1084,4294,4295],{},[860,4296,1567],{},[1084,4298,4299],{},[860,4300,2163],{},[1084,4302,4303],{},[860,4304,2696],{},[1084,4306,2699,4307,2183],{},[860,4308,2702],{},[1066,4310,4311,4315,4319,4323],{},[1084,4312,4313],{},[860,4314,1570],{},[1084,4316,4317],{},[860,4318,2163],{},[1084,4320,4321],{},[860,4322,2696],{},[1084,4324,2699,4325,2183],{},[860,4326,2721],{},[1066,4328,4329,4333,4337,4341],{},[1084,4330,4331],{},[860,4332,1573],{},[1084,4334,4335],{},[860,4336,2163],{},[1084,4338,4339],{},[860,4340,2736],{},[1084,4342,2699,4343,2741],{},[860,4344,985],{},[1066,4346,4347,4351,4355,4359],{},[1084,4348,4349],{},[860,4350,1576],{},[1084,4352,4353],{},[860,4354,2163],{},[1084,4356,4357],{},[860,4358,1135],{},[1084,4360,2699,4361,2741],{},[860,4362,1006],{},[1066,4364,4365,4369,4373,4377],{},[1084,4366,4367],{},[860,4368,2766],{},[1084,4370,4371],{},[860,4372,2650],{},[1084,4374,4375],{},[860,4376,1738],{},[1084,4378,2777],{},[1066,4380,4381,4385,4389,4393],{},[1084,4382,4383],{},[860,4384,882],{},[1084,4386,4387],{},[860,4388,2788],{},[1084,4390,4391],{},[860,4392,2793],{},[1084,4394,2796],{},[2798,4396,4397],{},[856,4398,4399,2804,4401,2807,4403,2810,4405,2813],{},[860,4400,2625],{},[860,4402,2645],{},[860,4404,2625],{},[860,4406,2645],{},[2815,4408,2817],{},{"title":900,"searchDepth":914,"depth":914,"links":4410},[4411,4412,4413,4419,4420,4424,4428],{"id":882,"depth":914,"text":883},{"id":1170,"depth":914,"text":1171},{"id":1368,"depth":914,"text":1369,"children":4414},[4415,4416,4417,4418],{"id":1540,"depth":945,"text":1541},{"id":1557,"depth":945,"text":1558},{"id":1580,"depth":945,"text":1581},{"id":1593,"depth":945,"text":1594},{"id":1713,"depth":914,"text":1714},{"id":1859,"depth":914,"text":283,"children":4421},[4422,4423],{"id":1862,"depth":945,"text":2832},{"id":2250,"depth":945,"text":2251},{"id":950,"depth":914,"text":2420,"children":4425},[4426,4427],{"id":2429,"depth":945,"text":2430},{"id":2548,"depth":945,"text":2549},{"id":2589,"depth":914,"text":2590},{},{"title":87,"description":2839},1780436280101]