JSON Web Token library

Overview

API Documentation Build Status

About

… a JSON Web Token (JWT) library for the Go programming language.

  • Feature complete
  • Full test coverage
  • Dependency free
  • Key management

The API enforces secure use by design. Unsigned tokens are rejected. No support for encrypted tokens either—use wire encryption instead.

This is free and unencumbered software released into the public domain.

Introduction

Tokens encapsulate signed statements called claims. A claim is a named JSON value. Applications using JWTs should define which specific claims they use and when they are required or optional.

var claims jwt.Claims
claims.Subject = "alice"
claims.Issued  = jwt.NewNumericTime(time.Now().Round(time.Second))
claims.Set     = map[string]interface{}{"email_verified": false}
// issue a JWT
token, err := claims.EdDSASign(JWTPrivateKey)

Tokens consists of printable ASCII characters, e.g., eyJhbGciOiJFUzI1NiJ9.eyJzdWIiOiJha3JpZWdlciIsInByZWZpeCI6IkRyLiJ9.RTOboYsLW7zXFJyXtIypOmXfuRGVT_FpDUTs2TOuK73qZKm56JcESfsl_etnBsl7W80TXE5l5qecrMizh3XYmw. Secured resources can use such tokens to determine the respective permissions. Note how the verification process is self-contained with just a public key.

// verify a JWT
claims, err := jwt.EdDSACheck(token, JWTPublicKey)
if err != nil {
	log.Print("credentials denied with ", err)
	return
}
if !claims.Valid(time.Now()) {
	log.Print("credential time constraints exceeded")
	return
}

log.Print("hello ", claims.Subject)
if verified, _ := claims.Set["email_verified"].(bool); !verified {
	log.Print("e-mail confirmation pending")
}

Commonly, agents receive a JWT uppon authentication/login. Then, that token is included with requests to the secured resources, as a proof of authority. Token access is “eyes only” in such scenario. Include and enforce more context detail with claims to further reduce risk. E.g., a session identifier or a fingerprint of the client's TLS key can prevent usage of any hijacked tokens.

High-Level API

Server-side security can be applied with a standard http.Handler setup. The following example denies requests to MyAPI when the JWT is not valid, or when the JWT is missing either the subject, formatted name or roles claim.

// define trusted credentials
var keys jwt.KeyRegister
n, err := keys.LoadPEM(text, nil)
if err != nil {
	log.Fatal(err)
}
log.Print("setup with ", n, " JWT keys")

http.Handle("/api/v1", &jwt.Handler{
	Target: MyAPI, // protected HTTP handler
	Keys:   keys,

	// map two claims to HTTP headers
	HeaderPrefix: "X-Verified-",
	HeaderBinding: map[string]string{
		"sub": "X-Verified-User", // registered [standard] claim
		"fn":  "X-Verified-Name", // private [custom] claim
	},

	// map another claim with custom logic
	Func: func(w http.ResponseWriter, req *http.Request, claims *jwt.Claims) (pass bool) {
		log.Printf("got a valid JWT %q for %q", claims.ID, claims.Audiences)

		// map role enumeration
		s, ok := claims.String("roles")
		if !ok {
			http.Error(w, "jwt: want roles claim as a string", http.StatusForbidden)
			return false
		}
		req.Header["X-Verified-Roles"] = strings.Fields(s)

		return true
	},
})

When all applicable JWT claims are mapped to HTTP request headers, then the service logic can stay free of verification code, plus easier unit testing.

// Greeting is a standard HTTP handler fuction.
func Greeting(w http.ResponseWriter, req *http.Request) {
	fmt.Fprintf(w, "Hello %s!\n", req.Header.Get("X-Verified-Name"))
	fmt.Fprintf(w, "You are authorized as %s.\n", req.Header.Get("X-Verified-User"))
}

The validated Claims object may also be exposed through the request context.

Performance

The following results were measured with Go 1.15RC2 on an Intel i5-7500.

