Skip to content

Commit

Permalink
Delete javaDoc, and update README in prep for 3.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
robotdan committed Jan 11, 2019
1 parent e41713d commit e6148ed
Show file tree
Hide file tree
Showing 111 changed files with 195 additions and 27,467 deletions.
21 changes: 20 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
Prime JWT Changes
FusionAuth JWT Changes

Changes in 3.0.0

This major version of fusionauth-jwt contains breaking changes.

* Elliptic Support, ES256, ES384 and ES512
* JWK Support
* Some minor breakages
* Upgraded Jackson from 2.9.6 to 2.9.8. This upgrade addresses CVE-2018-19360, CVE-2018-19361, CVE-2018-19362 and CVE-2018-1000873.

If you are unable to upgrade to 3.0.0, simply explicitly depend upon version 2.9.8 in your own application, this will be compatible with
this library.

See https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.9.8
See https://nvd.nist.gov/vuln/detail/CVE-2018-19360
See https://nvd.nist.gov/vuln/detail/CVE-2018-19361
See https://nvd.nist.gov/vuln/detail/CVE-2018-19362
See https://nvd.nist.gov/vuln/detail/CVE-2018-1000873

Changes in 2.1.1
* Ignore null values when calling JWT.addClaim

Changes in 2.1.0
* Rename packages from org.primeframework to io.fusionauth
* Rename project from prime-jwt to fusionauth-jwt

Changes in 2.0.0

Expand Down
170 changes: 159 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,70 +1,218 @@
## FusionAuth JWT ![semver 2.0.0 compliant](http://img.shields.io/badge/semver-2.0.0-brightgreen.svg?style=flat-square)

FusionAuth JWT is intended to be fast and easy to use. FusionAuth JWT has a single external dependency on Jackson.
FusionAuth JWT is intended to be fast and easy to use. FusionAuth JWT has a single external dependency on Jackson, no Bouncy Castle, Apache Commons or Guava.

### Features
- JWT signing using HMAC, RSA and Elliptic Curve support
- `HS256`, `HS384`, `HS512`, `RS256`, `RS384`, `RS512`, `ES256`, `ES384`, `ES512`
- PEM decoding / encoding
- Decode PEM files to PrivateKey or PublicKey
- Decode private EC keys un-encapsulated in PKCS#8, returned PEM will be in PKCS#8 form.
- Both public and private keys will be returned when encoded in the private PEM
- Encode PrivateKey or PublicKey to PEM
- JSON Web Key
- Build JWK from Private Key
- Build JWK from Public Key
- Build JWK from PEM
- Helpers
- Generate RSA Key Pairs in `2048`, `3072` or `4096` bit sizes
- Generate EC Key Pairs in `256`, `384` and `521` bit sizes
- Generate `x5t` and `x5t#256` values from X.509 Certificates
- Generate ideal HMAC secret lengths for `SHA-256`, `SHA-384` and `SHA-512`
- Generate the `at_hash` and `c_hash` claims for OpenID Connect

## Maven Dependency
```xml
<dependency>
<groupId>io.fusionauth</groupId>
<artifactId>fusionauth-jwt</artifactId>
<version>3.0.0</version>
</dependency>
```

## Example Code:

### Encode a JWT using HMAC
### JWT Signing and Verifying

#### Sign and encode a JWT using HMAC
```java
// Build an HMAC signer using a SHA-256 hash
Signer signer = HMACSigner.newSHA256Signer("too many secrets");

// Build a new JWT with an issuer(iss), issued at(iat), subject(sub) and expiration(exp)
JWT jwt = new JWT().setIssuer("www.acme.com")
.setIssuedAt(ZonedDateTime.now(ZoneOffset.UTC))
.setSubject("f1e33ab3-027f-47c5-bb07-8dd8ab37a2d3")
.setExpiration(ZonedDateTime.now(ZoneOffset.UTC).plusMinutes(60));

// Sign and encode the JWT to a JSON string representation
String encodedJWT = JWT.getEncoder().encode(jwt, signer);

```

A higher strength hash can be used by changing the signer. The encoding and decoding steps are not affected.
```java
Signer signer = HMACSigner.newSHA512Signer("too many secrets");
// Build an HMAC signer using a SHA-384 hash
Signer signer384 = HMACSigner.newSHA384Signer("too many secrets");

// Build an HMAC signer using a SHA-512 hash
Signer signer512 = HMACSigner.newSHA512Signer("too many secrets");
```

