github.com/lestrrat-go/jwx/v2@v2.0.21/README.md (about)

     1  # github.com/lestrrat-go/jwx/v2 ![](https://github.com/lestrrat-go/jwx/workflows/CI/badge.svg?branch=v2) [![Go Reference](https://pkg.go.dev/badge/github.com/lestrrat-go/jwx/v2.svg)](https://pkg.go.dev/github.com/lestrrat-go/jwx/v2) [![codecov.io](https://codecov.io/github/lestrrat-go/jwx/coverage.svg?branch=v2)](https://codecov.io/github/lestrrat-go/jwx?branch=v2)
     2  
     3  Go module implementing various JWx (JWA/JWE/JWK/JWS/JWT, otherwise known as JOSE) technologies.
     4  
     5  If you are using this module in your product or your company, please add  your product and/or company name in the [Wiki](https://github.com/lestrrat-go/jwx/wiki/Users)! It really helps keeping up our motivation.
     6  
     7  # Features
     8  
     9  * Complete coverage of JWA/JWE/JWK/JWS/JWT, not just JWT+minimum tool set.
    10    * Supports JWS messages with multiple signatures, both compact and JSON serialization
    11    * Supports JWS with detached payload
    12    * Supports JWS with unencoded payload (RFC7797)
    13    * Supports JWE messages with multiple recipients, both compact and JSON serialization
    14    * Most operations work with either JWK or raw keys e.g. *rsa.PrivateKey, *ecdsa.PrivateKey, etc).
    15  * Opinionated, but very uniform API. Everything is symmetric, and follows a standard convention
    16    * jws.Parse/Verify/Sign
    17    * jwe.Parse/Encrypt/Decrypt
    18    * Arguments are organized as explicit required paramters and optional WithXXXX() style options.
    19  * Extra utilities
    20    * `jwk.Cache` to always keep a JWKS up-to-date
    21    * [bazel](https://bazel.build)-ready
    22  
    23  Some more in-depth discussion on why you might want to use this library over others
    24  can be found in the [Description section](#description)
    25  
    26  If you are using v0 or v1, you are strongly encouraged to migrate to using v2
    27  (the version that comes with the README you are reading).
    28  
    29  # SYNOPSIS
    30  
    31  <!-- INCLUDE(examples/jwx_readme_example_test.go) -->
    32  ```go
    33  package examples_test
    34  
    35  import (
    36    "bytes"
    37    "fmt"
    38    "net/http"
    39    "time"
    40  
    41    "github.com/lestrrat-go/jwx/v2/jwa"
    42    "github.com/lestrrat-go/jwx/v2/jwe"
    43    "github.com/lestrrat-go/jwx/v2/jwk"
    44    "github.com/lestrrat-go/jwx/v2/jws"
    45    "github.com/lestrrat-go/jwx/v2/jwt"
    46  )
    47  
    48  func ExampleJWX() {
    49    // Parse, serialize, slice and dice JWKs!
    50    privkey, err := jwk.ParseKey(jsonRSAPrivateKey)
    51    if err != nil {
    52      fmt.Printf("failed to parse JWK: %s\n", err)
    53      return
    54    }
    55  
    56    pubkey, err := jwk.PublicKeyOf(privkey)
    57    if err != nil {
    58      fmt.Printf("failed to get public key: %s\n", err)
    59      return
    60    }
    61  
    62    // Work with JWTs!
    63    {
    64      // Build a JWT!
    65      tok, err := jwt.NewBuilder().
    66        Issuer(`github.com/lestrrat-go/jwx`).
    67        IssuedAt(time.Now()).
    68        Build()
    69      if err != nil {
    70        fmt.Printf("failed to build token: %s\n", err)
    71        return
    72      }
    73  
    74      // Sign a JWT!
    75      signed, err := jwt.Sign(tok, jwt.WithKey(jwa.RS256, privkey))
    76      if err != nil {
    77        fmt.Printf("failed to sign token: %s\n", err)
    78        return
    79      }
    80  
    81      // Verify a JWT!
    82      {
    83        verifiedToken, err := jwt.Parse(signed, jwt.WithKey(jwa.RS256, pubkey))
    84        if err != nil {
    85          fmt.Printf("failed to verify JWS: %s\n", err)
    86          return
    87        }
    88        _ = verifiedToken
    89      }
    90  
    91      // Work with *http.Request!
    92      {
    93        req, err := http.NewRequest(http.MethodGet, `https://github.com/lestrrat-go/jwx`, nil)
    94        req.Header.Set(`Authorization`, fmt.Sprintf(`Bearer %s`, signed))
    95  
    96        verifiedToken, err := jwt.ParseRequest(req, jwt.WithKey(jwa.RS256, pubkey))
    97        if err != nil {
    98          fmt.Printf("failed to verify token from HTTP request: %s\n", err)
    99          return
   100        }
   101        _ = verifiedToken
   102      }
   103    }
   104  
   105    // Encrypt and Decrypt arbitrary payload with JWE!
   106    {
   107      encrypted, err := jwe.Encrypt(payloadLoremIpsum, jwe.WithKey(jwa.RSA_OAEP, jwkRSAPublicKey))
   108      if err != nil {
   109        fmt.Printf("failed to encrypt payload: %s\n", err)
   110        return
   111      }
   112  
   113      decrypted, err := jwe.Decrypt(encrypted, jwe.WithKey(jwa.RSA_OAEP, jwkRSAPrivateKey))
   114      if err != nil {
   115        fmt.Printf("failed to decrypt payload: %s\n", err)
   116        return
   117      }
   118  
   119      if !bytes.Equal(decrypted, payloadLoremIpsum) {
   120        fmt.Printf("verified payload did not match\n")
   121        return
   122      }
   123    }
   124  
   125    // Sign and Verify arbitrary payload with JWS!
   126    {
   127      signed, err := jws.Sign(payloadLoremIpsum, jws.WithKey(jwa.RS256, jwkRSAPrivateKey))
   128      if err != nil {
   129        fmt.Printf("failed to sign payload: %s\n", err)
   130        return
   131      }
   132  
   133      verified, err := jws.Verify(signed, jws.WithKey(jwa.RS256, jwkRSAPublicKey))
   134      if err != nil {
   135        fmt.Printf("failed to verify payload: %s\n", err)
   136        return
   137      }
   138  
   139      if !bytes.Equal(verified, payloadLoremIpsum) {
   140        fmt.Printf("verified payload did not match\n")
   141        return
   142      }
   143    }
   144    // OUTPUT:
   145  }
   146  ```
   147  source: [examples/jwx_readme_example_test.go](https://github.com/lestrrat-go/jwx/blob/v2/examples/jwx_readme_example_test.go)
   148  <!-- END INCLUDE -->
   149  
   150  # How-to Documentation
   151  
   152  * [API documentation](https://pkg.go.dev/github.com/lestrrat-go/jwx/v2)
   153  * [How-to style documentation](./docs)
   154  * [Runnable Examples](./examples)
   155  
   156  # Description
   157  
   158  This Go module implements JWA, JWE, JWK, JWS, and JWT. Please see the following table for the list of
   159  available packages:
   160  
   161  | Package name                                              | Notes                                           |
   162  |-----------------------------------------------------------|-------------------------------------------------|
   163  | [jwt](https://github.com/lestrrat-go/jwx/tree/v2/jwt) | [RFC 7519](https://tools.ietf.org/html/rfc7519) |
   164  | [jwk](https://github.com/lestrrat-go/jwx/tree/v2/jwk) | [RFC 7517](https://tools.ietf.org/html/rfc7517) + [RFC 7638](https://tools.ietf.org/html/rfc7638) |
   165  | [jwa](https://github.com/lestrrat-go/jwx/tree/v2/jwa) | [RFC 7518](https://tools.ietf.org/html/rfc7518) |
   166  | [jws](https://github.com/lestrrat-go/jwx/tree/v2/jws) | [RFC 7515](https://tools.ietf.org/html/rfc7515) + [RFC 7797](https://tools.ietf.org/html/rfc7797) |
   167  | [jwe](https://github.com/lestrrat-go/jwx/tree/v2/jwe) | [RFC 7516](https://tools.ietf.org/html/rfc7516) |
   168  ## History
   169  
   170  My goal was to write a server that heavily uses JWK and JWT. At first glance
   171  the libraries that already exist seemed sufficient, but soon I realized that
   172  
   173  1. To completely implement the protocols, I needed the entire JWT, JWK, JWS, JWE (and JWA, by necessity).
   174  2. Most of the libraries that existed only deal with a subset of the various JWx specifications that were necessary to implement their specific needs
   175  
   176  For example, a certain library looks like it had most of JWS, JWE, JWK covered, but then it lacked the ability to include private claims in its JWT responses. Another library had support of all the private claims, but completely lacked in its flexibility to generate various different response formats.
   177  
   178  Because I was writing the server side (and the client side for testing), I needed the *entire* JOSE toolset to properly implement my server, **and** they needed to be *flexible* enough to fulfill the entire spec that I was writing.
   179  
   180  So here's `github.com/lestrrat-go/jwx/v2`. This library is extensible, customizable, and hopefully well organized to the point that it is easy for you to slice and dice it.
   181  
   182  ## Why would I use this library?
   183  
   184  There are several other major Go modules that handle JWT and related data formats,
   185  so why should you use this library?
   186  
   187  From a purely functional perspective, the only major difference is this:
   188  Whereas most other projects only deal with what they seem necessary to handle
   189  JWTs, this module handles the **_entire_** spectrum of JWS, JWE, JWK, and JWT.
   190  
   191  That is, if you need to not only parse JWTs, but also to control JWKs, or
   192  if you need to handle payloads that are NOT JWTs, you should probably consider
   193  using this module. You should also note that JWT is built _on top_ of those
   194  other technologies. You simply cannot have a complete JWT package without
   195  implementing the entirety of JWS/JWE/JWK, which this library does.
   196  
   197  Next, from an implementation perspective, this module differs significantly
   198  from others in that it tries very hard to expose only the APIs, and not the
   199  internal data. For example, individual JWT claims are not accessible through
   200  struct field lookups. You need to use one of the getter methods.
   201  
   202  This is because this library takes the stance that the end user is fully capable
   203  and even willing to shoot themselves on the foot when presented with a lax
   204  API. By making sure that users do not have access to open structs, we can protect
   205  users from doing silly things like creating _incomplete_ structs, or access the
   206  structs concurrently without any protection. This structure also allows
   207  us to put extra smarts in the structs, such as doing the right thing when
   208  you want to parse / write custom fields (this module does not require the user
   209  to specify alternate structs to parse objects with custom fields)
   210  
   211  In the end I think it comes down to your usage pattern, and priorities.
   212  Some general guidelines that come to mind are:
   213  
   214  * If you want a single library to handle everything JWx, such as using JWE, JWK, JWS, handling [auto-refreshing JWKs](https://github.com/lestrrat-go/jwx/blob/v2/docs/04-jwk.md#auto-refreshing-remote-keys), use this module.
   215  * If you want to honor all possible custom fields transparently, use this module.
   216  * If you want a standardized clean API, use this module.
   217  
   218  Otherwise, feel free to choose something else.
   219  
   220  # Contributions
   221  
   222  ## Issues
   223  
   224  For bug reports and feature requests, please try to follow the issue templates as much as possible.
   225  For either bug reports or feature requests, failing tests are even better.
   226  
   227  ## Pull Requests
   228  
   229  Please make sure to include tests that excercise the changes you made.
   230  
   231  If you are editing auto-generated files (those files with the `_gen.go` suffix, please make sure that you do the following:
   232  
   233  1. Edit the generator, not the generated files (e.g. internal/cmd/genreadfile/main.go)
   234  2. Run `make generate` (or `go generate`) to generate the new code
   235  3. Commit _both_ the generator _and_ the generated files
   236  
   237  ## Discussions / Usage
   238  
   239  Please try [discussions](https://github.com/lestrrat-go/jwx/tree/v2/discussions) first.
   240  
   241  # Related Modules
   242  
   243  * [github.com/lestrrat-go/echo-middileware-jwx](https://github.com/lestrrat-go/echo-middleware-jwx) - Sample Echo middleware
   244  * [github.com/jwx-go/crypto-signer/gcp](https://github.com/jwx-go/crypto-signer/tree/main/gcp) - GCP KMS wrapper that implements [`crypto.Signer`](https://pkg.go.dev/crypto#Signer)
   245  * [github.com/jwx-go/crypto-signer/aws](https://github.com/jwx-go/crypto-signer/tree/main/aws) - AWS KMS wrapper that implements [`crypto.Signer`](https://pkg.go.dev/crypto#Signer)
   246  
   247  # Credits
   248  
   249  * Initial work on this library was generously sponsored by HDE Inc (https://www.hde.co.jp)
   250  * Lots of code, especially JWE was initially taken from go-jose library (https://github.com/square/go-jose)
   251  * Lots of individual contributors have helped this project over the years. Thank each and everyone of you very much.
   252