name                      time/op
ECDSA/sign-ES256-4        27.9µs ± 0%
ECDSA/sign-ES384-4        4.36ms ± 0%
ECDSA/sign-ES512-4        7.66ms ± 0%
ECDSA/check-ES256-4       83.1µs ± 1%
ECDSA/check-ES384-4       8.61ms ± 0%
ECDSA/check-ES512-4       14.9ms ± 0%
EdDSA/sign-EdDSA-4        51.6µs ± 0%
EdDSA/check-EdDSA-4        138µs ± 1%
HMAC/sign-HS256-4         2.03µs ± 1%
HMAC/sign-HS256-reuse-4   1.42µs ± 1%
HMAC/sign-HS384-4         2.32µs ± 0%
HMAC/sign-HS384-reuse-4   1.39µs ± 0%
HMAC/sign-HS512-4         2.35µs ± 1%
HMAC/sign-HS512-reuse-4   1.42µs ± 0%
HMAC/check-HS256-4        4.14µs ± 0%
HMAC/check-HS256-reuse-4  3.51µs ± 1%
HMAC/check-HS384-4        4.47µs ± 1%
HMAC/check-HS384-reuse-4  3.53µs ± 0%
HMAC/check-HS512-4        4.53µs ± 1%
HMAC/check-HS512-reuse-4  3.57µs ± 0%
RSA/sign-1024-bit-4        327µs ± 0%
RSA/sign-2048-bit-4       1.49ms ± 0%
RSA/sign-4096-bit-4       8.14ms ± 1%
RSA/check-1024-bit-4      29.0µs ± 0%
RSA/check-2048-bit-4      64.6µs ± 1%
RSA/check-4096-bit-4       173µs ± 1%

EdDSA [Ed25519] produces small signatures and it performs well.

Standard Compliance

  • RFC 2617: “HTTP Authentication”
  • RFC 6750: “The OAuth 2.0 Authorization Framework: Bearer Token Usage”
  • RFC 7468: “Textual Encodings of PKIX, PKCS, and CMS Structures”
  • RFC 7515: “JSON Web Signature (JWS)”
  • RFC 7517: “JSON Web Key (JWK)”
  • RFC 7518: “JSON Web Algorithms (JWA)”
  • RFC 7519: “JSON Web Token (JWT)”
  • RFC 8037: “CFRG Elliptic Curve Diffie-Hellman (ECDH) and Signatures in JSON Object Signing and Encryption (JOSE)”

JWT.io

