[{"data":1,"prerenderedAt":795},["ShallowReactive",2],{"navigation":3,"-getting-started-core-concepts":167,"-getting-started-core-concepts-surround":792},[4,22,78,106,141,148],{"title":5,"path":6,"stem":7,"children":8},"Introduction","\u002Fgetting-started","0.Getting-Started\u002F0.index",[9,10,14,18],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13},"Installation","\u002Fgetting-started\u002Finstallation","0.Getting-Started\u002F1.installation",{"title":15,"path":16,"stem":17},"Quickstart","\u002Fgetting-started\u002Fquickstart","0.Getting-Started\u002F2.quickstart",{"title":19,"path":20,"stem":21},"Core concepts","\u002Fgetting-started\u002Fcore-concepts","0.Getting-Started\u002F3.core-concepts",{"title":23,"path":24,"stem":25,"children":26,"icon":28},"JWT","\u002Fjwt","1.JWT\u002F0.index",[27,29,52],{"title":23,"path":24,"stem":25,"icon":28},"i-carbon-certificate",{"title":30,"path":31,"stem":32,"children":33,"icon":35},"JWS","\u002Fjwt\u002Fjws","1.JWT\u002F1.JWS\u002F0.index",[34,36,40,44,48],{"title":30,"path":31,"stem":32,"icon":35},"i-carbon-document-signed",{"title":37,"path":38,"stem":39},"Signing","\u002Fjwt\u002Fjws\u002Fsigning","1.JWT\u002F1.JWS\u002F1.signing",{"title":41,"path":42,"stem":43},"Verifying","\u002Fjwt\u002Fjws\u002Fverifying","1.JWT\u002F1.JWS\u002F2.verifying",{"title":45,"path":46,"stem":47},"Multi-signature","\u002Fjwt\u002Fjws\u002Fmulti-signature","1.JWT\u002F1.JWS\u002F3.multi-signature",{"title":49,"path":50,"stem":51},"Algorithms","\u002Fjwt\u002Fjws\u002Falgorithms","1.JWT\u002F1.JWS\u002F4.algorithms",{"title":53,"path":54,"stem":55,"children":56,"icon":58},"JWE","\u002Fjwt\u002Fjwe","1.JWT\u002F2.JWE\u002F0.index",[57,59,63,67,71,75],{"title":53,"path":54,"stem":55,"icon":58},"i-carbon-locked",{"title":60,"path":61,"stem":62},"Encrypting","\u002Fjwt\u002Fjwe\u002Fencrypting","1.JWT\u002F2.JWE\u002F1.encrypting",{"title":64,"path":65,"stem":66},"Decrypting","\u002Fjwt\u002Fjwe\u002Fdecrypting","1.JWT\u002F2.JWE\u002F2.decrypting",{"title":68,"path":69,"stem":70},"Multi-recipient","\u002Fjwt\u002Fjwe\u002Fmulti-recipient","1.JWT\u002F2.JWE\u002F3.multi-recipient",{"title":72,"path":73,"stem":74},"ECDH-ES and end-to-end encryption","\u002Fjwt\u002Fjwe\u002Fecdh-es","1.JWT\u002F2.JWE\u002F4.ecdh-es",{"title":49,"path":76,"stem":77},"\u002Fjwt\u002Fjwe\u002Falgorithms","1.JWT\u002F2.JWE\u002F5.algorithms",{"title":79,"path":80,"stem":81,"children":82,"icon":84},"Examples","\u002Fexamples","10.Examples\u002F0.index",[83,85,90,94,98,102],{"title":79,"path":80,"stem":81,"icon":84},"i-carbon-code-reference",{"title":86,"path":87,"stem":88,"icon":89},"Authentication basics","\u002Fexamples\u002Fauthentication-basics","10.Examples\u002F1.authentication-basics","i-lucide-code",{"title":91,"path":92,"stem":93,"icon":89},"Consuming a JWKS endpoint","\u002Fexamples\u002Fjwks-endpoint","10.Examples\u002F2.jwks-endpoint",{"title":95,"path":96,"stem":97,"icon":89},"Refresh token pattern","\u002Fexamples\u002Frefresh-token-pattern","10.Examples\u002F3.refresh-token-pattern",{"title":99,"path":100,"stem":101,"icon":89},"End-to-end encryption","\u002Fexamples\u002Fend-to-end-encryption","10.Examples\u002F4.end-to-end-encryption",{"title":103,"path":104,"stem":105,"icon":89},"Signed receipts","\u002Fexamples\u002Fsigned-receipts","10.Examples\u002F5.signed-receipts",{"title":107,"path":108,"stem":109,"children":110,"icon":112},"JWK","\u002Fjwk","2.JWK\u002F0.index",[111,113,117,121,125,129,133,137],{"title":107,"path":108,"stem":109,"icon":112},"i-carbon-two-factor-authentication",{"title":114,"path":115,"stem":116},"Generating keys","\u002Fjwk\u002Fgenerating","2.JWK\u002F1.generating",{"title":118,"path":119,"stem":120},"Importing and exporting","\u002Fjwk\u002Fimport-export","2.JWK\u002F2.import-export",{"title":122,"path":123,"stem":124},"PEM conversion","\u002Fjwk\u002Fpem","2.JWK\u002F3.pem",{"title":126,"path":127,"stem":128},"Key wrapping","\u002Fjwk\u002Fwrapping","2.JWK\u002F4.wrapping",{"title":130,"path":131,"stem":132},"Password derivation","\u002Fjwk\u002Fpassword-derivation","2.JWK\u002F5.password-derivation",{"title":134,"path":135,"stem":136},"JWK Sets","\u002Fjwk\u002Fjwk-sets","2.JWK\u002F6.jwk-sets",{"title":138,"path":139,"stem":140},"JWK cache","\u002Fjwk\u002Fcache","2.JWK\u002F7.cache",{"title":142,"path":143,"stem":144,"children":145,"icon":147},"Utilities","\u002Futilities","3.Utilities\u002F0.index",[146],{"title":142,"path":143,"stem":144,"icon":147},"i-carbon-tool-box",{"title":149,"path":150,"stem":151,"children":152,"icon":154},"Adapters","\u002Fadapters","99.Adapters\u002F0.index",[153,155,159,163],{"title":149,"path":150,"stem":151,"icon":154},"i-carbon-plug",{"title":156,"path":157,"stem":158},"H3 sessions","\u002Fadapters\u002Fh3-sessions","99.Adapters\u002F1.h3-sessions",{"title":160,"path":161,"stem":162},"Lifecycle hooks","\u002Fadapters\u002Fhooks","99.Adapters\u002F2.hooks",{"title":164,"path":165,"stem":166},"Lower-level functions","\u002Fadapters\u002Flower-level","99.Adapters\u002F3.lower-level",{"id":168,"title":19,"body":169,"description":214,"extension":787,"meta":788,"navigation":789,"path":20,"seo":790,"stem":21,"__hash__":791},"content\u002F0.Getting-Started\u002F3.core-concepts.md",{"type":170,"value":171,"toc":777},"minimark",[172,193,198,204,215,218,229,270,274,283,286,296,307,311,319,321,329,339,348,352,357,433,447,457,461,467,489,493,496,643,651,655,662,709,712,723,741,749,753,773],[173,174,175,176,180,181,184,185,188,189,192],"p",{},"The JOSE specs (short for ",[177,178,179],"strong",{},"J","avaScript ",[177,182,183],{},"O","bject ",[177,186,187],{},"S","igning and ",[177,190,191],{},"E","ncryption) use several acronyms that sound alike. This page is the shortest explanation of each that still makes sense.",[194,195,197],"h2",{"id":196},"jwt-json-web-token","JWT — JSON Web Token",[173,199,200,201,203],{},"A ",[177,202,23],{}," is the end product: a small string that carries some JSON data, and is either signed or encrypted so the receiver can trust it.",[205,206,211],"pre",{"className":207,"code":209,"language":210},[208],"language-text","eyJhbGciOi...eyJzdWIiOi...SflKxwRJSM...\n\u003Cheader>   .\u003Cpayload>   .\u003Csignature>\n","text",[212,213,209],"code",{"__ignoreMap":214},"",[173,216,217],{},"Three base64url segments joined by dots. That's the \"Compact Serialization\" — by far the most common form.",[173,219,220,221,228],{},"Defined in ",[222,223,227],"a",{"href":224,"rel":225},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc7519",[226],"nofollow","RFC 7519",".",[230,231,232],"note",{},[173,233,234,235,238,239,242,243,242,246,249,250,253,254,257,258,261,262,265,266,269],{},"\"JWT\" specifically refers to tokens whose ",[177,236,237],{},"payload is a JSON object of claims"," (",[212,240,241],{},"sub",", ",[212,244,245],{},"exp",[212,247,248],{},"iss",", …). The broader term for the same dotted format is ",[177,251,252],{},"JOSE token",", and its payload can be any bytes. unjwt handles both — if you pass a ",[212,255,256],{},"string"," or ",[212,259,260],{},"Uint8Array"," to ",[212,263,264],{},"sign()","\u002F",[212,267,268],{},"encrypt()",", you get a valid JOSE token that isn't technically a JWT.",[194,271,273],{"id":272},"jws-json-web-signature","JWS — JSON Web Signature",[173,275,200,276,278,279,282],{},[177,277,30],{}," is a JWT whose payload is ",[177,280,281],{},"signed",". Anyone can read the payload; only the holder of the signing key could have produced the signature.",[173,284,285],{},"Use when:",[287,288,289,293],"ul",{},[290,291,292],"li",{},"You want the client to read the data (user ID, role, expiration) but trust it came from you.",[290,294,295],{},"The data is non-sensitive.",[173,297,220,298,303,304,228],{},[222,299,302],{"href":300,"rel":301},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc7515",[226],"RFC 7515",". → ",[222,305,306],{"href":31},"JWS in unjwt",[194,308,310],{"id":309},"jwe-json-web-encryption","JWE — JSON Web Encryption",[173,312,200,313,278,315,318],{},[177,314,53],{},[177,316,317],{},"encrypted",". Only the holder of the decryption key can read the data. Anyone else sees opaque ciphertext.",[173,320,285],{},[287,322,323,326],{},[290,324,325],{},"The payload contains sensitive data the client (or intermediary) should not see.",[290,327,328],{},"You want to keep the self-contained, signed-like shape of a JWT but with confidentiality.",[173,330,220,331,303,336,228],{},[222,332,335],{"href":333,"rel":334},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc7516",[226],"RFC 7516",[222,337,338],{"href":54},"JWE in unjwt",[340,341,342],"tip",{},[173,343,344,347],{},[177,345,346],{},"JWS or JWE?"," Signed is the default choice. Encrypt only when you have a concrete reason — encrypted tokens can't be inspected in logs, shown in DevTools, or debugged by the frontend team. You can also nest a JWS inside a JWE if you want to make sure the sender is trusted and the payload is confidential, but that's a more complex workflow.",[194,349,351],{"id":350},"jwk-json-web-key","JWK — JSON Web Key",[173,353,200,354,356],{},[177,355,107],{}," is a way to represent a cryptographic key as a JSON object. Every signing, verifying, encrypting, and decrypting operation involves a key; a JWK is unjwt's preferred way to pass keys around.",[205,358,362],{"className":359,"code":360,"language":361,"meta":214,"style":214},"language-json shiki shiki-themes github-light github-dark github-dark","{\n  \"kty\": \"oct\",\n  \"k\": \"GawgguFyGrWKav7AX4VKUg\",\n  \"alg\": \"HS256\",\n  \"kid\": \"4c3d...\"\n}\n","json",[212,363,364,373,390,403,416,427],{"__ignoreMap":214},[365,366,369],"span",{"class":367,"line":368},"line",1,[365,370,372],{"class":371},"slsVL","{\n",[365,374,376,380,383,387],{"class":367,"line":375},2,[365,377,379],{"class":378},"suiK_","  \"kty\"",[365,381,382],{"class":371},": ",[365,384,386],{"class":385},"sfrk1","\"oct\"",[365,388,389],{"class":371},",\n",[365,391,393,396,398,401],{"class":367,"line":392},3,[365,394,395],{"class":378},"  \"k\"",[365,397,382],{"class":371},[365,399,400],{"class":385},"\"GawgguFyGrWKav7AX4VKUg\"",[365,402,389],{"class":371},[365,404,406,409,411,414],{"class":367,"line":405},4,[365,407,408],{"class":378},"  \"alg\"",[365,410,382],{"class":371},[365,412,413],{"class":385},"\"HS256\"",[365,415,389],{"class":371},[365,417,419,422,424],{"class":367,"line":418},5,[365,420,421],{"class":378},"  \"kid\"",[365,423,382],{"class":371},[365,425,426],{"class":385},"\"4c3d...\"\n",[365,428,430],{"class":367,"line":429},6,[365,431,432],{"class":371},"}\n",[173,434,200,435,438,439,442,443,446],{},[177,436,437],{},"JWK Set"," (or JWKS) is simply a JSON document with a ",[212,440,441],{},"keys"," array — typically published at ",[212,444,445],{},"\u002F.well-known\u002Fjwks.json"," by OAuth\u002FOIDC providers.",[173,448,220,449,303,454,228],{},[222,450,453],{"href":451,"rel":452},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc7517",[226],"RFC 7517",[222,455,456],{"href":108},"JWK in unjwt",[194,458,460],{"id":459},"how-they-fit-together","How they fit together",[205,462,465],{"className":463,"code":464,"language":210},[208],"      ┌─────────────────────────────┐\n      │             JWT             │  ← the portable string\n      └──────────────┬──────────────┘\n                     │\n        ┌────────────┴────────────┐\n        ▼                         ▼\n       JWS                       JWE\n     (signed)                (encrypted)\n        │                         │\n        └────────────┬────────────┘\n                     ▼\n                    JWK\n  (the key used to produce or consume the above)\n",[212,466,464],{"__ignoreMap":214},[287,468,469,479],{},[290,470,200,471,473,474,476,477,228],{},[177,472,23],{}," is either a ",[177,475,30],{}," or a ",[177,478,53],{},[290,480,481,482,484,485,488],{},"Both use a ",[177,483,107],{}," as the key (or a ",[212,486,487],{},"CryptoKey"," \u002F password \u002F raw bytes, which unjwt normalizes internally).",[194,490,492],{"id":491},"the-claims-youll-actually-see","The claims you'll actually see",[173,494,495],{},"Inside a JWT payload, certain claim names are standardized. unjwt validates the ones that affect security automatically:",[497,498,499,522],"table",{},[500,501,502],"thead",{},[503,504,505,509,512],"tr",{},[506,507,508],"th",{},"Claim",[506,510,511],{},"Meaning",[506,513,514,515,518,519],{},"Validated by ",[212,516,517],{},"verify()"," \u002F ",[212,520,521],{},"decrypt()",[523,524,525,542,556,571,583,596,612,628],"tbody",{},[503,526,527,532,535],{},[528,529,530],"td",{},[212,531,248],{},[528,533,534],{},"Issuer",[528,536,537,538,541],{},"Only if ",[212,539,540],{},"options.issuer"," is set",[503,543,544,548,551],{},[528,545,546],{},[212,547,241],{},[528,549,550],{},"Subject",[528,552,537,553,541],{},[212,554,555],{},"options.subject",[503,557,558,563,566],{},[528,559,560],{},[212,561,562],{},"aud",[528,564,565],{},"Audience",[528,567,537,568,541],{},[212,569,570],{},"options.audience",[503,572,573,577,580],{},[528,574,575],{},[212,576,245],{},[528,578,579],{},"Expires at (seconds)",[528,581,582],{},"Always — rejects expired tokens",[503,584,585,590,593],{},[528,586,587],{},[212,588,589],{},"nbf",[528,591,592],{},"Not before (seconds)",[528,594,595],{},"Always — rejects tokens used before the specified time",[503,597,598,603,606],{},[528,599,600],{},[212,601,602],{},"iat",[528,604,605],{},"Issued at (seconds)",[528,607,608,609],{},"Type-checked; used with ",[212,610,611],{},"options.maxTokenAge",[503,613,614,619,622],{},[528,615,616],{},[212,617,618],{},"jti",[528,620,621],{},"JWT ID",[528,623,624,625],{},"Not validated, but the H3 session adapters use it as a ",[212,626,627],{},"session.id",[503,629,630,635,638],{},[528,631,632],{},[212,633,634],{},"typ",[528,636,637],{},"Type header (e.g. JWT)",[528,639,537,640,541],{},[212,641,642],{},"options.typ",[173,644,645,646,228],{},"Full definitions in ",[222,647,650],{"href":648,"rel":649},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc7519#section-4.1",[226],"RFC 7519 §4.1",[194,652,654],{"id":653},"whats-an-algorithm","What's an \"algorithm\"?",[173,656,657,658,661],{},"A JWS or JWE header always carries an ",[212,659,660],{},"alg"," field naming the algorithm the token was produced with. unjwt reads it back to choose the preferred verification path. The algorithms split into two families:",[287,663,664,694],{},[290,665,666,238,669,671,672,675,676,242,679,682,683,686,687,690,691,228],{},[177,667,668],{},"Signing algorithms",[212,670,660],{}," in a JWS): HMAC (",[212,673,674],{},"HS*","), RSA (",[212,677,678],{},"RS*",[212,680,681],{},"PS*","), ECDSA (",[212,684,685],{},"ES*","), EdDSA (",[212,688,689],{},"Ed25519","). See ",[222,692,693],{"href":50},"JWS algorithms",[290,695,696,238,699,701,702,705,706,228],{},[177,697,698],{},"Key-management algorithms",[212,700,660],{}," in a JWE): how the content key is delivered. Direct (",[212,703,704],{},"dir","), AES Key Wrap, RSA-OAEP, PBES2, ECDH-ES. See ",[222,707,708],{"href":76},"JWE algorithms",[173,710,711],{},"Plus one more for JWE only:",[287,713,714],{},[290,715,716,238,719,722],{},[177,717,718],{},"Content-encryption algorithms",[212,720,721],{},"enc"," in a JWE): AES-GCM or AES-CBC+HMAC-SHA2 — the cipher that encrypts the actual payload.",[173,724,725,726,728,729,732,733,265,735,737,738,740],{},"When you pass a JWK that has an ",[212,727,660],{}," field set (which ",[212,730,731],{},"generateJWK()"," always does), unjwt uses it automatically. You only need to specify ",[212,734,660],{},[212,736,721],{}," explicitly when the key carries no such metadata (raw bytes, untyped JWKs, ",[212,739,487],{}," objects without algorithm hints).",[173,742,743,744,228],{},"Full algorithm registry: ",[222,745,748],{"href":746,"rel":747},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc7518",[226],"RFC 7518",[194,750,752],{"id":751},"ready","Ready?",[287,754,755,761,767],{},[290,756,757,758],{},"If you want to start writing code: ",[222,759,760],{"href":16},"Quickstart →",[290,762,763,764],{},"If you want to understand the signed path: ",[222,765,766],{"href":31},"JWS →",[290,768,769,770],{},"If you want the encrypted path: ",[222,771,772],{"href":54},"JWE →",[774,775,776],"style",{},"html pre.shiki code .slsVL, html code.shiki .slsVL{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .suiK_, html code.shiki .suiK_{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html pre.shiki code .sfrk1, html code.shiki .sfrk1{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}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":214,"searchDepth":375,"depth":375,"links":778},[779,780,781,782,783,784,785,786],{"id":196,"depth":375,"text":197},{"id":272,"depth":375,"text":273},{"id":309,"depth":375,"text":310},{"id":350,"depth":375,"text":351},{"id":459,"depth":375,"text":460},{"id":491,"depth":375,"text":492},{"id":653,"depth":375,"text":654},{"id":751,"depth":375,"text":752},"md",{},{},{"title":19,"description":214},"jo6G8lpG2DEorUcTK_mDB21B3tjYi7AaLitIlLB1BMY",[793,794],{"title":15,"path":16,"stem":17,"description":214,"children":-1},{"title":23,"path":24,"stem":25,"description":214,"icon":28,"children":-1},1776888560029]