11# KJWT
22
3+ [ ![ Tests] ( https://github.com/touchlab/kjwt/actions/workflows/tests.yml/badge.svg?event=push )] ( https://github.com/touchlab/kjwt/actions/workflows/tests.yml )
4+ [ ![ Detekt Checks] ( https://github.com/touchlab/kjwt/actions/workflows/detekt.yml/badge.svg )] ( https://github.com/touchlab/kjwt/actions/workflows/detekt.yml )
5+
6+
37[ ![ Maven Central] ( https://img.shields.io/maven-central/v/co.touchlab/kjwt?label=Maven%20Central )] ( https://search.maven.org/artifact/co.touchlab/kjwt )
48![ 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&label=Snapshot )
59
6- Kotlin Multiplatform library implementing JWT ([ RFC 7519] ( https://datatracker.ietf.org/doc/html/rfc7519 ) ).
10+ A JSON Web Token (JWT) is a compact, URL-safe standard for representing data to be transferred between two parties. The
11+ data within a JWT - referred to as claims - is encoded as a JSON object that serves as the payload for either a JSON Web
12+ Signature (JWS) or a JSON Web Encryption (JWE) structure. This design allows claims to be digitally signed for
13+ integrity (using a Message Authentication Code or MAC) and/or encrypted for privacy.
14+
15+ The most common JWT format is a string composed of three dot-separated segments: header, payload, and signature. This
16+ structure represents a JWS, as defined by RFC 7515. In this format, the header and payload are Base64URL-encoded,
17+ meaning they can be easily decoded by anyone to reveal their contents. The third segment, the signature, is also
18+ Base64URL-encoded and is used to verify that the first two parts of the token have not been tampered with.
19+
20+ While less common, JWTs can also follow the JWE format defined by RFC 7516, which consists of five dot-separated parts:
21+ header, encrypted key, initialization vector, ciphertext, and authentication tag. Unlike a JWS, where data is merely
22+ signed, a JWE encrypts the data. While the header remains decodable, the remaining segments are encrypted and cannot be
23+ read without the appropriate cryptographic key.
24+
25+ ### How about the other formats and RFCs?
26+
27+ The JWT is just a part of the JOSE family of standards. JOSE stands for JSON Object Signing and Encryption, and it
28+ groups several related RFCs that define how to sign, encrypt, and manage keys for JSON data. To support all of these
29+ features, the JOSE family includes a few different standards, such as:
30+
31+ - [ RFC 7519 (JWT)] ( https://datatracker.ietf.org/doc/html/rfc7519 ) - JSON Web Token
32+ - [ RFC 7515 (JWS)] ( https://datatracker.ietf.org/doc/html/rfc7515 ) - JSON Web Signature
33+ - [ RFC 7516 (JWE)] ( https://datatracker.ietf.org/doc/html/rfc7516 ) - JSON Web Encryption
34+ - [ RFC 7517 (JWK)] ( https://datatracker.ietf.org/doc/html/rfc7517 ) - JSON Web Key
35+ - [ RFC 7518 (JWA)] ( https://datatracker.ietf.org/doc/html/rfc7518 ) - JSON Web Algorithms
36+ - [ RFC 7520 (JOSE)] ( https://datatracker.ietf.org/doc/html/rfc7520 ) - JSON Object Signing and Encryption (JOSE)
37+ - [ RFC 7638 (JWK Thumbprint)] ( https://datatracker.ietf.org/doc/html/rfc7638 ) - JWK Thumbprint
38+
39+ While the JWT is a specific format for representing claims (payload), the JOSE standards provide the tools and
40+ specifications for creating, signing, encrypting, and managing those claims in a secure and interoperable way. The JWT
41+ is just one of the possible formats for representing claims, and it is designed to be compact and URL-safe.
42+
43+ When we first conceived KJWT, our goal was to support the JWS format of JWTs. However, as we developed the library, we
44+ realized that supporting the full range of JOSE standards would provide a more robust solution for users.
45+ Therefore, we decided to implement support for JWS, JWE, JWK, and JWA in addition to JWT. This allows KJWT to be a
46+ comprehensive library for working with JSON Web Tokens and related standards.
47+
48+ That said, our plan is not to implement all the RFCs. We will focus our efforts on implementing the ones that are
49+ necessary and relevant for JWT use cases. Some RFCs that are not relevant, or that explicitly state they should not be
50+ used with JWTs, may not be implemented. One example is the
51+ [ RFC-7797 - JSON Web Signature (JWS) Unencoded Payload Option] ( https://www.rfc-editor.org/rfc/rfc7797.html ) which
52+ states in section 7 that it should not be used with JWTs.
753
854## Features
955
56+ As of now, the library supports the following operations:
57+
1058| Operations | Signing Algorithms | Encryption Algorithms | Platforms |
1159| -----------------| --------------------| ---------------------------| ---------------------------------------------|
1260| ✅ Sign | ✅ HS256 | ✅ RSA-OAEP ` (alg) ` | ✅ JVM (incl. Android) |
@@ -87,21 +135,21 @@ dependencies {
87135## Why another library?
88136
89137[ Signum] ( https://a-sit-plus.github.io/signum/ ) is a community KMP library that aims to support many cryptographic
90- operations, such as JWT Operations . Their library is more feature-rich and supports many algorithms. However, it has a
91- requirement of SDK 30+ for Android projects. This limitation is needed as they support hardware backed operations that
92- have such requirement.
138+ operations, such as JWT operations . Their library is more feature-rich and supports many algorithms. However, it has a
139+ requirement of SDK 30+ for Android projects. This limitation is needed as they support hardware- backed operations that
140+ have such a requirement.
93141
94142On the other hand, [ Cryptography Kotlin] ( https://whyoleg.github.io/cryptography-kotlin/ ) is another community library
95- with a much narrow scope. It supports a wide range of platforms and algorithms, but its goal is to provide access to
143+ with a much narrower scope. It supports a wide range of platforms and algorithms, but its goal is to provide access to
96144the cryptographic APIs, and not to implement any specific protocol on top of it.
97145
98- Our proposal is to support JWT on top of the cryptographic library. We aim to provide an easy-to-migrate API for
99- Kotlin/Java only applications that are using JJWT for this purpose, supporting the main KMP platforms available.
100- As of now, the library is compliant with Jws and Jwe specifications.
146+ Our goal is to support JWT on top of the cryptographic library. We aim to provide an easy-to-migrate API for
147+ Kotlin/Java- only applications that are using JJWT for this purpose, supporting the main KMP platforms available.
148+ As of now, the library is compliant with the JWS and JWE specifications.
101149
102150## Usage
103151
104- All actions were designed to be chainable, and start from the ` Jwt ` (` import co.touchlab.kjwt.Jwt ` ) object. It the
152+ All actions were designed to be chainable, and start from the ` Jwt ` (` import co.touchlab.kjwt.Jwt ` ) object. It is the
105153entrypoint for most JWT operations. In that object, you will find methods to ` build ` and ` parse ` JWTs.
106154
107155### Building a JWT
@@ -124,7 +172,7 @@ val serialized: String = token.compact()
124172// This call will generate the string version of the JWT, in the compact format
125173// Note: the compact format is the one split by the dots, with the header, payload and signature encoded in Base64URL
126174// format. It will look like this:
127- // <header>.<payload>.<signature> 👈This is the compact format template 👇And this a real example
175+ // <header>.<payload>.<signature> 👈This is the compact format template 👇And this is a real example
128176// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.yaquqtp1qJ9uDVaWMdRtujneuFqIBkImorBu9hdLVl4
129177```
130178
@@ -143,17 +191,18 @@ val jwtParser = Jwt.parser()
143191val parsedToken = jwtParser.parse(compactToken)
144192```
145193
146- Note that if the content was changed on the client side, the signature will be invalid and the parsing will throw an
194+ Note that if the content has been changed on the client side, the signature will be invalid and the parsing will throw
195+ an
147196exception. If the parse succeeds, the token is valid and ready to be used.
148197
149198``` kotlin
150199// Use content from the JWT:
151- val subject = jws .payload.subjectOrNull
200+ val subject = parsedToken .payload.subjectOrNull
152201```
153202
154203### Keys
155204
156- As you probably noticed, we skipped the keys part in the previous examples. The main reason for that, is that we do not
205+ As you probably noticed, we skipped the keys part in the previous examples. The main reason for that is that we do not
157206implement any cryptographic operations. Instead, we rely on
158207the [ Cryptography Kotlin] ( https://github.com/whyoleg/cryptography-kotlin ) library. It's an amazing and robust library
159208that provides a wide range of cryptographic operations, and providers for most of the Kotlin Multiplatform targets.
@@ -162,12 +211,12 @@ To generate the `hmacKey` we used in the previous examples, you can use the foll
162211
163212``` kotlin
164213val myKeyString = " a-string-secret-at-least-256-bits-long"
165- .encodeToByteArray() // Convert the string into byte array to perform the crypto operations
214+ .encodeToByteArray() // Convert the string into a byte array to perform the crypto operations
166215
167216val hmacKey =
168- CryptographyProvider .Default // Get the provider you use for your project. CryptographyProvider.Default most common
217+ CryptographyProvider .Default // Get the provider you use for your project. CryptographyProvider.Default is most common
169218 .get(HMAC ) // Get the HMAC algorithm
170- .keyDecoder(SHA256 ) // Use the correct digest for your operation. For HS256. For HS384 use SHA384, etc. .
219+ .keyDecoder(SHA256 ) // Use the correct digest for your operation. For HS256, use SHA256 . For HS384 use SHA384, etc.
171220 .decodeFromByteArray(HMAC .Key .Format .RAW , myKeyString) // Decode your key bytes into a HMAC key
172221
173222// Then you can use the HMAC key to sign or verify tokens
0 commit comments