Issues
  • Abstract signing

    Abstract signing

    Feature Request. I can make a call to Azure keyvault to sign and what I get back are the following ;

    1. kid
    2. base64 url encoded signature
    3. alg, i.e. "RSA256" passed in

    Could you think about putting the signing stuff into an interface and letting me implement that on my end. I would still expect your code to construct the JWT ({0}.{1}.{signature})

    That way we could also reduce what looks like redundant code in all the *Sign() functions.

    my POC function looks like this, and would change based upon the interface requirements of your engine;

    // HARD CODED to SHA256 at the moment
    
    func RSA256AzureSign(ctx context.Context, data []byte) (kid *string, signature *string, err error) {
    	keyClient := getKeysClient()
    	digest := crypto.SHA256.New()
    	digest.Write(data)
    	h := digest.Sum(nil)
    	sEnc := b64.StdEncoding.EncodeToString(h)
    
    	keyOperationResult, err := keyClient.Sign(ctx, "https://P7KeyValut.vault.azure.net/", "P7IdentityServer4SelfSigned", "", keyvault.KeySignParameters{
    		Algorithm: keyvault.RS256,
    		Value:     &sEnc,
    	})
    	if err != nil {
    		return
    	}
    	return keyOperationResult.Kid, keyOperationResult.Result, nil
    }
    

    The call to azure picks the latest version of the cert and signs for me, returning the kid and the base64 signature.

    enhancement 
    opened by ghstahl 10
  • Missing Ed25519 package

    Missing Ed25519 package

    Hey there! Love your package. It's very simple and straight-forward. I prefer it to other JWT packages thanks to its API. Great job!

    I only have one problem. I have jwt in my project and it's in my go.mod and in go.sum. Every time I try to run go test -v -count=1 ./... in my root directory, it complains about jwt's imported library and fails:

    myproject:master* λ go test -v -count=1 ./...
    ../../pascaldekloe/jwt/check.go:6:2: cannot find package "crypto/ed25519" in any of:
    	/usr/lib/go/src/crypto/ed25519 (from $GOROOT)
    	/home/myusername/go/src/crypto/ed25519 (from $GOPATH)
    

    crypto/ed25519 exists on my system:

    ed25519:master λ pwd
    /home/myusername/go/src/golang.org/x/crypto/ed25519
    

    Is there something wrong with my system variables or import paths?

    This problem doesn't occur with any other packages.

    Thanks!

    question 
    opened by thecsw 6
  • Custom Error responses

    Custom Error responses

    Refactored previous MR with a suggested more general approach via

            WriteError func(w ResponseWriter, error string, code int)
    

    Also added tests

    enhancement good first issue 
    opened by krylphi 6
  • No typ in header

    No typ in header

    Hi,

    I just wandering can we put typ in the header?

    Thanks

    enhancement 
    opened by grim-bees 5
  • Feature/example request

    Feature/example request

    This library looks very promising, however, to make it really useful, I have two questions:

    1. can you provide a convenient method to convert a JSON string into the jwt.Claims structure?
    2. how can I verify a jwt token if I have a private string typed password?

    For 1, you can argue that it's not this project's responsibility to do it, that's fine. But for 2, I cannot believe it's not documented in the readme.md. This is the most fundamental use of jwt. I think if your project is better documented, this project will gain 50x more popularity. I have been here several times and was turned off by lacking of useful examples every time. This time I finally decided to open this ticket. Thanks.

    question 
    opened by elgs 5
  • Unexported errors

    Unexported errors

    I'm curious as to why some of potential return errors from HMACCheckHeader aren't exported. This includes errAuthHeader, and errAuthSchema. Since they aren't exported I can't compare against them in my middleware.

    I need to handle differently the situations where an invalid token is submitted and no token is submitted. I could just duplicate the code, but those errors are already being returned. To take advantage of them, I'd need to do string comparison, which is frowned upon.

    Any interest in exporting these errors?

    enhancement 
    opened by freb 4
  • Audiences are represented as string if claims.Set is used

    Audiences are represented as string if claims.Set is used

    Hi, at first, thank you for this awesome library! But whenever I use claims.Set = map[string]interface{}{"role": "userrole",} audiences are stated as a string instead of an array.

    E.g.:

    {
      "aud": "audience.org",
      "exp": 1897992150.1938002,
      "iat": 1582275750,
      "iss": "issuer.org",
      "role": "userrole",
      "sub": "0ff88b48-231c-4862-8fcf-56c7fce32400"
    }
    

    vs.

    {
      "aud": [
               "audience.org"
             ],
      "exp": 1897992150.1938002,
      "iat": 1582275750,
      "iss": "issuer.org",
      "sub": "0ff88b48-231c-4862-8fcf-56c7fce32400"
    }
    
    opened by TimoGatta 4
  • Use semver to support go module

    Use semver to support go module

    If you try to use this lib with go 1.11's module system the latest release it will download is v1.2.1. Go modules require tags to be formatted as vx.y.z where x is MAJOR, y is MINOR and z is the PATCH number. Could you migrate tags and releases to semver-formatted strings?

    enhancement 
    opened by jammehcow 3
  • Remove goe dependency

    Remove goe dependency

    Thanks for your work on this package.

    In the README it says the package uses no third-party dependencies, but the go.mod file lists the dependency github.com/pascaldekloe/goe.

    From a quick check it looks like the only place goe is being used is the following line: https://github.com/pascaldekloe/jwt/blob/fcba0b3ef7ede11014a95c26e2ecea73a94e5013/x/x_test.go#L134

    I was wondering if the test could be refactored to inline any necessary code, instead of pulling through the whole dependency?

    enhancement 
    opened by alexedwards 3
  • How to encode/decode ed25519 keys

    How to encode/decode ed25519 keys

    Must these be stored in binary in a file? I want to persist them to a file, but so far have not been able to encode/decode as PEM, or even base64. They are always corrupt when I read them back in.

    If I try to generate the keys from openssl or ssh-keygen, I'm also not able to read those in as valid ed25519 keys.

    The test I use is to generate them in Go, then try to encode them, decode them, and re-run a sign/verify.

    invalid question 
    opened by davisford 3
Releases(v1.10.0)
Owner
Pascal S. de Kloe
freelance engineer
Pascal S. de Kloe
This package provides json web token (jwt) middleware for goLang http servers

jwt-auth jwt auth middleware in goLang. If you're interested in using sessions, checkout my sessions library! README Contents: Quickstart Performance

Adam Hanna 206 Sep 21, 2021
The easiest JWT library to GO

JWT Go The easiest JWT Library that could be a starting point for your project. Installation go get github.com/supanadit/jwt-go Quick Start package ma

Supan Adit Pratama 16 Apr 21, 2021
JWT login microservice with plugable backends such as OAuth2, Google, Github, htpasswd, osiam, ..

loginsrv loginsrv is a standalone minimalistic login server providing a JWT login for multiple login backends. ** Attention: Update to v1.3.0 for Goog