### Decode a JWT using HMAC
#### Verify and decode a JWT using HMAC
```java
// Build an HMC verifier using the same secret that was used to sign the JWT
Verifier verifier = HMACVerifier.newVerifier("too many secrets");

// Verify and decode the encoded string JWT to a rich object
JWT jwt = JWT.getDecoder().decode(encodedJWT, verifier);

// Assert the subject of the JWT is as expected
assertEquals(jwt.subject, "f1e33ab3-027f-47c5-bb07-8dd8ab37a2d3");
```

### Encode a JWT using RSA
#### Sign and encode a JWT using RSA
```java
// Build an RSA signer using a SHA-256 hash
Signer signer = RSASigner.newSHA256Signer(new String(Files.readAllBytes(Paths.get("private_key.pem"))));

// Build a new JWT with an issuer(iss), issued at(iat), subject(sub) and expiration(exp)
JWT jwt = new JWT().setIssuer("www.acme.com")
.setIssuedAt(ZonedDateTime.now(ZoneOffset.UTC))
.setSubject("f1e33ab3-027f-47c5-bb07-8dd8ab37a2d3")
.setExpiration(ZonedDateTime.now(ZoneOffset.UTC).plusMinutes(60));

// Sign and encode the JWT to a JSON string representation
String encodedJWT = JWT.getEncoder().encode(jwt, signer);
```

A higher strength hash can be used by changing the signer. The encoding and decoding steps are not affected.
```java
// Build an RSA signer using a SHA-384 hash
Signer signer = RSASigner.newSHA384Signer(new String(Files.readAllBytes(Paths.get("private_key.pem"))));

// Build an RSA signer using a SHA5124 hash
Signer signer = RSASigner.newSHA512Signer(new String(Files.readAllBytes(Paths.get("private_key.pem"))));
```

### Decode a JWT using RSA
#### Verify and decode a JWT using RSA
```java
// Build an RSA verifier using an RSA Public Key
Verifier verifier = RSAVerifier.newVerifier(Paths.get("public_key.pem"));

// Verify and decode the encoded string JWT to a rich object
JWT jwt = JWT.getDecoder().decode(encodedJWT, verifier);

// Assert the subject of the JWT is as expected
assertEquals(jwt.subject, "f1e33ab3-027f-47c5-bb07-8dd8ab37a2d3");
```

#### Sign and encode a JWT using EC
```java
// Build an EC signer using a SHA-256 hash
Signer signer = ECSigner.newSHA256Signer(new String(Files.readAllBytes(Paths.get("private_key.pem"))));

// Build a new JWT with an issuer(iss), issued at(iat), subject(sub) and expiration(exp)
JWT jwt = new JWT().setIssuer("www.acme.com")
.setIssuedAt(ZonedDateTime.now(ZoneOffset.UTC))
.setSubject("f1e33ab3-027f-47c5-bb07-8dd8ab37a2d3")
.setExpiration(ZonedDateTime.now(ZoneOffset.UTC).plusMinutes(60));

// Sign and encode the JWT to a JSON string representation
String encodedJWT = JWT.getEncoder().encode(jwt, signer);
```

A higher strength hash can be used by changing the signer. The encoding and decoding steps are not affected.
```java
// Build an EC signer using a SHA-384 hash
Signer signer = ECSigner.newSHA384Signer(new String(Files.readAllBytes(Paths.get("private_key.pem"))));

// Build an EC signer using a SHA-512 hash
Signer signer = ECSigner.newSHA512Signer(new String(Files.readAllBytes(Paths.get("private_key.pem"))));
```

#### Verify and decode a JWT using EC
```java
Verifier verifier = RSAVerifier.newVerifier(new String(Files.readAllBytes(Paths.get("public_key.pem"))));
// Build an EC verifier using an EC Public Key
Verifier verifier = ECSigner.newVerifier(Paths.get("public_key.pem"));

// Verify and decode the encoded string JWT to a rich object
JWT jwt = JWT.getDecoder().decode(encodedJWT, verifier);

// Assert the subject of the JWT is as expected
assertEquals(jwt.subject, "f1e33ab3-027f-47c5-bb07-8dd8ab37a2d3");
```

### Supported JSON Web Algorithms (JWA) as described in RFC 7518
## JSON Web Keys

### Convert a Public Key to JWK

```java
JSONWebKey jwk = JSONWebKey.build(publicKey);

String json = jwk.toJSON();
```

