[{"data":1,"prerenderedAt":757},["ShallowReactive",2],{"navigation":3,"\u002Fauth\u002Fpasswordless-and-messaging":189,"\u002Fauth\u002Fpasswordless-and-messaging-surround":752},[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":82,"body":191,"description":745,"extension":746,"links":747,"meta":748,"navigation":749,"path":83,"seo":750,"stem":84,"__hash__":751},"docs\u002F3.auth\u002F3.passwordless-and-messaging.md",{"type":192,"value":193,"toc":734},"minimark",[194,198,220,257,262,313,317,376,394,398,428,434,451,455,458,487,537,543,547,550,562,569,573,585,589,625,632,650,654,699,703,730],[195,196,197],"p",{},"Magic links, one-time access codes, invitations, and delivery over email \u002F\nWhatsApp \u002F SMS. Split of responsibility:",[199,200,201,213],"ul",{},[202,203,204,205,209,210],"li",{},"The library ",[206,207,208],"strong",{},"mints"," secrets and stores ",[206,211,212],{},"hashes",[202,214,215,216,219],{},"Your host ",[206,217,218],{},"delivers"," messages (templates, Twilio\u002FMeta\u002FSMTP, branding)",[195,221,222,223,226,227,230,231,235,236,239,240,243,244,246,247,239,252,226],{},"Invitations walkthrough: ",[224,225,97],"a",{"href":98},".",[228,229],"br",{},"\nRunnable recipes: ",[232,233,234],"code",{},"examples\u002Fenterprise_rbac\u002F"," (",[232,237,238],{},"transactional_mail.py",",\n",[232,241,242],{},"challenge_messaging.py",").",[228,245],{},"\nMaintainer depth: ",[224,248,249],{"href":83},[232,250,251],{},"docs\u002FAUTH_EXTENSIONS.md",[224,253,254],{"href":83},[232,255,256],{},"docs\u002FWHATSAPP_ACCOUNT_MESSAGING.md",[258,259,261],"h2",{"id":260},"who-owns-what","Who owns what?",[263,264,265,278],"table",{},[266,267,268],"thead",{},[269,270,271,275],"tr",{},[272,273,274],"th",{},"Concern",[272,276,277],{},"Owner",[279,280,281,290,298,306],"tbody",{},[269,282,283,287],{},[284,285,286],"td",{},"When a challenge\u002Finvite is needed",[284,288,289],{},"Library",[269,291,292,295],{},[284,293,294],{},"Plaintext token\u002Fcode (once)",[284,296,297],{},"Returned to host hooks \u002F intents — never leave in NotificationService payloads",[269,299,300,303],{},[284,301,302],{},"Templates, Twilio\u002FMeta\u002FSMTP credentials, branding",[284,304,305],{},"Host",[269,307,308,311],{},[284,309,310],{},"Hash in Postgres + expiry + rate limits",[284,312,289],{},[258,314,316],{"id":315},"feature-flags","Feature flags",[318,319,324],"pre",{"className":320,"code":321,"language":322,"meta":323,"style":323},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","auth = EnterpriseRBAC(\n    database_url=...,\n    secret_key=...,\n    enable_invitations=True,       # default True\n    enable_magic_links=True,       # default False\n    enable_access_codes=True,      # default False\n    # magic_link_* \u002F access_code_* TTL and rate-limit knobs — see AuthConfig\n)\n","python","",[232,325,326,334,340,346,352,358,364,370],{"__ignoreMap":323},[327,328,331],"span",{"class":329,"line":330},"line",1,[327,332,333],{},"auth = EnterpriseRBAC(\n",[327,335,337],{"class":329,"line":336},2,[327,338,339],{},"    database_url=...,\n",[327,341,343],{"class":329,"line":342},3,[327,344,345],{},"    secret_key=...,\n",[327,347,349],{"class":329,"line":348},4,[327,350,351],{},"    enable_invitations=True,       # default True\n",[327,353,355],{"class":329,"line":354},5,[327,356,357],{},"    enable_magic_links=True,       # default False\n",[327,359,361],{"class":329,"line":360},6,[327,362,363],{},"    enable_access_codes=True,      # default False\n",[327,365,367],{"class":329,"line":366},7,[327,368,369],{},"    # magic_link_* \u002F access_code_* TTL and rate-limit knobs — see AuthConfig\n",[327,371,373],{"class":329,"line":372},8,[327,374,375],{},")\n",[195,377,378,379,382,383,239,386,389,390,393],{},"Mount ",[232,380,381],{},"get_auth_router"," so the HTTP endpoints exist (",[232,384,385],{},"\u002Fauth\u002Fmagic-link\u002F...",[232,387,388],{},"\u002Fauth\u002Faccess-code\u002F...",", ",[232,391,392],{},"\u002Fauth\u002Finvite",", …).",[258,395,397],{"id":396},"magic-links","Magic links",[399,400,401,408,418,421],"ol",{},[202,402,403,404,407],{},"Client requests a link (",[232,405,406],{},"POST …\u002Fauth\u002Fmagic-link\u002Frequest"," with email)",[202,409,410,411,235,414,417],{},"Library creates ",[232,412,413],{},"AuthChallenge",[232,415,416],{},"magic_link","), returns plaintext once to the\ndelivery path",[202,419,420],{},"Host emails (or otherwise sends) the link",[202,422,423,424,427],{},"Client verifies (",[232,425,426],{},"POST …\u002Fauth\u002Fmagic-link\u002Fverify",") → JWT session",[195,429,430,431,226],{},"Rate limits are email-keyed. Challenges are single-use via ",[232,432,433],{},"used_at",[195,435,436,437,440,441,444,445,448,449,226],{},"With frontend profiles configured (",[232,438,439],{},"0.1.0a25+","), requests may name a\nregistered ",[232,442,443],{},"app"," key and verification responses carry a server-validated\ncanonical ",[232,446,447],{},"next_url"," — see ",[224,450,72],{"href":73},[258,452,454],{"id":453},"access-codes","Access codes",[195,456,457],{},"Same shape as magic links, with a short numeric code.",[195,459,460,461,464,465,468,469,472,473,476,477,479,480,479,483,486],{},"Request\u002Fverify accept ",[206,462,463],{},"exactly one"," of ",[232,466,467],{},"email"," or ",[232,470,471],{},"phone"," (E.164) when phone\nlogin is enabled in your build. Optional ",[232,474,475],{},"channel",": ",[232,478,467],{}," | ",[232,481,482],{},"whatsapp",[232,484,485],{},"sms","\n(phone defaults toward WhatsApp when that path is wired).",[263,488,489,502],{},[266,490,491],{},[269,492,493,496,499],{},[272,494,495],{},"Identifier",[272,497,498],{},"Typical challenge type",[272,500,501],{},"Requirement",[279,503,504,517],{},[269,505,506,509,514],{},[284,507,508],{},"Email",[284,510,511],{},[232,512,513],{},"access_code",[284,515,516],{},"User exists (enumeration-safe responses still apply)",[269,518,519,522,531],{},[284,520,521],{},"Verified phone",[284,523,524,527,528],{},[232,525,526],{},"whatsapp_otp"," \u002F ",[232,529,530],{},"sms_otp",[284,532,533,536],{},[232,534,535],{},"phone_verified"," on the user",[195,538,539,540,226],{},"Hosts without SMS credentials should fail clearly for ",[232,541,542],{},"delivery_channel=sms",[258,544,546],{"id":545},"phone-verification","Phone verification",[195,548,549],{},"Self-service verify (users router) registers WhatsApp\u002FSMS as a delivery \u002F\nlogin destination:",[199,551,552,557],{},[202,553,554],{},[232,555,556],{},"POST …\u002Fusers\u002Fme\u002Fphone\u002Frequest-code",[202,558,559],{},[232,560,561],{},"POST …\u002Fusers\u002Fme\u002Fphone\u002Fverify-code",[195,563,564,565,568],{},"Challenge type: ",[232,566,567],{},"phone_verify",". See the WhatsApp design note for host template\nmapping.",[258,570,572],{"id":571},"invitations","Invitations",[195,574,575,576,579,580,226],{},"Admin invite → mail intent with token → accept set-password flow. Full guide:\n",[224,577,578],{"href":98},"24-User-Invitations.md",". SimpleRBAC vs Enterprise\ninvite body rules: ",[224,581,582],{"href":150},[232,583,584],{},"docs\u002FAUTH_UI.md",[258,586,588],{"id":587},"host-delivery-wiring-enterprise-example-pattern","Host delivery wiring (enterprise example pattern)",[399,590,591,605,615],{},[202,592,593,596,597,600,601,604],{},[206,594,595],{},"Transactional mail"," — invite \u002F reset \u002F access-granted shaped messages via\n",[232,598,599],{},"outlabs_auth.mail"," providers (",[232,602,603],{},"console",", SMTP, etc.)",[202,606,607,610,611,614],{},[206,608,609],{},"Challenge messaging"," — magic link \u002F access code \u002F WhatsApp \u002F SMS OTP via\nhost ",[232,612,613],{},"AuthChallengeDeliveryIntent"," (or equivalent hooks)",[202,616,617,620,621,624],{},[206,618,619],{},"NotificationService"," — ambient events only (lockouts, notices). ",[206,622,623],{},"Do not","\nput plaintext OTPs on that path",[195,626,627,628,631],{},"Environment knobs in the enterprise example (see ",[232,629,630],{},".env.example","):",[199,633,634,640,643],{},[202,635,636,639],{},[232,637,638],{},"OUTLABS_AUTH_MAIL_PROVIDER",", provider credentials, optional recipient override",[202,641,642],{},"Twilio WhatsApp Content SID + SMS from-number for live delivery",[202,644,645,646,649],{},"Debug capture endpoints under ",[232,647,648],{},"\u002Fdev\u002Fauth\u002F..."," for local QA (never in production)",[258,651,653],{"id":652},"checklist","Checklist",[199,655,658,668,681,687,693],{"className":656},[657],"contains-task-list",[202,659,662,667],{"className":660},[661],"task-list-item",[663,664],"input",{"disabled":665,"type":666},true,"checkbox"," Flags enabled only for methods you deliver",[202,669,671,673,674,676,677,680],{"className":670},[661],[663,672],{"disabled":665,"type":666}," ",[232,675,381],{}," (+ ",[232,678,679],{},"get_users_router"," for phone verify \u002F invites admin)",[202,682,684,686],{"className":683},[661],[663,685],{"disabled":665,"type":666}," Host mail and\u002For WhatsApp\u002FSMS providers configured",[202,688,690,692],{"className":689},[661],[663,691],{"disabled":665,"type":666}," Rate limits and HTTPS verified in staging",[202,694,696,698],{"className":695},[661],[663,697],{"disabled":665,"type":666}," OutlabsAuth UI pointed at the same prefix if you use its invite\u002Faccount flows",[258,700,702],{"id":701},"related","Related",[199,704,705,710,715,720,724],{},[202,706,707],{},[224,708,709],{"href":16},"01-Getting-Started.md",[202,711,712],{},[224,713,714],{"href":47},"03-Configuration.md",[202,716,717],{},[224,718,719],{"href":68},"04-OAuth-and-Social-Login.md",[202,721,722],{},[224,723,72],{"href":73},[202,725,726],{},[224,727,728],{"href":150},[232,729,584],{},[731,732,733],"style",{},"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);}",{"title":323,"searchDepth":330,"depth":336,"links":735},[736,737,738,739,740,741,742,743,744],{"id":260,"depth":336,"text":261},{"id":315,"depth":336,"text":316},{"id":396,"depth":336,"text":397},{"id":453,"depth":336,"text":454},{"id":545,"depth":336,"text":546},{"id":571,"depth":336,"text":572},{"id":587,"depth":336,"text":588},{"id":652,"depth":336,"text":653},{"id":701,"depth":336,"text":702},"Magic links, access codes, and host-owned delivery.","md",null,{},{"icon":85},{"title":82,"description":745},"53hmhP78RRgvXJq54P23rCdFbwVvWM_FoQrO6CXUuwg",[753,755],{"title":77,"path":78,"stem":79,"description":754,"icon":80,"children":-1},"Active sessions and user audit search.",{"title":87,"path":88,"stem":89,"description":756,"icon":90,"children":-1},"Access and refresh token behavior.",1787472744721]