[{"data":1,"prerenderedAt":1243},["ShallowReactive",2],{"navigation_docs":3,"-auth-overview":172,"-auth-overview-surround":1238},[4,26,67,98,124,140,161],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":25},"Getting Started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Quick Start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start","i-lucide-play",false,{"title":27,"icon":28,"path":29,"stem":30,"children":31,"page":25},"Core","i-lucide-box","\u002Fcore","2.core",[32,37,42,47,52,57,62],{"title":33,"path":34,"stem":35,"icon":36},"Routing","\u002Fcore\u002Frouting","2.core\u002F1.routing","i-lucide-route",{"title":38,"path":39,"stem":40,"icon":41},"Handlers","\u002Fcore\u002Fhandlers","2.core\u002F2.handlers","i-lucide-braces",{"title":43,"path":44,"stem":45,"icon":46},"Request Binding","\u002Fcore\u002Frequest-binding","2.core\u002F3.request-binding","i-lucide-tags",{"title":48,"path":49,"stem":50,"icon":51},"Validation","\u002Fcore\u002Fvalidation","2.core\u002F4.validation","i-lucide-check-check",{"title":53,"path":54,"stem":55,"icon":56},"Context","\u002Fcore\u002Fcontext","2.core\u002F5.context","i-lucide-file-input",{"title":58,"path":59,"stem":60,"icon":61},"Errors","\u002Fcore\u002Ferrors","2.core\u002F6.errors","i-lucide-triangle-alert",{"title":63,"path":64,"stem":65,"icon":66},"Middleware","\u002Fcore\u002Fmiddleware","2.core\u002F7.middleware","i-lucide-layers",{"title":68,"icon":69,"path":70,"stem":71,"children":72,"page":25},"Auth","i-lucide-shield-check","\u002Fauth","3.auth",[73,78,83,88,93],{"title":74,"path":75,"stem":76,"icon":77},"Overview","\u002Fauth\u002Foverview","3.auth\u002F1.overview","i-lucide-shield",{"title":79,"path":80,"stem":81,"icon":82},"Auth Rules","\u002Fauth\u002Fauth-rules","3.auth\u002F2.auth-rules","i-lucide-lock",{"title":84,"path":85,"stem":86,"icon":87},"JWT Providers","\u002Fauth\u002Fjwt-providers","3.auth\u002F3.jwt-providers","i-lucide-key",{"title":89,"path":90,"stem":91,"icon":92},"Roles & Permissions","\u002Fauth\u002Froles-and-permissions","3.auth\u002F4.roles-and-permissions","i-lucide-users",{"title":94,"path":95,"stem":96,"icon":97},"Audit Logging","\u002Fauth\u002Faudit-logging","3.auth\u002F5.audit-logging","i-lucide-scroll-text",{"title":99,"icon":100,"path":101,"stem":102,"children":103,"page":25},"GoTrue","i-lucide-key-round","\u002Fgotrue","4.gotrue",[104,109,114,119],{"title":105,"path":106,"stem":107,"icon":108},"Proxy","\u002Fgotrue\u002Fproxy","4.gotrue\u002F1.proxy","i-lucide-shuffle",{"title":110,"path":111,"stem":112,"icon":113},"Endpoints","\u002Fgotrue\u002Fendpoints","4.gotrue\u002F2.endpoints","i-lucide-list",{"title":115,"path":116,"stem":117,"icon":118},"Client IP & Rate Limits","\u002Fgotrue\u002Fclient-ip-and-rate-limits","4.gotrue\u002F3.client-ip-and-rate-limits","i-lucide-network",{"title":120,"path":121,"stem":122,"icon":123},"Deployment","\u002Fgotrue\u002Fdeployment","4.gotrue\u002F4.deployment","i-lucide-server",{"title":125,"icon":126,"path":127,"stem":128,"children":129,"page":25},"API Docs","i-lucide-file-text","\u002Fapi-docs","5.api-docs",[130,135],{"title":131,"path":132,"stem":133,"icon":134},"OpenAPI","\u002Fapi-docs\u002Fopenapi","5.api-docs\u002F1.openapi","i-lucide-file-json",{"title":136,"path":137,"stem":138,"icon":139},"Scalar UI","\u002Fapi-docs\u002Fscalar","5.api-docs\u002F2.scalar","i-lucide-book-open-text",{"title":141,"icon":142,"path":143,"stem":144,"children":145,"page":25},"Guides","i-lucide-compass","\u002Fguides","6.guides",[146,151,156],{"title":147,"path":148,"stem":149,"icon":150},"Testing","\u002Fguides\u002Ftesting","6.guides\u002F1.testing","i-lucide-flask-conical",{"title":152,"path":153,"stem":154,"icon":155},"Performance","\u002Fguides\u002Fperformance","6.guides\u002F2.performance","i-lucide-gauge",{"title":157,"path":158,"stem":159,"icon":160},"Releasing","\u002Fguides\u002Freleasing","6.guides\u002F3.releasing","i-lucide-tag",{"title":162,"icon":163,"path":164,"stem":165,"children":166,"page":25},"Reference","i-lucide-code","\u002Freference","7.reference",[167],{"title":168,"path":169,"stem":170,"icon":171},"API Reference","\u002Freference\u002Fapi-reference","7.reference\u002F1.api-reference","i-lucide-list-tree",{"id":173,"title":74,"body":174,"description":1231,"extension":1232,"links":1233,"meta":1234,"navigation":1235,"path":75,"seo":1236,"stem":76,"__hash__":1237},"docs\u002F3.auth\u002F1.overview.md",{"type":175,"value":176,"toc":1223},"minimark",[177,181,261,264,269,363,370,517,529,532,566,570,573,625,635,647,651,661,692,791,795,964,970,1039,1042,1118,1122,1195,1199,1219],[178,179,180],"p",{},"Authentication in ezz is a single interface plus a per-route rule. You register one provider on the app; each route carries a rule saying what it needs.",[182,183,188],"pre",{"className":184,"code":185,"language":186,"meta":187,"style":187},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","type AuthProvider interface {\n    Authenticate(r *http.Request) (any, error)\n}\n","go","",[189,190,191,210,255],"code",{"__ignoreMap":187},[192,193,196,200,204,207],"span",{"class":194,"line":195},"line",1,[192,197,199],{"class":198},"sMK4o","type",[192,201,203],{"class":202},"sBMFI"," AuthProvider",[192,205,206],{"class":198}," interface",[192,208,209],{"class":198}," {\n",[192,211,213,217,220,224,227,230,233,236,239,242,245,248,252],{"class":194,"line":212},2,[192,214,216],{"class":215},"s2Zo4","    Authenticate",[192,218,219],{"class":198},"(",[192,221,223],{"class":222},"sHdIc","r",[192,225,226],{"class":198}," *",[192,228,229],{"class":202},"http",[192,231,232],{"class":198},".",[192,234,235],{"class":202},"Request",[192,237,238],{"class":198},")",[192,240,241],{"class":198}," (",[192,243,244],{"class":202},"any",[192,246,247],{"class":198},",",[192,249,251],{"class":250},"spNyl"," error",[192,253,254],{"class":198},")\n",[192,256,258],{"class":194,"line":257},3,[192,259,260],{"class":198},"}\n",[178,262,263],{},"The provider turns a request into a user value of any type. The rule decides whether that user may proceed.",[265,266,268],"h2",{"id":267},"turn-authentication-on","Turn authentication on",[182,270,272],{"className":184,"code":271,"language":186,"meta":187,"style":187},"jwt := auth.NewHMACProvider(os.Getenv(\"JWT_SECRET\"), \"my-service\")\napp := ezz.New().Auth(auth.NewJWTAuthProvider(jwt))\n",[189,273,274,325],{"__ignoreMap":187},[192,275,276,280,283,286,288,291,293,296,298,301,303,306,310,312,315,318,321,323],{"class":194,"line":195},[192,277,279],{"class":278},"sTEyZ","jwt ",[192,281,282],{"class":198},":=",[192,284,285],{"class":278}," auth",[192,287,232],{"class":198},[192,289,290],{"class":215},"NewHMACProvider",[192,292,219],{"class":198},[192,294,295],{"class":278},"os",[192,297,232],{"class":198},[192,299,300],{"class":215},"Getenv",[192,302,219],{"class":198},[192,304,305],{"class":198},"\"",[192,307,309],{"class":308},"sfazB","JWT_SECRET",[192,311,305],{"class":198},[192,313,314],{"class":198},"),",[192,316,317],{"class":198}," \"",[192,319,320],{"class":308},"my-service",[192,322,305],{"class":198},[192,324,254],{"class":198},[192,326,327,330,332,335,337,340,343,345,347,350,352,355,357,360],{"class":194,"line":212},[192,328,329],{"class":278},"app ",[192,331,282],{"class":198},[192,333,334],{"class":278}," ezz",[192,336,232],{"class":198},[192,338,339],{"class":215},"New",[192,341,342],{"class":198},"().",[192,344,68],{"class":215},[192,346,219],{"class":198},[192,348,349],{"class":278},"auth",[192,351,232],{"class":198},[192,353,354],{"class":215},"NewJWTAuthProvider",[192,356,219],{"class":198},[192,358,359],{"class":278},"jwt",[192,361,362],{"class":198},"))\n",[178,364,365,366,369],{},"From that point, every route requires a valid token, because the app's default rule is ",[189,367,368],{},"ezz.Authenticated()",". Public endpoints are explicit:",[182,371,373],{"className":184,"code":372,"language":186,"meta":187,"style":187},"app.GET(\"\u002Fhealth\", health).Public()\napp.POST(\"\u002Flogin\", login).Public()\napp.GET(\"\u002Fme\", profile)                             \u002F\u002F needs a token\napp.GET(\"\u002Fadmin\", panel).Auth(ezz.Role(\"admin\"))    \u002F\u002F needs the admin role\n",[189,374,375,408,437,465],{"__ignoreMap":187},[192,376,377,380,382,385,387,389,392,394,396,399,402,405],{"class":194,"line":195},[192,378,379],{"class":278},"app",[192,381,232],{"class":198},[192,383,384],{"class":215},"GET",[192,386,219],{"class":198},[192,388,305],{"class":198},[192,390,391],{"class":308},"\u002Fhealth",[192,393,305],{"class":198},[192,395,247],{"class":198},[192,397,398],{"class":278}," health",[192,400,401],{"class":198},").",[192,403,404],{"class":215},"Public",[192,406,407],{"class":198},"()\n",[192,409,410,412,414,417,419,421,424,426,428,431,433,435],{"class":194,"line":212},[192,411,379],{"class":278},[192,413,232],{"class":198},[192,415,416],{"class":215},"POST",[192,418,219],{"class":198},[192,420,305],{"class":198},[192,422,423],{"class":308},"\u002Flogin",[192,425,305],{"class":198},[192,427,247],{"class":198},[192,429,430],{"class":278}," login",[192,432,401],{"class":198},[192,434,404],{"class":215},[192,436,407],{"class":198},[192,438,439,441,443,445,447,449,452,454,456,459,461],{"class":194,"line":257},[192,440,379],{"class":278},[192,442,232],{"class":198},[192,444,384],{"class":215},[192,446,219],{"class":198},[192,448,305],{"class":198},[192,450,451],{"class":308},"\u002Fme",[192,453,305],{"class":198},[192,455,247],{"class":198},[192,457,458],{"class":278}," profile",[192,460,238],{"class":198},[192,462,464],{"class":463},"sHwdD","                             \u002F\u002F needs a token\n",[192,466,468,470,472,474,476,478,481,483,485,488,490,492,494,497,499,502,504,506,509,511,514],{"class":194,"line":467},4,[192,469,379],{"class":278},[192,471,232],{"class":198},[192,473,384],{"class":215},[192,475,219],{"class":198},[192,477,305],{"class":198},[192,479,480],{"class":308},"\u002Fadmin",[192,482,305],{"class":198},[192,484,247],{"class":198},[192,486,487],{"class":278}," panel",[192,489,401],{"class":198},[192,491,68],{"class":215},[192,493,219],{"class":198},[192,495,496],{"class":278},"ezz",[192,498,232],{"class":198},[192,500,501],{"class":215},"Role",[192,503,219],{"class":198},[192,505,305],{"class":198},[192,507,508],{"class":308},"admin",[192,510,305],{"class":198},[192,512,513],{"class":198},"))",[192,515,516],{"class":463},"    \u002F\u002F needs the admin role\n",[518,519,520,521,524,525,528],"warning",{},"Without ",[189,522,523],{},"app.Auth(...)",", no rule is enforced, including ",[189,526,527],{},"ezz.Role(...)",". The check is skipped entirely when there is no provider, so a service with route rules but no provider serves everything to everyone. Register the provider in the same place you build the app.",[178,530,531],{},"To invert the default and opt into protection per route:",[182,533,535],{"className":184,"code":534,"language":186,"meta":187,"style":187},"app := ezz.New().Auth(provider).DefaultAuth(nil)\n",[189,536,537],{"__ignoreMap":187},[192,538,539,541,543,545,547,549,551,553,555,558,560,563],{"class":194,"line":195},[192,540,329],{"class":278},[192,542,282],{"class":198},[192,544,334],{"class":278},[192,546,232],{"class":198},[192,548,339],{"class":215},[192,550,342],{"class":198},[192,552,68],{"class":215},[192,554,219],{"class":198},[192,556,557],{"class":278},"provider",[192,559,401],{"class":198},[192,561,562],{"class":215},"DefaultAuth",[192,564,565],{"class":198},"(nil)\n",[265,567,569],{"id":568},"follow-a-request-through","Follow a request through",[178,571,572],{},"For a route that is not public:",[574,575,576,587,594,611,622],"ol",{},[577,578,579,582,583,586],"li",{},[189,580,581],{},"Authenticate(r)"," runs. An error means ",[189,584,585],{},"401"," and the request stops.",[577,588,589,590,593],{},"The route's rule gets the returned user. ",[189,591,592],{},"Check"," returning nil lets the request continue.",[577,595,596,597,599,600,603,604,607,608,232],{},"If ",[189,598,592],{}," fails, ezz looks at the user for a resolver error first. If there is one, the response is ",[189,601,602],{},"500","; otherwise it is ",[189,605,606],{},"403",", or the status carried by the returned ",[189,609,610],{},"*ezz.HTTPError",[577,612,613,614,617,618,621],{},"The user is attached to the request context, so ",[189,615,616],{},"ctx.User()"," and ",[189,619,620],{},"ezz.UserFromContext"," can reach it.",[577,623,624],{},"The middleware chain and your handler run.",[178,626,627,628,631,632,634],{},"Public routes skip all of it, so ",[189,629,630],{},"Authenticate"," is never called and ",[189,633,616],{}," is nil.",[636,637,638,639,617,641,643,644,232],"caution",{},"This check happens before the middleware chain, so ",[189,640,585],{},[189,642,606],{}," responses are not passed through logging, recovery, or CORS middleware. See the ordering notes in ",[645,646,63],"a",{"href":64},[265,648,650],{"id":649},"what-the-jwt-provider-gives-you","What the JWT provider gives you",[178,652,653,656,657,660],{},[189,654,655],{},"auth.NewJWTAuthProvider(jwtProvider)"," adapts any ",[189,658,659],{},"auth.JWTProvider"," to the app interface. It:",[662,663,664,679,682,685],"ul",{},[577,665,666,667,670,671,674,675,678],{},"pulls the token from ",[189,668,669],{},"Authorization: Bearer \u003Ctoken>",", then the ",[189,672,673],{},"token"," query parameter, then an ",[189,676,677],{},"access_token"," cookie;",[577,680,681],{},"validates it with the underlying provider;",[577,683,684],{},"logs a failure through the audit logger, when one is configured;",[577,686,687,688,691],{},"returns an ",[189,689,690],{},"*auth.AuthorizedUser",", which exposes the claims and answers role and permission checks.",[182,693,695],{"className":184,"code":694,"language":186,"meta":187,"style":187},"provider := auth.NewJWTAuthProvider(jwt).\n    WithResolver(myResolver{db: db}).          \u002F\u002F roles and permissions from your store\n    WithAuditLogger(auth.NewSlogAuditLogger(nil))\n\napp := ezz.New().Auth(provider)\n",[189,696,697,717,745,762,768],{"__ignoreMap":187},[192,698,699,702,704,706,708,710,712,714],{"class":194,"line":195},[192,700,701],{"class":278},"provider ",[192,703,282],{"class":198},[192,705,285],{"class":278},[192,707,232],{"class":198},[192,709,354],{"class":215},[192,711,219],{"class":198},[192,713,359],{"class":278},[192,715,716],{"class":198},").\n",[192,718,719,722,724,727,730,733,736,739,742],{"class":194,"line":212},[192,720,721],{"class":215},"    WithResolver",[192,723,219],{"class":198},[192,725,726],{"class":202},"myResolver",[192,728,729],{"class":198},"{",[192,731,732],{"class":278},"db",[192,734,735],{"class":198},":",[192,737,738],{"class":278}," db",[192,740,741],{"class":198},"}).",[192,743,744],{"class":463},"          \u002F\u002F roles and permissions from your store\n",[192,746,747,750,752,754,756,759],{"class":194,"line":257},[192,748,749],{"class":215},"    WithAuditLogger",[192,751,219],{"class":198},[192,753,349],{"class":278},[192,755,232],{"class":198},[192,757,758],{"class":215},"NewSlogAuditLogger",[192,760,761],{"class":198},"(nil))\n",[192,763,764],{"class":194,"line":467},[192,765,767],{"emptyLinePlaceholder":766},true,"\n",[192,769,771,773,775,777,779,781,783,785,787,789],{"class":194,"line":770},5,[192,772,329],{"class":278},[192,774,282],{"class":198},[192,776,334],{"class":278},[192,778,232],{"class":198},[192,780,339],{"class":215},[192,782,342],{"class":198},[192,784,68],{"class":215},[192,786,219],{"class":198},[192,788,557],{"class":278},[192,790,254],{"class":198},[265,792,794],{"id":793},"reach-the-user-in-a-handler","Reach the user in a handler",[182,796,798],{"className":184,"code":797,"language":186,"meta":187,"style":187},"app.GET(\"\u002Fme\", ezz.HFunc(func(ctx *ezz.Context) (*Profile, error) {\n    user, ok := ctx.User().(auth.User)\n    if !ok {\n        return nil, ezz.Unauthorized(\"no user on request\")\n    }\n    return loadProfile(ctx, user.ID())\n}))\n",[189,799,800,855,886,901,927,932,958],{"__ignoreMap":187},[192,801,802,804,806,808,810,812,814,816,818,820,822,825,828,831,833,835,837,839,841,844,847,849,851,853],{"class":194,"line":195},[192,803,379],{"class":278},[192,805,232],{"class":198},[192,807,384],{"class":215},[192,809,219],{"class":198},[192,811,305],{"class":198},[192,813,451],{"class":308},[192,815,305],{"class":198},[192,817,247],{"class":198},[192,819,334],{"class":278},[192,821,232],{"class":198},[192,823,824],{"class":215},"HFunc",[192,826,827],{"class":198},"(func(",[192,829,830],{"class":222},"ctx",[192,832,226],{"class":198},[192,834,496],{"class":202},[192,836,232],{"class":198},[192,838,53],{"class":202},[192,840,238],{"class":198},[192,842,843],{"class":198}," (*",[192,845,846],{"class":202},"Profile",[192,848,247],{"class":198},[192,850,251],{"class":250},[192,852,238],{"class":198},[192,854,209],{"class":198},[192,856,857,860,862,865,867,870,872,875,878,880,882,884],{"class":194,"line":212},[192,858,859],{"class":278},"    user",[192,861,247],{"class":198},[192,863,864],{"class":278}," ok ",[192,866,282],{"class":198},[192,868,869],{"class":278}," ctx",[192,871,232],{"class":198},[192,873,874],{"class":215},"User",[192,876,877],{"class":198},"().(",[192,879,349],{"class":202},[192,881,232],{"class":198},[192,883,874],{"class":202},[192,885,254],{"class":198},[192,887,888,892,895,898],{"class":194,"line":257},[192,889,891],{"class":890},"s7zQu","    if",[192,893,894],{"class":198}," !",[192,896,897],{"class":278},"ok ",[192,899,900],{"class":198},"{\n",[192,902,903,906,909,911,913,916,918,920,923,925],{"class":194,"line":467},[192,904,905],{"class":890},"        return",[192,907,908],{"class":198}," nil,",[192,910,334],{"class":278},[192,912,232],{"class":198},[192,914,915],{"class":215},"Unauthorized",[192,917,219],{"class":198},[192,919,305],{"class":198},[192,921,922],{"class":308},"no user on request",[192,924,305],{"class":198},[192,926,254],{"class":198},[192,928,929],{"class":194,"line":770},[192,930,931],{"class":198},"    }\n",[192,933,935,938,941,943,945,947,950,952,955],{"class":194,"line":934},6,[192,936,937],{"class":890},"    return",[192,939,940],{"class":215}," loadProfile",[192,942,219],{"class":198},[192,944,830],{"class":278},[192,946,247],{"class":198},[192,948,949],{"class":278}," user",[192,951,232],{"class":198},[192,953,954],{"class":215},"ID",[192,956,957],{"class":198},"())\n",[192,959,961],{"class":194,"line":960},7,[192,962,963],{"class":198},"}))\n",[178,965,966,969],{},[189,967,968],{},"auth.User"," is the interface the built-in user values satisfy:",[182,971,973],{"className":184,"code":972,"language":186,"meta":187,"style":187},"type User interface {\n    ID() string\n    GetClaims() *Claims\n    GetAttribute(key string) (any, bool)\n}\n",[189,974,975,986,997,1009,1035],{"__ignoreMap":187},[192,976,977,979,982,984],{"class":194,"line":195},[192,978,199],{"class":198},[192,980,981],{"class":202}," User",[192,983,206],{"class":198},[192,985,209],{"class":198},[192,987,988,991,994],{"class":194,"line":212},[192,989,990],{"class":215},"    ID",[192,992,993],{"class":198},"()",[192,995,996],{"class":250}," string\n",[192,998,999,1002,1004,1006],{"class":194,"line":257},[192,1000,1001],{"class":215},"    GetClaims",[192,1003,993],{"class":198},[192,1005,226],{"class":198},[192,1007,1008],{"class":202},"Claims\n",[192,1010,1011,1014,1016,1019,1022,1024,1026,1028,1030,1033],{"class":194,"line":467},[192,1012,1013],{"class":215},"    GetAttribute",[192,1015,219],{"class":198},[192,1017,1018],{"class":222},"key",[192,1020,1021],{"class":250}," string",[192,1023,238],{"class":198},[192,1025,241],{"class":198},[192,1027,244],{"class":202},[192,1029,247],{"class":198},[192,1031,1032],{"class":250}," bool",[192,1034,254],{"class":198},[192,1036,1037],{"class":194,"line":770},[192,1038,260],{"class":198},[178,1040,1041],{},"For role checks inside a handler, assert the narrower interface instead of a concrete type:",[182,1043,1045],{"className":184,"code":1044,"language":186,"meta":187,"style":187},"if rc, ok := ctx.User().(interface{ HasRole(string) bool }); ok && rc.HasRole(\"admin\") {\n    \u002F\u002F admin-only branch\n}\n",[189,1046,1047,1109,1114],{"__ignoreMap":187},[192,1048,1049,1052,1055,1057,1059,1061,1063,1065,1067,1070,1073,1075,1078,1080,1082,1085,1087,1090,1092,1094,1097,1099,1101,1103,1105,1107],{"class":194,"line":195},[192,1050,1051],{"class":890},"if",[192,1053,1054],{"class":278}," rc",[192,1056,247],{"class":198},[192,1058,864],{"class":278},[192,1060,282],{"class":198},[192,1062,869],{"class":278},[192,1064,232],{"class":198},[192,1066,874],{"class":215},[192,1068,1069],{"class":198},"().(interface{",[192,1071,1072],{"class":215}," HasRole",[192,1074,219],{"class":198},[192,1076,1077],{"class":250},"string",[192,1079,238],{"class":198},[192,1081,1032],{"class":250},[192,1083,1084],{"class":198}," });",[192,1086,864],{"class":278},[192,1088,1089],{"class":198},"&&",[192,1091,1054],{"class":278},[192,1093,232],{"class":198},[192,1095,1096],{"class":215},"HasRole",[192,1098,219],{"class":198},[192,1100,305],{"class":198},[192,1102,508],{"class":308},[192,1104,305],{"class":198},[192,1106,238],{"class":198},[192,1108,209],{"class":198},[192,1110,1111],{"class":194,"line":212},[192,1112,1113],{"class":463},"    \u002F\u002F admin-only branch\n",[192,1115,1116],{"class":194,"line":257},[192,1117,260],{"class":198},[265,1119,1121],{"id":1120},"pick-your-approach","Pick your approach",[1123,1124,1125,1138],"table",{},[1126,1127,1128],"thead",{},[1129,1130,1131,1135],"tr",{},[1132,1133,1134],"th",{},"Situation",[1132,1136,1137],{},"Use",[1139,1140,1141,1155,1172,1183],"tbody",{},[1129,1142,1143,1147],{},[1144,1145,1146],"td",{},"You issue your own HS256 tokens",[1144,1148,1149],{},[645,1150,1152],{"href":1151},"\u002Fauth\u002Fjwt-providers#issue-and-validate-your-own-tokens",[189,1153,1154],{},"auth.NewHMACProvider",[1129,1156,1157,1160],{},[1144,1158,1159],{},"GoTrue or Supabase issues tokens",[1144,1161,1162,1168,1169],{},[645,1163,1165],{"href":1164},"\u002Fauth\u002Fjwt-providers#validate-gotrue-tokens",[189,1166,1167],{},"auth.NewGoTrueProvider"," or the ",[645,1170,1171],{"href":106},"GoTrue proxy",[1129,1173,1174,1177],{},[1144,1175,1176],{},"Roles and permissions live in your database",[1144,1178,1179,1180],{},"An ",[645,1181,1182],{"href":90},"authorization resolver",[1129,1184,1185,1188],{},[1144,1186,1187],{},"API keys, sessions, or mTLS",[1144,1189,1190,1191,1194],{},"Implement ",[189,1192,1193],{},"ezz.AuthProvider"," yourself",[265,1196,1198],{"id":1197},"next-steps","Next steps",[662,1200,1201,1207,1213],{},[577,1202,1203,1206],{},[645,1204,1205],{"href":80},"Auth rules"," for the rule set and how precedence works.",[577,1208,1209,1212],{},[645,1210,1211],{"href":90},"Roles and permissions"," for authorization backed by your own data.",[577,1214,1215,1218],{},[645,1216,1217],{"href":95},"Audit logging"," for a record of auth events.",[1220,1221,1222],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}",{"title":187,"searchDepth":212,"depth":212,"links":1224},[1225,1226,1227,1228,1229,1230],{"id":267,"depth":212,"text":268},{"id":568,"depth":212,"text":569},{"id":649,"depth":212,"text":650},{"id":793,"depth":212,"text":794},{"id":1120,"depth":212,"text":1121},{"id":1197,"depth":212,"text":1198},"How authentication is wired into the app, and what happens on every request.","md",null,{},{"icon":77},{"title":74,"description":1231},"nk3eL21kPoUZ826cvNG2lHUjDpVw5IHXjZ9JPn0nrXk",[1239,1241],{"title":63,"path":64,"stem":65,"description":1240,"icon":66,"children":-1},"Use the built-in middleware, add your own, and understand the order everything runs in.",{"title":79,"path":80,"stem":81,"description":1242,"icon":82,"children":-1},"Require authentication, roles, permissions, or your own predicate, per route or per group.",1784970045269]