tarent 1.8k Sep 23, 2021
OAuth 2.0 middleware service for chi (ported from gin by community member)

oauth middleware OAuth 2.0 Authorization Server & Authorization Middleware for go-chi This library was ported to go-chi from https://github.com/maxzer

go-chi 9 Sep 23, 2021
Golang implementation of JSON Web Tokens (JWT)

jwt-go A go (or 'golang' for search engine friendliness) implementation of JSON Web Tokens NEW VERSION COMING: There have been a lot of improvements s

Dave Grijalva 9.9k Sep 24, 2021
Platform-Agnostic Security Tokens implementation in GO (Golang)

Golang implementation of PASETO: Platform-Agnostic Security Tokens This is a 100% compatible pure Go (Golang) implementation of PASETO tokens. PASETO

Oleg Lobanov 538 Sep 20, 2021
A go implementation of JSON Web Tokens

jwt-go A go (or 'golang' for search engine friendliness) implementation of JSON Web Tokens NEW VERSION COMING: There have been a lot of improvements s

null 941 Sep 23, 2021
Go login handlers for authentication providers (OAuth1, OAuth2)

gologin Package gologin provides chainable login http.Handler's for Google, Github, Twitter, Facebook, Bitbucket, Tumblr, or any OAuth1 or OAuth2 auth

Dalton Hubble 1.4k Sep 23, 2021
HTTP Session Management for Go

SCS: HTTP Session Management for Go Features Automatic loading and saving of session data via middleware. Choice of server-side session stores includi

Alex Edwards 931 Sep 23, 2021
JSON Web Token library

About … a JSON Web Token (JWT) library for the Go programming language. Feature complete Full test coverage Dependency free Key management The API enf

Pascal S. de Kloe 264 Sep 12, 2021
The boss of http auth.

Authboss Authboss is a modular authentication system for the web. It has several modules that represent authentication and authorization features that

Volatile Technologies Inc. 2.8k Sep 14, 2021
Safe, simple and fast JSON Web Tokens for Go

jwt JSON Web Token for Go RFC 7519, also see jwt.io for more. The latest version is v3. Rationale There are many JWT libraries, but many of them are h

cristaltech 289 Sep 24, 2021
simple-jwt-provider - Simple and lightweight provider which exhibits JWTs, supports login, password-reset (via mail) and user management.

Simple and lightweight JWT-Provider written in go (golang). It exhibits JWT for the in postgres persisted user, which can be managed via api. Also, a password-reset flow via mail verification is available. User specific custom-claims also available for jwt-generation and mail rendering.

Max 20 Aug 2, 2021
An implementation of JOSE standards (JWE, JWS, JWT) in Go

Go JOSE Package jose aims to provide an implementation of the Javascript Object Signing and Encryption set of standards. This includes support for JSO

Square 1.8k Sep 24, 2021
This is an implementation of JWT in golang!

jwt This is a minimal implementation of JWT designed with simplicity in mind. What is JWT? Jwt is a signed JSON object used for claims based authentic

John Rowley 92 Aug 25, 2021
A collection of authentication Go packages related to OIDC, JWKs and Distributed Claims.

cap (collection of authentication packages) provides a collection of related packages which enable support for OIDC, JWT Verification and Distributed Claims.

HashiCorp 297 Sep 19, 2021
:key: Secure alternative to JWT. Authenticated Encrypted API Tokens for Go.

branca branca is a secure alternative to JWT, This implementation is written in pure Go (no cgo dependencies) and implements the branca token specific

Wesley Hill 158 Sep 17, 2021
⛩️ Go library for protecting HTTP handlers with authorization bearer token.

G8, pronounced Gate, is a simple Go library for protecting HTTP handlers with tokens. Tired of constantly re-implementing a security layer for each

Chris C. 28 Aug 6, 2021
Go + Vue开发的管理系统脚手架, 前后端分离, 仅包含项目开发的必需部分, 基于角色的访问控制(RBAC), 分包合理, 精简易于扩展。 后端Go包含了gin、 gorm、 jwt和casbin等的使用, 前端Vue基于vue-element-admin开发

go-web-mini Go + Vue开发的管理系统脚手架, 前后端分离, 仅包含项目开发的必需部分, 基于角色的访问控制(RBAC), 分包合理, 精简易于扩展。 后端Go包含了gin、 gorm、 jwt和casbin等的使用, 前端Vue基于vue-element-admin开发: http

gnimli 17 Sep 9, 2021