[{"data":1,"prerenderedAt":663},["ShallowReactive",2],{"navigation":3,"\u002Fauth\u002Fjwt-tokens":189,"\u002Fauth\u002Fjwt-tokens-surround":658},[4,34,60,116,137,153],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":33},"Getting Started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,18,23,28],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-house",{"title":5,"path":16,"stem":17,"icon":6},"\u002Fgetting-started\u002Fgetting-started","1.getting-started\u002F2.getting-started",{"title":19,"path":20,"stem":21,"icon":22},"Choosing a Preset","\u002Fgetting-started\u002Fchoosing-a-preset","1.getting-started\u002F3.choosing-a-preset","i-lucide-git-branch",{"title":24,"path":25,"stem":26,"icon":27},"Deployment","\u002Fgetting-started\u002Fdeployment","1.getting-started\u002F4.deployment","i-lucide-cloud",{"title":29,"path":30,"stem":31,"icon":32},"Background Maintenance","\u002Fgetting-started\u002Fbackground-maintenance","1.getting-started\u002F5.background-maintenance","i-lucide-timer-reset",false,{"title":35,"icon":36,"path":37,"stem":38,"children":39,"page":33},"Build","i-lucide-wrench","\u002Fbuild","2.build",[40,45,50,55],{"title":41,"path":42,"stem":43,"icon":44},"Routers & Prefixes","\u002Fbuild\u002Frouters-and-prefixes","2.build\u002F1.routers-and-prefixes","i-lucide-route",{"title":46,"path":47,"stem":48,"icon":49},"Configuration","\u002Fbuild\u002Fconfiguration","2.build\u002F2.configuration","i-lucide-settings",{"title":51,"path":52,"stem":53,"icon":54},"Authorization Dependencies","\u002Fbuild\u002Fauthorization-dependencies","2.build\u002F3.authorization-dependencies","i-lucide-shield-check",{"title":56,"path":57,"stem":58,"icon":59},"Command Line","\u002Fbuild\u002Fcli","2.build\u002F4.cli","i-lucide-terminal",{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":33},"Auth","i-lucide-lock","\u002Fauth","3.auth",[66,71,76,81,86,91,96,101,106,111],{"title":67,"path":68,"stem":69,"icon":70},"OAuth & Social Login","\u002Fauth\u002Foauth-and-social-login","3.auth\u002F1.oauth-and-social-login","i-lucide-log-in",{"title":72,"path":73,"stem":74,"icon":75},"Multi-Frontend Support","\u002Fauth\u002Fmulti-frontend","3.auth\u002F10.multi-frontend","i-lucide-layout-grid",{"title":77,"path":78,"stem":79,"icon":80},"Sessions & Audit","\u002Fauth\u002Fsessions-and-audit","3.auth\u002F2.sessions-and-audit","i-lucide-monitor-smartphone",{"title":82,"path":83,"stem":84,"icon":85},"Passwordless & Messaging","\u002Fauth\u002Fpasswordless-and-messaging","3.auth\u002F3.passwordless-and-messaging","i-lucide-mail",{"title":87,"path":88,"stem":89,"icon":90},"JWT Tokens","\u002Fauth\u002Fjwt-tokens","3.auth\u002F4.jwt-tokens","i-lucide-key-round",{"title":92,"path":93,"stem":94,"icon":95},"User Management API","\u002Fauth\u002Fuser-management-api","3.auth\u002F5.user-management-api","i-lucide-users",{"title":97,"path":98,"stem":99,"icon":100},"User Invitations","\u002Fauth\u002Fuser-invitations","3.auth\u002F6.user-invitations","i-lucide-send",{"title":102,"path":103,"stem":104,"icon":105},"Roles & Permissions","\u002Fauth\u002Froles-and-permissions","3.auth\u002F7.roles-and-permissions","i-lucide-shield",{"title":107,"path":108,"stem":109,"icon":110},"ABAC","\u002Fauth\u002Fabac","3.auth\u002F8.abac","i-lucide-filter",{"title":112,"path":113,"stem":114,"icon":115},"User Status","\u002Fauth\u002Fuser-status","3.auth\u002F9.user-status","i-lucide-user-cog",{"title":117,"icon":118,"path":119,"stem":120,"children":121,"page":33},"Enterprise","i-lucide-building-2","\u002Fenterprise","4.enterprise",[122,127,132],{"title":123,"path":124,"stem":125,"icon":126},"Core Authorization Concepts","\u002Fenterprise\u002Fcore-authorization-concepts","4.enterprise\u002F1.core-authorization-concepts","i-lucide-network",{"title":128,"path":129,"stem":130,"icon":131},"Entities","\u002Fenterprise\u002Fentities","4.enterprise\u002F2.entities","i-lucide-folder-tree",{"title":133,"path":134,"stem":135,"icon":136},"Entity Memberships","\u002Fenterprise\u002Fentity-memberships","4.enterprise\u002F3.entity-memberships","i-lucide-user-plus",{"title":138,"icon":139,"path":140,"stem":141,"children":142,"page":33},"Integrations","i-lucide-plug","\u002Fintegrations","5.integrations",[143,148],{"title":144,"path":145,"stem":146,"icon":147},"API Keys","\u002Fintegrations\u002Fapi-keys","5.integrations\u002F1.api-keys","i-lucide-key",{"title":149,"path":150,"stem":151,"icon":152},"OutlabsAuth UI","\u002Fintegrations\u002Foutlabsauth-ui","5.integrations\u002F2.outlabsauth-ui","i-lucide-layout-dashboard",{"title":154,"icon":155,"path":156,"stem":157,"children":158,"page":33},"Reference","i-lucide-book-marked","\u002Freference","6.reference",[159,164,169,174,179,184],{"title":160,"path":161,"stem":162,"icon":163},"Data Models","\u002Freference\u002Fdata-models","6.reference\u002F1.data-models","i-lucide-database",{"title":165,"path":166,"stem":167,"icon":168},"Activity Tracking","\u002Freference\u002Factivity-tracking","6.reference\u002F2.activity-tracking","i-lucide-activity",{"title":170,"path":171,"stem":172,"icon":173},"Testing","\u002Freference\u002Ftesting","6.reference\u002F3.testing","i-lucide-flask-conical",{"title":175,"path":176,"stem":177,"icon":178},"Observability","\u002Freference\u002Fobservability","6.reference\u002F4.observability","i-lucide-eye",{"title":180,"path":181,"stem":182,"icon":183},"Metrics Reference","\u002Freference\u002Fmetrics-reference","6.reference\u002F5.metrics-reference","i-lucide-chart-bar",{"title":185,"path":186,"stem":187,"icon":188},"Log Events Reference","\u002Freference\u002Flog-events-reference","6.reference\u002F6.log-events-reference","i-lucide-scroll-text",{"id":190,"title":87,"body":191,"description":651,"extension":652,"links":653,"meta":654,"navigation":655,"path":88,"seo":656,"stem":89,"__hash__":657},"docs\u002F3.auth\u002F4.jwt-tokens.md",{"type":192,"value":193,"toc":637},"minimark",[194,208,211,216,219,273,276,283,288,327,335,337,341,351,363,365,369,380,488,494,496,500,520,529,531,535,584,589,591,595,611,613,617],[195,196,197],"note",{},[198,199,200,201,204,205,207],"p",{},"— how access and refresh tokens behave. Mount login routes: ",[202,203,41],"a",{"href":42},". Sessions: ",[202,206,77],{"href":78},".",[209,210],"hr",{},[212,213,215],"h2",{"id":214},"how-outlabsauth-uses-jwts","How OutlabsAuth uses JWTs",[198,217,218],{},"Login (and accept-invite, magic-link verify, access-code verify, …) returns two\ntokens:",[220,221,222,238],"table",{},[223,224,225],"thead",{},[226,227,228,232,235],"tr",{},[229,230,231],"th",{},"Token",[229,233,234],{},"Typical lifetime",[229,236,237],{},"Role",[239,240,241,260],"tbody",{},[226,242,243,250,253],{},[244,245,246],"td",{},[247,248,249],"strong",{},"Access",[244,251,252],{},"~15 minutes",[244,254,255,259],{},[256,257,258],"code",{},"Authorization: Bearer …"," on API calls",[226,261,262,267,270],{},[244,263,264],{},[247,265,266],{},"Refresh",[244,268,269],{},"~30 days",[244,271,272],{},"Exchange for a new access token; powers session inventory when stored",[198,274,275],{},"Defaults are configurable. Prefer short access tokens; revoke refresh rows (or\nblacklist access JWTs with Redis) when you need immediate cut-off.",[198,277,278,279,282],{},"Refresh tokens must ",[247,280,281],{},"not"," be accepted as access credentials (SEC-1).",[284,285,287],"h3",{"id":286},"typical-claims","Typical claims",[198,289,290,293,294,297,298,301,302,301,305,301,308,301,311,314,317,320,321,324,325],{},[247,291,292],{},"Access:"," ",[256,295,296],{},"sub"," (user id), ",[256,299,300],{},"exp",", ",[256,303,304],{},"iat",[256,306,307],{},"type: \"access\"",[256,309,310],{},"aud",[256,312,313],{},"jti",[315,316],"br",{},[247,318,319],{},"Refresh:"," same shape with ",[256,322,323],{},"type: \"refresh\""," and a longer ",[256,326,300],{},[198,328,329,331,332,334],{},[256,330,310],{}," (audience) reduces accidental cross-app token reuse. ",[256,333,313],{}," supports\nblacklist \u002F uniqueness.",[209,336],{},[212,338,340],{"id":339},"token-flow","Token flow",[342,343,348],"pre",{"className":344,"code":346,"language":347},[345],"language-text","POST \u002Fauth\u002Flogin  →  access_token + refresh_token\n       │\n       ▼\nAPI calls with Bearer access_token\n       │\n       ▼ (near expiry)\nPOST \u002Fauth\u002Frefresh { refresh_token }  →  new access (+ optional rotated refresh)\n       │\n       ▼\nPOST \u002Fauth\u002Flogout  (revokes refresh when store_refresh_tokens is on)\n","text",[256,349,346],{"__ignoreMap":350},"",[198,352,353,354,301,356,301,359,362],{},"Exact paths depend on your mount prefix (",[256,355,63],{},[256,357,358],{},"\u002Fv1\u002Fauth",[256,360,361],{},"\u002Fiam\u002Fauth",", …).",[209,364],{},[212,366,368],{"id":367},"configuration-knobs","Configuration knobs",[198,370,371,372,375,376,379],{},"Set on the preset \u002F ",[256,373,374],{},"AuthConfig"," (names may vary slightly by version — check\n",[256,377,378],{},"outlabs_auth\u002Fcore\u002Fconfig.py","):",[220,381,382,395],{},[223,383,384],{},[226,385,386,389,392],{},[229,387,388],{},"Setting",[229,390,391],{},"Typical default",[229,393,394],{},"Purpose",[239,396,397,410,425,440,458,473],{},[226,398,399,404,407],{},[244,400,401],{},[256,402,403],{},"secret_key",[244,405,406],{},"required",[244,408,409],{},"HS256 signing (≥ 32 chars)",[226,411,412,417,422],{},[244,413,414],{},[256,415,416],{},"access_token_expire_minutes",[244,418,419],{},[256,420,421],{},"15",[244,423,424],{},"Access token TTL",[226,426,427,432,437],{},[244,428,429],{},[256,430,431],{},"refresh_token_expire_days",[244,433,434],{},[256,435,436],{},"30",[244,438,439],{},"Refresh token TTL",[226,441,442,447,452],{},[244,443,444],{},[256,445,446],{},"store_refresh_tokens",[244,448,449],{},[256,450,451],{},"True",[244,453,454,455],{},"Persist refresh rows → revoke + ",[202,456,457],{"href":78},"sessions",[226,459,460,465,470],{},[244,461,462],{},[256,463,464],{},"enable_token_blacklist",[244,466,467],{},[256,468,469],{},"False",[244,471,472],{},"Immediate access-token kill switch (needs Redis)",[226,474,475,480,485],{},[244,476,477],{},[256,478,479],{},"token_blacklist_failure_mode",[244,481,482],{},[256,483,484],{},"fail_closed",[244,486,487],{},"Behavior if blacklist Redis is down",[198,489,490,491,493],{},"Production: long random ",[256,492,403],{},", HTTPS, prefer httpOnly cookies for refresh\nin browser apps (host-owned cookie transport).",[209,495],{},[212,497,499],{"id":498},"validation-and-auth-deps","Validation and auth deps",[198,501,502,503,506,507,510,511,301,513,516,517,519],{},"Host routes use ",[256,504,505],{},"auth.deps.require_auth()"," \u002F ",[256,508,509],{},"require_permission(...)",". The\nlibrary verifies signature, ",[256,512,300],{},[256,514,515],{},"type",", and audience, then loads the user\nand applies status \u002F lockout rules (",[202,518,112],{"href":113},").",[198,521,522,523,526,527,207],{},"For dependency patterns and the ",[256,524,525],{},"0.1.0a26+"," authenticate-once \u002F authorize-many\nboundary, see ",[202,528,51],{"href":52},[209,530],{},[212,532,534],{"id":533},"revocation","Revocation",[220,536,537,547],{},[223,538,539],{},[226,540,541,544],{},[229,542,543],{},"Goal",[229,545,546],{},"Mechanism",[239,548,549,557,565,576],{},[226,550,551,554],{},[244,552,553],{},"End one device \u002F login",[244,555,556],{},"Delete that refresh row (session APIs)",[226,558,559,562],{},[244,560,561],{},"End all sessions for a user",[244,563,564],{},"Delete all refresh rows for the user",[226,566,567,570],{},[244,568,569],{},"Kill a still-valid access JWT early",[244,571,572,573,575],{},"Redis blacklist (",[256,574,464],{},")",[226,577,578,581],{},[244,579,580],{},"Password change \u002F suspend \u002F ban",[244,582,583],{},"Revoke refresh tokens in the same flow",[198,585,586,587,207],{},"Without blacklist, access tokens remain valid until ",[256,588,300],{},[209,590],{},[212,592,594],{"id":593},"custom-claims","Custom claims",[198,596,597,598,601,602,506,604,506,606,506,608,610],{},"Prefer putting product claims in ",[247,599,600],{},"your"," tokens or session store. If you extend\nOutlabsAuth JWT payloads, keep ",[256,603,296],{},[256,605,515],{},[256,607,310],{},[256,609,313],{}," intact and\ndocument any audience changes for every consumer.",[209,612],{},[212,614,616],{"id":615},"related","Related",[618,619,620,625,629,633],"ul",{},[621,622,623],"li",{},[202,624,77],{"href":78},[621,626,627],{},[202,628,46],{"href":47},[621,630,631],{},[202,632,112],{"href":113},[621,634,635],{},[202,636,5],{"href":16},{"title":350,"searchDepth":638,"depth":639,"links":640},1,2,[641,645,646,647,648,649,650],{"id":214,"depth":639,"text":215,"children":642},[643],{"id":286,"depth":644,"text":287},3,{"id":339,"depth":639,"text":340},{"id":367,"depth":639,"text":368},{"id":498,"depth":639,"text":499},{"id":533,"depth":639,"text":534},{"id":593,"depth":639,"text":594},{"id":615,"depth":639,"text":616},"Access and refresh token behavior.","md",null,{},{"icon":90},{"title":87,"description":651},"RCnPEr98jMp2jXuSdI3UPxrf1Y6Jv9W_FEUKAidXSXI",[659,661],{"title":82,"path":83,"stem":84,"description":660,"icon":85,"children":-1},"Magic links, access codes, and host-owned delivery.",{"title":92,"path":93,"stem":94,"description":662,"icon":95,"children":-1},"Admin and self-service user HTTP surface.",1787472745731]