[{"data":1,"prerenderedAt":573},["ShallowReactive",2],{"navigation":3,"-getting-started":167,"-getting-started-surround":570},[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":5,"body":169,"description":254,"extension":565,"meta":566,"navigation":567,"path":6,"seo":568,"stem":7,"__hash__":569},"content\u002F0.Getting-Started\u002F0.index.md",{"type":170,"value":171,"toc":559},"minimark",[172,188,193,196,217,228,244,248,410,413,417,447,450,502,506,528,555],[173,174,175,179,180,187],"p",{},[176,177,178],"strong",{},"unjwt"," is a low-level JSON Web Token (JWT) library built entirely on the ",[181,182,186],"a",{"href":183,"rel":184},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FWeb_Crypto_API",[185],"nofollow","Web Crypto API",". It gives you the pieces you need to sign, verify, encrypt, decrypt, and manage keys — nothing more, and nothing hidden.",[189,190,192],"h2",{"id":191},"what-it-does","What it does",[173,194,195],{},"JWT is a portable, self-contained format for carrying data between systems — most commonly used for authentication tokens. A JWT is either:",[197,198,199,209],"ul",{},[200,201,202,205,206,208],"li",{},[176,203,204],{},"Signed"," (a ",[181,207,30],{"href":31},") — anyone can read the data, and you can prove it hasn't been tampered with.",[200,210,211,205,214,216],{},[176,212,213],{},"Encrypted",[181,215,53],{"href":54},") — only the holder of the right key can read the data.",[173,218,219,220,223,224,227],{},"Both forms are built on top of cryptographic ",[176,221,222],{},"keys",", which unjwt represents as ",[181,225,226],{"href":108},"JWKs"," (JSON Web Keys) — a standard way to serialize a key as a JSON object.",[173,229,230,231,233,234,236,237,239,240,243],{},"That's the whole library: ",[181,232,30],{"href":31}," for signing, ",[181,235,53],{"href":54}," for encryption, ",[181,238,107],{"href":108}," for keys, and a small set of ",[181,241,242],{"href":143},"utilities",".",[189,245,247],{"id":246},"what-it-looks-like","What it looks like",[249,250,255],"pre",{"className":251,"code":252,"language":253,"meta":254,"style":254},"language-ts shiki shiki-themes github-light github-dark github-dark","import { sign, verify } from \"unjwt\u002Fjws\";\nimport { generateJWK } from \"unjwt\u002Fjwk\";\n\nconst key = await generateJWK(\"HS256\");\n\nconst token = await sign({ sub: \"user_1\" }, key, { expiresIn: \"1h\" });\n\u002F\u002F eyJhbGciOiJIUzI1NiIsImtpZCI6IjRjM2QiLCJ0eXAiOiJKV1QifQ...\n\nconst { payload } = await verify(token, key);\n\u002F\u002F { sub: \"user_1\", iat: 1736860800, exp: 1736864400 }\n","ts","",[256,257,258,281,296,303,332,337,367,374,379,404],"code",{"__ignoreMap":254},[259,260,263,267,271,274,278],"span",{"class":261,"line":262},"line",1,[259,264,266],{"class":265},"so5gQ","import",[259,268,270],{"class":269},"slsVL"," { sign, verify } ",[259,272,273],{"class":265},"from",[259,275,277],{"class":276},"sfrk1"," \"unjwt\u002Fjws\"",[259,279,280],{"class":269},";\n",[259,282,284,286,289,291,294],{"class":261,"line":283},2,[259,285,266],{"class":265},[259,287,288],{"class":269}," { generateJWK } ",[259,290,273],{"class":265},[259,292,293],{"class":276}," \"unjwt\u002Fjwk\"",[259,295,280],{"class":269},[259,297,299],{"class":261,"line":298},3,[259,300,302],{"emptyLinePlaceholder":301},true,"\n",[259,304,306,309,313,316,319,323,326,329],{"class":261,"line":305},4,[259,307,308],{"class":265},"const",[259,310,312],{"class":311},"suiK_"," key",[259,314,315],{"class":265}," =",[259,317,318],{"class":265}," await",[259,320,322],{"class":321},"shcOC"," generateJWK",[259,324,325],{"class":269},"(",[259,327,328],{"class":276},"\"HS256\"",[259,330,331],{"class":269},");\n",[259,333,335],{"class":261,"line":334},5,[259,336,302],{"emptyLinePlaceholder":301},[259,338,340,342,345,347,349,352,355,358,361,364],{"class":261,"line":339},6,[259,341,308],{"class":265},[259,343,344],{"class":311}," token",[259,346,315],{"class":265},[259,348,318],{"class":265},[259,350,351],{"class":321}," sign",[259,353,354],{"class":269},"({ sub: ",[259,356,357],{"class":276},"\"user_1\"",[259,359,360],{"class":269}," }, key, { expiresIn: ",[259,362,363],{"class":276},"\"1h\"",[259,365,366],{"class":269}," });\n",[259,368,370],{"class":261,"line":369},7,[259,371,373],{"class":372},"sCsY4","\u002F\u002F eyJhbGciOiJIUzI1NiIsImtpZCI6IjRjM2QiLCJ0eXAiOiJKV1QifQ...\n",[259,375,377],{"class":261,"line":376},8,[259,378,302],{"emptyLinePlaceholder":301},[259,380,382,384,387,390,393,396,398,401],{"class":261,"line":381},9,[259,383,308],{"class":265},[259,385,386],{"class":269}," { ",[259,388,389],{"class":311},"payload",[259,391,392],{"class":269}," } ",[259,394,395],{"class":265},"=",[259,397,318],{"class":265},[259,399,400],{"class":321}," verify",[259,402,403],{"class":269},"(token, key);\n",[259,405,407],{"class":261,"line":406},10,[259,408,409],{"class":372},"\u002F\u002F { sub: \"user_1\", iat: 1736860800, exp: 1736864400 }\n",[173,411,412],{},"That's a complete round trip: generate a key, sign a token, verify it. No config files, no framework setup, no globals.",[189,414,416],{"id":415},"why-it-exists","Why it exists",[173,418,419,420,425,426,425,431,425,436,425,441,446],{},"The JOSE family of specs (",[181,421,424],{"href":422,"rel":423},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc7515",[185],"RFC 7515",", ",[181,427,430],{"href":428,"rel":429},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc7516",[185],"RFC 7516",[181,432,435],{"href":433,"rel":434},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc7517",[185],"RFC 7517",[181,437,440],{"href":438,"rel":439},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc7518",[185],"RFC 7518",[181,442,445],{"href":443,"rel":444},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc7519",[185],"RFC 7519",") is powerful but dense. Most applications only need a handful of functions out of the whole spec surface, but they need those functions to be correct by default.",[173,448,449],{},"unjwt aims for a short, readable API where:",[197,451,452,470,485],{},[200,453,454,457,458,461,462,465,466,469],{},[176,455,456],{},"Keys carry their own metadata."," If your JWK has ",[256,459,460],{},"\"alg\": \"RS256\"",", you don't need to tell ",[256,463,464],{},"sign()"," or ",[256,467,468],{},"verify()"," which algorithm to use — the library reads it from the key.",[200,471,472,475,476,481,482,484],{},[176,473,474],{},"Safe defaults go without saying."," PBES2 iterations default to ",[181,477,480],{"href":478,"rel":479},"https:\u002F\u002Fcheatsheetseries.owasp.org\u002Fcheatsheets\u002FPassword_Storage_Cheat_Sheet.html#pbkdf2",[185],"OWASP-recommended 600 000","; ",[256,483,468],{}," validates JWT claims automatically when the payload is an object; algorithm allowlists are inferred from the key shape.",[200,486,487,490,491,493,494,425,496,425,498,501],{},[176,488,489],{},"The full standard is still reachable."," General JSON Serialization for both ",[181,492,30],{"href":46}," and ",[181,495,53],{"href":69},[181,497,122],{"href":123},[181,499,500],{"href":73},"ECDH-ES",", JWK Sets with automatic key rotation — all first-class.",[189,503,505],{"id":504},"where-to-go-next","Where to go next",[197,507,508,514,521],{},[200,509,510,513],{},[181,511,512],{"href":12},"Install unjwt"," and get your first token working.",[200,515,516,517,520],{},"Read the ",[181,518,519],{"href":16},"quickstart"," — a two-minute signed token, end to end.",[200,522,523,524,527],{},"If the acronyms are new, skim ",[181,525,526],{"href":20},"core concepts"," first.",[529,530,531],"note",{},[173,532,533,534,539,540,548,549,554],{},"unjwt was originally visioned by ",[181,535,538],{"href":536,"rel":537},"https:\u002F\u002Fgithub.com\u002Fjohannschopplich",[185],"Johann Schopplich",", heavily inspired by ",[181,541,544,545],{"href":542,"rel":543},"https:\u002F\u002Fgithub.com\u002Fpanva\u002Fjose",[185],"Filip Skokan's ",[256,546,547],{},"jose"," internal cryptographic primitives, and initially sponsored by ",[181,550,553],{"href":551,"rel":552},"https:\u002F\u002Fjamflow.cloud",[185],"JAMflow"," — thanks to all three for making this project possible.",[556,557,558],"style",{},"html pre.shiki code .so5gQ, html code.shiki .so5gQ{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F97583}html pre.shiki code .slsVL, html code.shiki .slsVL{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .sfrk1, html code.shiki .sfrk1{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html pre.shiki code .suiK_, html code.shiki .suiK_{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html pre.shiki code .shcOC, html code.shiki .shcOC{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#B392F0}html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}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":254,"searchDepth":283,"depth":283,"links":560},[561,562,563,564],{"id":191,"depth":283,"text":192},{"id":246,"depth":283,"text":247},{"id":415,"depth":283,"text":416},{"id":504,"depth":283,"text":505},"md",{},{},{"title":5,"description":254},"CmjiFHY6fiVodu4DQxYCAPDdT_tlcO7gVWIbgPNKm7Y",[571,572],null,{"title":11,"path":12,"stem":13,"description":254,"children":-1},1776888557909]