```json
{
"e": "AQAB",
"kty": "RSA",
"n": "Auchby3lZKHbiAZrTkJh79hJvgC3W7STSS4y6UZEhhxx3m3W2hD8qCyw6BEyrciPpwou-vmeDN7qBSk2QKqTTjlg5Pkf8O4z8d9HAlBTUDg4p98qLFOF2EFWWTiFbQwAP2qODOIv9WCAM2rkXEPwGiF962XAoOwiSmldeDu7Uo5A-bnTi0z3oNu4qm_48kv90o9CMiELszE9jsfoH32WE71HDqhsRjVNddDJ81e5zxBN8UEmaR-gmWqa63laON2KANPugJP7PrYJ_PC9ilQfV3F1rDpqbvlFQkshohJ39VrVpEtSRmJ12nqTFuspXLApekOyic3J9jo6ZI7o3IdQmy3bpnJIT_U",
"use": "sig"
}
```

### Convert a Private Key to JWK

```java
JSONWebKey jwk = JSONWebKey.build(privateKey);

String json = jwk.toJSON();
```

```json
{
"p": "9dy6wUxA0eOHopUP-E5QjDzuW8rXdaQMR566oDJ1qL0iD0koQAB9X3hboB-2Rru0aATu6WDW-jd4mgtYnXO8ow",
"kty": "RSA",
"q": "6Nfc6c8meTRkVRAHCF24LB5GLfsjoMB0tOeEO9w9Ous1a4o-D24bAePMUImAp3woFoNDRfWtlNktOqLel5Pjew",
"d": "C0G3QGI6OQ6tvbCNYGCqq043YI_8MiBl7C5dqbGZmx1ewdJBhMNJPStuckhskURaDwk4-8VBW9SlvcfSJJrnZhgFMjOYSSsBtPGBIMIdM5eSKbenCCjO8Tg0BUh_xa3CHST1W4RQ5rFXadZ9AeNtaGcWj2acmXNO3DVETXAX3x0",
"e": "AQAB",
"use": "sig",
"qi": "XLE5O360x-MhsdFXx8Vwz4304-MJg-oGSJXCK_ZWYOB_FGXFRTfebxCsSYi0YwJo-oNu96bvZCuMplzRI1liZw",
"dp": "32QGgDmjr9GX3N6p2wh1YWa_gMHmUSqUScLseUA_7eijeNYU70pCoCtAvVXzDYPhoJ3S4lQuIL2kI_tpMe8GFw",
"dq": "21tJjqeN-k-mWhCwX2xTbpTSzsyy4uWMzUTy6aXxtUkTWY2yK70yClS-Df2MS70G0za0MPtjnUAAgSYhB7HWcw",
"n": "359ZykLITko_McOOKAtpJRVkjS5itwZxzjQidW2X6tBEOYCH4LZbwfj8fGGvlUtzpyuwnYuIlNX8TvZLTenOk45pphXr5PMCMKi7YZgkhd6_t_oeHnXY-4bnDLF1r9OUFKwj6C-mFFM-woKc-62tuK6QJiuc-5bFfn9wRL15K1E"
}
```

### Add a custom property to a JWK

```java
JSONWebKey jwk = JSONWebKey.build(privateKey)
.addOther("boom", "goes the dynamite")
.addOther("more", "cowbell");

HS256, HS384, HS512, RS256, RS384, RS512, none (Unsecured)
String json = jwk.toJSON();
```

```json
{
"alg" : "ES256",
"boom" : "goes the dynamite",
"crv" : "P-256",
"kty" : "EC",
"more" : "cowbell",
"use" : "sig",
"x" : "NIWpsIea0qzB22S0utDG8dGFYqEInv9C7ZgZuKtwjno",
"y" : "iVFFtTgiInz_fjh-n1YqbibnUb2vtBZFs3wPpQw3mc0"
}
```

## Maven Dependency
```xml
<dependency>
<groupId>io.fusionauth</groupId>
<artifactId>fusionauth-jwt</artifactId>
<version>2.1.1</version>
<version>3.0.0</version>
</dependency>
```

Expand Down
8 changes: 1 addition & 7 deletions build.savant
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,13 @@ target(name: "test", description: "Runs the project's tests", dependsOn: ["jar"]

target(name: "doc", description: "Generate the project's JavaDoc", dependsOn: ["jar"]) {
java.document()

file.prune(dir: "docs")

file.copy(to: "docs") {
fileSet(dir: "build/doc")
}
}

target(name: "int", description: "Releases a local integration build of the project", dependsOn: ["test"]) {
dependency.integrate()
}

target(name: "release", description: "Releases a full version of the project", dependsOn: ["test", "doc"]) {
target(name: "release", description: "Releases a full version of the project", dependsOn: ["test"]) {
release.release()
}

Expand Down
74 changes: 0 additions & 74 deletions docs/allclasses-frame.html

This file was deleted.

Loading

0 comments on commit e6148ed

Please sign in to comment.