{"id":48458004,"url":"https://github.com/touchlab/kjwt","last_synced_at":"2026-04-07T00:03:55.351Z","repository":{"id":343791430,"uuid":"1176864263","full_name":"touchlab/kjwt","owner":"touchlab","description":null,"archived":false,"fork":false,"pushed_at":"2026-04-03T22:57:47.000Z","size":2304,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-04T00:30:42.547Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://touchlab.github.io/kjwt/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/touchlab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-09T13:07:14.000Z","updated_at":"2026-04-03T22:47:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/touchlab/kjwt","commit_stats":null,"previous_names":["faogustavo/kjwt","touchlab/kjwt"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/touchlab/kjwt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/touchlab%2Fkjwt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/touchlab%2Fkjwt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/touchlab%2Fkjwt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/touchlab%2Fkjwt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/touchlab","download_url":"https://codeload.github.com/touchlab/kjwt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/touchlab%2Fkjwt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31494183,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-06T17:22:55.647Z","status":"ssl_error","status_checked_at":"2026-04-06T17:22:54.741Z","response_time":112,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-07T00:03:55.255Z","updated_at":"2026-04-07T00:03:55.338Z","avatar_url":"https://github.com/touchlab.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# KJWT\n\n![Static Badge](https://img.shields.io/badge/Experimental-purple?logo=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAIGNIUk0AAHomAACAhAAA%2BgAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAGYktHRAD%2FAP8A%2F6C9p5MAAAAHdElNRQfqAxQQNwqPJMIGAAAIYElEQVRo3u1XaZBU1RX%2Bzr1v6X4zPSszDMuwKQRkkUVCxQVNuUQjBNFohEKLKGqMJJLESswPrZS%2FUkZQCitUBbegKShMXDLGQAaklFRZgsMmKIzA0MMI0zDMNNPzenn97j358WZ6ppkeTfwVq%2Fqrvq%2Fe67r3nO8s373vAUUUUUQRRRRRRBFFfGNBXzVhwv2LkagYibrWfXASHYgPG4dsqBRgBgCEbODG%2BQYMA1j9w9f%2FvwK4%2Fokl6Fr2W%2BCzw0iVV8EXDogVwAMmMQPMkJxFOHEWXDUM%2BqV1OPDndwfZ%2B%2Fj9m6AZqK1QMCUAiCF9d7sCk%2Bc5WPt0FKt%2Bs%2FfrBTBzRwM0A6I9NiHllM7Q2iAWxHnLmAkgllAIJ7uadKT0lPDS2H%2FXfYPsbf%2F7dWBGVXW5vtoQMADBhfwyg5JpeXjcGOtouLQUFfVDV3bIAC598nco%2F9ZImOlEpGPSnFfTobIFTKyZ%2Bn0SAwF9wIYrS5Odr5buanowXVvtnd3bjLb16%2FNsvr%2F1BmSVqJ0%2BIf23SChzJQA1hHvpeqHGI63ldzt2Nv7piR7cs3zX%2F16B8ceOwGppWe5W1fzJl4bJxOC%2BshMHAYAgkYWDblh%2Bqsc6G1%2BK2sqGurISbJt47UWZfQzoaMLJNiyprUq%2BbIqsPZRvpQwVu%2BD8bOx0rK%2BfcRJth04WjrTQn9PXrsaIFSvgRKOj3NoRazMhexRAwa%2B3gYiDi2CGjSRMygCCLEFyRMnBlgY3diFVNmsuOnbuzNkNV0qkkxY%2BP2WdGFXL00KmmtKfx%2FxBxEJKMe7wpxXvLr%2B9Jn7zLeOxacvxQVwHqWj6XVfDbD%2BNA3fcCXf48BWZcGgWALDoIx3cMwEMAYksDMqAASiS8MPWNdkxtUvEwrlwN3%2BACfcvztl%2BfNUuXDbWwjWzRfLchZJnM77ZAXBvbhggnRtMhLCZnTqiquehafNuROcFYMFdU766hea88RqSpeWQydTM7pH1DelQePTAngcC8gAgWMNmFxalQNAACEoI2Mn0kXBr7Fa2rBN0phNNP1mVs7985SxcO6cGK9eMEc2bm1cPK02tEqShiZG%2FvREIhHTWbm875ywK27y7M25gznXbhq7AxMcehDoXw%2FD33jZTlXWPelY%2F%2BT7ifeSJGSZnYJCXI88AhGZoy5ysh1U%2BPG7RvcQJF%2FW%2FXpmz8crz%2BzC6RqLp5VM6Fg%2BtT%2Ftmc6GtSDCBQbANr66mwl%2B18%2BOIfS4OrP3jTUNXYDkzPtqzB9TRfmuipm6TZ1kRHkLmkhVCSMBEBgCDIcHEkDoov5XJng2d6bpNhM0PubUTe1b8NLd26t3XYpqZxOaNIUQPGj%2BvrehZI4UvaUANqLdnmYGsMt1YvGxZXYX3ljOuFUQt%2FTzySI2qQeTk0Uj32Elr0qHIFLAAQYBYgJhALAMRs4CJNCxK5nIQ9DAFFSJAS1FCJByzcX9DxhYqtrUx5%2BfcoSh%2B8cgEuOctnD5vHB9WruYbUtVrJvQPzt2T0BbDGPXvg6VvRY9VpF%2Fb1C9mY5CmWTBrW0M7YBZ5JerVMJgYWnhgot72kQAUiDU0CfS1MzErkdWFpAZPabgZBS%2FLoiOREUkvna8BJjBpMBjEEilPqqxnMbE3tAbqrrwKHbO%2B22Ml4s%2BZnt8d0JcDhgBYgNiAryvg6UguNIYIAmICgWF62XazM7Eue8NMzygJ5TmdcN8ifHLCws0LmzFimHuPNJJzfaWhFPcPraGUhlJAxpduPGGuvXxyT3zBreH8Vh74oCMOStw4Kj96J5q5dNZ4z3Zma8rfaQlBZvqCkjIJgb4sM5gAQ2vYidS6Jbcs3Xhg2hU4ffAY3L0f52ysf3w0rpqhcPxo9eTK8tSzppGtBunBQqPgmEx7odd3H6xb3e2yemNrHDt3fFFYxAAw7cVX4NeNgsy4l3fXTWzwrEg9OGgb6t1p%2BpqJoGEb7bAp0dczAAA75R1yTp1bwJYVVbFu7H2gX8DLH70Ss6eE8eYHI%2BQzjxx9riycXEnC7z0OqL9NewPI%2BqH2812RRbaN3d09IVz%2F%2Fe1DtxAArLujEcaHW3F48aIDttu5wVDZvkM4rw5BGAKeqoTPVqAFBoRiX%2FaknnfnXRb1frAsjzwAPL5EYv50F0%2F9uGW%2BY6eXkvR7K3qRB2KwlkimnJeuvvH3e5o%2BtfH0hujgIqEALlu7BkbdWEjPHRkfP%2FWdVKh6VqBLGrREMEMa5xEWHZDMMN1Uo3209U7thC6YX7Rj96%2BezM39w9PzMHZMCbrdUMm3p8Y2Oba7EAMOMOL%2BfDKAdNb55MTpioUhW0c7uwTuXvrefxdAHyYdisJoPXJvd%2FW4DZ60raDElLeYARB5CMt2hP3uhN3e9SNdXflPGXawb%2BZ1F1m00BmdjuYW457Ksp4NUng2QSBo0f4qEAClLT%2BeqHh44iXqhcrRpwC0FeRY8GUOACY%2B8SRKvS44nW3Hs%2BW1M5S0LiVmXzArwToYWilipYQiJbTPTk%2FXX8p37Fqnkp7Ovr0FZ%2FcdzbPZ2DAfbWecusoKd7UhVD1rw9daKs1ScTB8Zqk0G0h7zvbo6fBTZ2IiM%2FcKG9v%2Bdbogzy%2F%2FoNm2HWlhwoidGp90qqf6ZLLQha0YnOZSN7YP5ZEzMnEBTcseGDTt7S3XAIyqcCj5HSKWgJnrGCIEn3YUiDnjmc21w%2FlzK%2BRgxpzGITka%2BBL4b70AfvQZUE%2B8RUTKWwRZEEO8WwikQJQAVdfC27Kh4JyyMhMAOiOO%2BIcghuJ%2B9wQGiSCjmgmptMTESxgvvdzxZRS%2F%2BqO%2BEPbz0rzn21ek8p5PvPhmwXUDX60Hzt3PSzGT4pj9yxBMA7jtewY%2BO6ax8aG%2Ffh16RRRRRBFFFFFEEUV8U%2FAfGXvGZ1J%2FCK4AAAAldEVYdGRhdGU6Y3JlYXRlADIwMjYtMDMtMjBUMTY6NTQ6NTkrMDA6MDCRKVM4AAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI2LTAzLTIwVDE2OjU0OjU5KzAwOjAw4HTrhAAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyNi0wMy0yMFQxNjo1NToxMCswMDowMElx6kwAAAAASUVORK5CYII%3D\u0026label=Maturity)\n[![Maven Central](https://img.shields.io/maven-central/v/co.touchlab/kjwt?label=Maven%20Central)](https://search.maven.org/artifact/co.touchlab/kjwt)\n![Maven Central (Snapshots)](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fcentral.sonatype.com%2Frepository%2Fmaven-snapshots%2Fco%2Ftouchlab%2Fkjwt%2Fmaven-metadata.xml\u0026label=Snapshot)\n![Dynamic TOML Badge](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fraw.githubusercontent.com%2Ftouchlab%2Fkjwt%2Frefs%2Fheads%2Fmain%2Fgradle%2Flibs.versions.toml\u0026query=%24.versions.kotlin\u0026logo=kotlin\u0026logoColor=%23dedede\u0026label=Kotlin%20Version\u0026color=%237f52ff)\n![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/touchlab/kjwt/tests.yml?logo=github\u0026label=Tests)\n![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/touchlab/kjwt/detekt.yml?logo=github\u0026label=Detekt)\n\nA JSON Web Token (JWT) is a compact, URL-safe standard for representing data to be transferred between two parties. The\ndata within a JWT - referred to as claims - is encoded as a JSON object that serves as the payload for either a JSON Web\nSignature (JWS) or a JSON Web Encryption (JWE) structure. This design allows claims to be digitally signed for\nintegrity (using a Message Authentication Code or MAC) and/or encrypted for privacy.\n\nThe most common JWT format is a string composed of three dot-separated segments: header, payload, and signature. This\nstructure represents a JWS, as defined by RFC 7515. In this format, the header and payload are Base64URL-encoded,\nmeaning they can be easily decoded by anyone to reveal their contents. The third segment, the signature, is also\nBase64URL-encoded and is used to verify that the first two parts of the token have not been tampered with.\n\nWhile less common, JWTs can also follow the JWE format defined by RFC 7516, which consists of five dot-separated parts:\nheader, encrypted key, initialization vector, ciphertext, and authentication tag. Unlike a JWS, where data is merely\nsigned, a JWE encrypts the data. While the header remains decodable, the remaining segments are encrypted and cannot be\nread without the appropriate cryptographic key.\n\n### How about the other formats and RFCs?\n\nThe JWT is just a part of the JOSE family of standards. JOSE stands for JSON Object Signing and Encryption, and it\ngroups several related RFCs that define how to sign, encrypt, and manage keys for JSON data. To support all of these\nfeatures, the JOSE family includes a few different standards, such as:\n\n- [RFC 7519 (JWT)](https://datatracker.ietf.org/doc/html/rfc7519) - JSON Web Token\n- [RFC 7515 (JWS)](https://datatracker.ietf.org/doc/html/rfc7515) - JSON Web Signature\n- [RFC 7516 (JWE)](https://datatracker.ietf.org/doc/html/rfc7516) - JSON Web Encryption\n- [RFC 7517 (JWK)](https://datatracker.ietf.org/doc/html/rfc7517) - JSON Web Key\n- [RFC 7518 (JWA)](https://datatracker.ietf.org/doc/html/rfc7518) - JSON Web Algorithms\n- [RFC 7520 (JOSE)](https://datatracker.ietf.org/doc/html/rfc7520) - JSON Object Signing and Encryption (JOSE)\n- [RFC 7638 (JWK Thumbprint)](https://datatracker.ietf.org/doc/html/rfc7638) - JWK Thumbprint\n\nWhile the JWT is a specific format for representing claims (payload), the JOSE standards provide the tools and\nspecifications for creating, signing, encrypting, and managing those claims in a secure and interoperable way. The JWT\nis just one of the possible formats for representing claims, and it is designed to be compact and URL-safe.\n\nWhen we first conceived KJWT, our goal was to support the JWS format of JWTs. However, as we developed the library, we\nrealized that supporting the full range of JOSE standards would provide a more robust solution for users.\nTherefore, we decided to implement support for JWS, JWE, JWK, and JWA in addition to JWT. This allows KJWT to be a\ncomprehensive library for working with JSON Web Tokens and related standards.\n\nThat said, our plan is not to implement all the RFCs. We will focus our efforts on implementing the ones that are\nnecessary and relevant for JWT use cases. Some RFCs that are not relevant, or that explicitly state they should not be\nused with JWTs, may not be implemented. One example is the\n[RFC-7797 - JSON Web Signature (JWS) Unencoded Payload Option](https://www.rfc-editor.org/rfc/rfc7797.html) which\nstates in section 7 that it should not be used with JWTs.\n\n## Features\n\nAs of now, the library supports the following operations:\n\n| Operations      | Signing Algorithms | Encryption Algorithms     | Platforms                                   |\n|-----------------|--------------------|---------------------------|---------------------------------------------|\n| ✅ Sign          | ✅ HS256            | ✅ RSA-OAEP `(alg)`        | ✅ JVM (incl. Android)                       |\n| ✅ Verify        | ✅ HS384            | ✅ RSA-OAEP-256 `(alg)`    | ✅ JS (node + browser)⁴                      |\n| ✅ `iss` check¹  | ✅ HS512            | ✅ dir `(alg)`             | ✅ wasmJs (node + browser)⁴                  |\n| ✅ `sub` check¹  | ✅ RS256            | ❌ A128KW `(alg)`          | ❌ wasmWasi⁵                                 |\n| ✅ `aud` check¹  | ✅ RS384            | ❌ A192KW `(alg)`          | ✅ iOS (arm64, x64, simulatorArm64)⁶         |\n| ✅ `exp` check   | ✅ RS512            | ❌ A256KW `(alg)`          | ✅ macOS (x64, arm64)⁶                       |\n| ✅ `nbf` check   | ✅ ES256            | ❌ ECDH-ES `(alg)`         | ✅ watchOS (x64, arm32, arm64, sim, device)⁶ |\n| ⚠️ `iat` check² | ❌ ES256K           | ✅ A128GCM `(enc)`         | ✅ tvOS (x64, arm64, sim)⁶                   |\n| ⚠️ `jti` check² | ✅ ES384            | ⚠️ A192GCM `(enc)`⁴       | ✅ Linux (x64, arm64)                        |\n| ❌ `typ` check   | ✅ ES512            | ✅ A256GCM `(enc)`         | ✅ Windows/MinGW (x64)                       |\n|                 | ✅ PS256³           | ✅ A128CBC-HS256 `(enc)`   | ✅ Android Native (x64, x86, arm64, arm32)   |\n|                 | ✅ PS384³           | ⚠️ A192CBC-HS384 `(enc)`⁴ |                                             |\n|                 | ✅ PS512³           | ✅ A256CBC-HS512 `(enc)`   |                                             |\n|                 | ❌ EdDSA            |                           |                                             |\n\n\u003e ¹ Opt-in: call `requireIssuer()` / `requireSubject()` / `requireAudience()` on the parser builder. A missing claim\n\u003e throws `MissingClaimException`; a mismatched value throws `IncorrectClaimException`.\n\u003e\n\u003e ² Accessible via `payload.issuedAtOrNull` / `payload.jwtIdOrNull` but not automatically validated. Use the generic\n`requireClaim()` for custom validation.\n\u003e\n\u003e ³ PS256 / PS384 / PS512 are not supported by Android's default JDK security provider. Register BouncyCastle as the\n\u003e security provider to enable them. Android Native targets use OpenSSL3 and are unaffected.\n\u003e\n\u003e ⁴ JS and wasmJs use WebCrypto, which does not support 192-bit AES keys. `A192GCM` and `A192CBC-HS384` are unavailable\n\u003e on these platforms.\n\u003e\n\u003e ⁵ wasmWasi has no `cryptography-kotlin` provider. The library compiles for this target but all cryptographic\n\u003e operations throw at runtime.\n\u003e\n\u003e ⁶ Apple targets (iOS, macOS, watchOS, tvOS): use `cryptography-provider-optimal` for full algorithm support (CryptoKit\n\u003e for AES-GCM; Apple/CommonCrypto for AES-CBC+HMAC and RSA). `cryptography-provider-openssl3-prebuilt` also supports all\n\u003e algorithms and is a good choice when a single consistent provider is needed across Apple, Linux, and Android Native.\n\u003e With only `cryptography-provider-cryptokit`, RSA and AES-CBC algorithms are unavailable. With only\n\u003e `cryptography-provider-apple`, AES-GCM algorithms are unavailable.\n\n---\n\n## Setup\n\nAdd the library to your project and register a cryptography provider. The `cryptography-provider-optimal` artifact\nauto-registers on startup and is the recommended choice:\n\n```kotlin\n// build.gradle.kts\ndependencies {\n    implementation(\"co.touchlab:kjwt-core:\u003ckjwt-version\u003e\")\n\n    // For usage with `Cryptography-Kotlin`, include the processor and the providers for it:\n    implementation(\"co.touchlab:kjwt-cryptography-kotlin-processor:\u003ckjwt-version\u003e\")\n    implementation(\"dev.whyoleg.cryptography:cryptography-provider-optimal:\u003ccryptography-kotlin-version\u003e\")\n    \n    // Optional: Some extensions exist for the cryptography-kotlin library\n    implementation(\"co.touchlab:kjwt-cryptography-kotlin-processor-ext:\u003ckjwt-version\u003e\")\n    \n    // Mover providers will be added soon\n}\n```\n\n### Snapshot builds\n\nEvery merge to `main` is automatically published to the Maven snapshot repository. To use a snapshot version, add the\nrepository and use the `-SNAPSHOT` suffix:\n\n```kotlin\n// settings.gradle.kts\ndependencyResolutionManagement {\n    repositories {\n        maven(\"https://central.sonatype.com/repository/maven-snapshots\") {\n            mavenContent {\n                includeModuleByRegex(\"co\\\\.touchlab\", \"kjwt.*\")\n            }\n        }\n    }\n}\n```\n\n```kotlin\n// build.gradle.kts\ndependencies {\n    implementation(\"co.touchlab:kjwt:\u003ckjwt-version\u003e-SNAPSHOT\") {\n        isChanging = true\n    }\n}\n```\n\n## Why another library?\n\nThere are two common reference points in the KMP ecosystem:\n\n[Signum](https://a-sit-plus.github.io/signum/) is a community KMP library that supports many cryptographic operations,\nincluding JWT. It is more feature-rich and supports many algorithms, but it requires Android SDK 30+ — a hard limit\nfor apps that need to support older devices.\n\n[Cryptography Kotlin](https://whyoleg.github.io/cryptography-kotlin/) takes a different approach: it is a low-level\nlibrary whose goal is to expose cryptographic primitives across KMP targets, not to implement protocols on top of them.\nIt is an excellent building block, but it does not give you a JWT API.\n\nKJWT fills that gap. It provides a high-level, easy-to-use JWT API (JWS and JWE) that works across all major KMP\nplatforms, with a migration-friendly design for teams moving from JJWT on the JVM.\n\nWe started by building KJWT directly on top of Cryptography Kotlin, and it remains the recommended crypto backend.\nOver time, however, we decoupled the JWT logic from any specific crypto implementation. The cryptographic layer is now\npluggable: if your project already uses a different library for cryptography, you can write a thin processor for it and\nplug it into KJWT without changing anything else. This makes KJWT useful even in projects where the crypto stack is\nalready decided.\n\nOne concrete motivation for this design was hardware-backed cryptography. Signum supports hardware-backed operations,\nwhich is a compelling feature — but it comes at the cost of requiring Android SDK 30+. With KJWT's pluggable\narchitecture, you can implement a processor backed by hardware security when your app's minimum SDK allows it, while\nusers on older Android versions continue to use a standard software-backed provider. The JWT layer stays the same\nregardless of which processor is underneath.\n\nGoing forward, we plan to ship first-party processors for hardware-backed cryptography and other provider types, so\nyou get the benefits of those integrations without having to implement them yourself.\n\n\u003cdetails\u003e\n\u003csummary\u003eAren't there enough standards already?\u003c/summary\u003e\n\n[Yes.](https://xkcd.com/927/)\n\n\u003c/details\u003e\n\n## Usage\n\nAll actions were designed to be chainable, and start from the `Jwt` (`import co.touchlab.kjwt.Jwt`) object. It is the\nentrypoint for most JWT operations. In that object, you will find methods to `build` and `parse` JWTs.\n\n### Building a JWT\n\nThe most common usage of JWTs is to generate signed tokens. You can achieve this by using the `.signWith(...)` method\nwhen building a JWT.\n\n```kotlin\nval signingKey = SigningAlgorithm.HS256.newKey()\n\nval token: JwtInstance = Jwt.builder()\n    .subject(\"1234567890\")\n    .signWith(signingKey)\n```\n\nThe result of the operation is a `JwtInstance` object. That object is a Kotlin representation of the JWT. You can use\nit to access the defined claims and headers, as well as generate the famous compact version of the JWT.\n\n```kotlin\nval token: JwtInstance = // build the token as shown above\nval serialized: String = token.compact()\n// This call will generate the string version of the JWT, in the compact format\n// Note: the compact format is the one split by the dots, with the header, payload and signature encoded in Base64URL\n// format. It will look like this:\n// \u003cheader\u003e.\u003cpayload\u003e.\u003csignature\u003e 👈This is the compact format template 👇And this is a real example\n// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.yaquqtp1qJ9uDVaWMdRtujneuFqIBkImorBu9hdLVl4\n```\n\n### Parsing a JWT\n\nAnother common usage of JWTs is to verify the authenticity of a token. If you are a backend application, you need to\nensure that the user hasn't modified the token on their side. That is achieved by verifying the signature of the token.\n\n```kotlin\nval compactToken: String = //\n\nval jwtParser = Jwt.parser()\n    .verifyWith(signingKey)\n    .build()\n\nval parsedToken = jwtParser.parse(compactToken)\n```\n\nNote that if the content has been changed on the client side, the signature will be invalid and the parsing will throw\nan\nexception. If the parse succeeds, the token is valid and ready to be used.\n\n```kotlin\n// Use content from the JWT:\nval subject = parsedToken.payload.subjectOrNull\n```\n\n### Keys\n\nAs you probably noticed, we skipped the keys part in the previous examples. The main reason for that is that we do not\nimplement any cryptographic operations. Instead, we rely on\nthe [Cryptography Kotlin](https://github.com/whyoleg/cryptography-kotlin) library. It's an amazing and robust library\nthat provides a wide range of cryptographic operations, and providers for most of the Kotlin Multiplatform targets.\n\nKJWT ships extension functions on each algorithm object that generate or decode keys without\nrequiring you to touch the `cryptography-kotlin` API directly:\n\n```kotlin\nimport co.touchlab.kjwt.model.algorithm.SigningAlgorithm\n\n// Generate a new random HMAC key\nval key = SigningAlgorithm.HS256.newKey()\n\n// Decode an HMAC key from existing bytes\nval key = SigningAlgorithm.HS256.parse(myKeyBytes)\n\n// Generate an RSA key pair (also available for RS384/RS512, PS*, ES*)\nval key = SigningAlgorithm.RS256.newKey()\n\n// Decode individual RSA/ECDSA keys\nval key = SigningAlgorithm.RS256.parsePublicKey(pemBytes)    // verify only\nval key = SigningAlgorithm.RS256.parsePrivateKey(pemBytes)   // sign only\nval key = SigningAlgorithm.RS256.parseKeyPair(pubPem, privPem)\n```\n\nThe returned `SigningKey` can be passed directly to `signWith` or `verifyWith`:\n\n```kotlin\nval key = SigningAlgorithm.HS256.parse(myKeyBytes)\n\nval token: JwtInstance = Jwt.builder()\n    .subject(\"1234567890\")\n    .signWith(key)          // Use the key to sign the token\n\nval jwtParser = Jwt.parser()\n    .verifyWith(key)        // Use the key to verify the token\n    .build()\n\nval compactToken: String =  // ...\nval parsedToken = jwtParser.parse(compactToken) // Token will get verified using the key used in the builder\n```\n\nIf you prefer to work with `cryptography-kotlin` directly, you can also construct keys manually\nusing its API and pass them to `signWith` / `verifyWith`. For a full reference of all key helper\noverloads, see the [usage guide](docs/usage.md#keys).\n\n### More features\n\nFor a more detailed list of features, check out the usage documentation available at the [docs](docs/USAGE.md).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftouchlab%2Fkjwt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftouchlab%2Fkjwt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftouchlab%2Fkjwt/lists"}