All Projects → o1egl → Paseto

o1egl / Paseto

Licence: mit
Platform-Agnostic Security Tokens implementation in GO (Golang)

Programming Languages

go
31211 projects - #10 most used programming language
golang
3204 projects

Projects that are alternatives of or similar to Paseto

Fastify Esso
The easiest authentication plugin for Fastify, with built-in support for Single sign-on
Stars: ✭ 20 (-95.66%)
Mutual labels:  authentication, jwt, auth
Access
Ponzu Addon to manage API access grants and tokens for authentication
Stars: ✭ 13 (-97.18%)
Mutual labels:  authentication, jwt, token
Django Graphql Jwt
JSON Web Token (JWT) authentication for Graphene Django
Stars: ✭ 649 (+40.78%)
Mutual labels:  authentication, jwt, token
Auth Module
auth.nuxtjs.org
Stars: ✭ 1,624 (+252.28%)
Mutual labels:  jwt, auth, token
Go Alone
A simple to use, high-performance, Go (golang) MAC signer.
Stars: ✭ 82 (-82.21%)
Mutual labels:  authentication, jwt, token
Hapi Auth Keycloak
JSON Web Token based Authentication powered by Keycloak
Stars: ✭ 29 (-93.71%)
Mutual labels:  authentication, jwt, auth
Angular Token
🔑 Token based authentication service for Angular with interceptor and multi-user support. Works best with devise token auth for Rails. Example:
Stars: ✭ 376 (-18.44%)
Mutual labels:  authentication, auth, token
Barong
Barong auth server
Stars: ✭ 100 (-78.31%)
Mutual labels:  microservice, authentication, jwt
Authex
Authex is an opinionated JWT authentication and authorization library for Elixir.
Stars: ✭ 73 (-84.16%)
Mutual labels:  authentication, jwt, auth
Paseto
Java Implementation of Platform-Agnostic Security Tokens - https://paseto.io
Stars: ✭ 32 (-93.06%)
Mutual labels:  authentication, jwt, token
Express Mongodb Rest Api Boilerplate
A boilerplate for Node.js apps / Rest API / Authentication from scratch - express, mongodb (mongoose).
Stars: ✭ 153 (-66.81%)
Mutual labels:  authentication, jwt, token
Authentic
Authentication for microservices.
Stars: ✭ 221 (-52.06%)
Mutual labels:  microservice, authentication, jwt
Jimu
.netcore micro service framework
Stars: ✭ 315 (-31.67%)
Mutual labels:  microservice, jwt
Ultrajson
Ultra fast JSON decoder and encoder written in C with Python bindings
Stars: ✭ 3,504 (+660.09%)
Mutual labels:  decoder, encoder
Jwt Auth Guard
JWT Auth Guard for Laravel and Lumen Frameworks.
Stars: ✭ 319 (-30.8%)
Mutual labels:  jwt, auth
Shinobi
👺 Simple and light-weight role-based permissions system for Laravel's built in Auth system.
Stars: ✭ 349 (-24.3%)
Mutual labels:  authentication, auth
React Native Auth Boilerplate
A react native boilerplate with authentication already implemented
Stars: ✭ 307 (-33.41%)
Mutual labels:  authentication, auth
Tiny Utf8
Unicode (UTF-8) capable std::string
Stars: ✭ 322 (-30.15%)
Mutual labels:  decoder, encoder
Jwt sessions
XSS/CSRF safe JWT auth designed for SPA
Stars: ✭ 431 (-6.51%)
Mutual labels:  jwt, auth
Flif
Free Lossless Image Format
Stars: ✭ 3,668 (+695.66%)
Mutual labels:  decoder, encoder

Golang implementation of PASETO: Platform-Agnostic Security Tokens

License GoDoc Build Status Coverage Status Go Report Card

This is a 100% compatible pure Go (Golang) implementation of PASETO tokens.

PASETO is everything you love about JOSE (JWT, JWE, JWS) without any of the many design deficits that plague the JOSE standards.

Contents

What is PASETO?

PASETO (Platform-Agnostic SEcurity TOkens) is a specification and reference implementation for secure stateless tokens.

Key Differences between PASETO and JWT

Unlike JSON Web Tokens (JWT), which gives developers more than enough rope with which to hang themselves, PASETO only allows secure operations. JWT gives you "algorithm agility", PASETO gives you "versioned protocols". It's incredibly unlikely that you'll be able to use PASETO in an insecure way.

Caution: Neither JWT nor PASETO were designed for stateless session management. PASETO is suitable for tamper-proof cookies, but cannot prevent replay attacks by itself.

PASETO

PASETO Example 1

v2.local.QAxIpVe-ECVNI1z4xQbm_qQYomyT3h8FtV8bxkz8pBJWkT8f7HtlOpbroPDEZUKop_vaglyp76CzYy375cHmKCW8e1CCkV0Lflu4GTDyXMqQdpZMM1E6OaoQW27gaRSvWBrR3IgbFIa0AkuUFw.UGFyYWdvbiBJbml0aWF0aXZlIEVudGVycHJpc2Vz

This decodes to:

  • Version: v2
  • Purpose: local (shared-key authenticated encryption)
  • Payload (hex-encoded):
    400c48a557be10254d235cf8c506e6fea418a26c93de1f05b55f1bc64cfca412
    56913f1fec7b653a96eba0f0c46542a8a7fbda825ca9efa0b3632dfbe5c1e628
    25bc7b5082915d0b7e5bb81930f25cca9076964c33513a39aa105b6ee06914af
    581ad1dc881b1486b4024b9417
    
    • Nonce: 400c48a557be10254d235cf8c506e6fea418a26c93de1f05
    • Authentication tag: 6914af581ad1dc881b1486b4024b9417
  • Decrypted Payload:
    {
      "data": "this is a signed message",
      "exp": "2039-01-01T00:00:00+00:00"
    }
    
    • Key used in this example (hex-encoded):
      707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f  
      
  • Footer:
    Paragon Initiative Enterprises
    

PASETO Example 2

v2.public.eyJleHAiOiIyMDM5LTAxLTAxVDAwOjAwOjAwKzAwOjAwIiwiZGF0YSI6InRoaXMgaXMgYSBzaWduZWQgbWVzc2FnZSJ91gC7-jCWsN3mv4uJaZxZp0btLJgcyVwL-svJD7f4IHyGteKe3HTLjHYTGHI1MtCqJ-ESDLNoE7otkIzamFskCA

This decodes to:

  • Version: v2
  • Purpose: public (public-key digital signature)
  • Payload:
    {
      "data": "this is a signed message",
      "exp": "2039-01-01T00:00:00+00:00"
    }
    
  • Signature (hex-encoded):
    d600bbfa3096b0dde6bf8b89699c59a746ed2c981cc95c0bfacbc90fb7f8207c
    86b5e29edc74cb8c761318723532d0aa27e1120cb36813ba2d908cda985b2408
    
  • Public key (hex-encoded):
    11324397f535562178d53ff538e49d5a162242970556b4edd950c87c7d86648a
    

To learn what each version means, please see this page in the documentation.

JWT

An example JWT (taken from JWT.io) might look like this:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ 

This decodes to:

Header:

{
  "alg": "HS256",
  "typ": "JWT"
}

Body:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

Signature:

TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

Motivation

As you can see, with JWT, you get to specify an alg header. There are a lot of options to choose from (including none).

There have been ways to exploit JWT libraries by replacing RS256 with HS256 and using the known public key as the HMAC-SHA256 key, thereby allowing arbitrary token forgery.

With PASETO, your options are version and a purpose. There are two possible values for purpose:

  • local -- shared-key encryption (symmetric-key, AEAD)
  • public -- public-key digital signatures (asymmetric-key)

PASETO only allows you to use authenticated modes.

Regardless of the purpose selected, the header (and an optional footer, which is always cleartext but base64url-encoded) is included in the signature or authentication tag.

Installation

To install the library use the following command:

$ go get -u github.com/o1egl/paseto

Usage

This library contains a predefined JsonToken struct for using as payload, but you are free to use any data types and structs you want.

During the encoding process, a payload of type string and []byte is used without transformation. For other data types, the library encodes the payload to JSON.

Create token using symmetric key (local mode):

symmetricKey := []byte("YELLOW SUBMARINE, BLACK WIZARDRY") // Must be 32 bytes
now := time.Now()
exp := now.Add(24 * time.Hour)
nbt := now

jsonToken := paseto.JSONToken{
        Audience:   "test",
        Issuer:     "test_service",
        Jti:        "123",
        Subject:    "test_subject",
        IssuedAt:   now,
        Expiration: exp,
        NotBefore:  nbt,
        }
// Add custom claim    to the token    
jsonToken.Set("data", "this is a signed message")
footer := "some footer"

// Encrypt data
token, err := paseto.Encrypt(symmetricKey, jsonToken, footer)
// token = "v2.local.E42A2iMY9SaZVzt-WkCi45_aebky4vbSUJsfG45OcanamwXwieieMjSjUkgsyZzlbYt82miN1xD-X0zEIhLK_RhWUPLZc9nC0shmkkkHS5Exj2zTpdNWhrC5KJRyUrI0cupc5qrctuREFLAvdCgwZBjh1QSgBX74V631fzl1IErGBgnt2LV1aij5W3hw9cXv4gtm_jSwsfee9HZcCE0sgUgAvklJCDO__8v_fTY7i_Regp5ZPa7h0X0m3yf0n4OXY9PRplunUpD9uEsXJ_MTF5gSFR3qE29eCHbJtRt0FFl81x-GCsQ9H9701TzEjGehCC6Bhw.c29tZSBmb290ZXI"

// Decrypt data
var newJsonToken paseto.JSONToken
var newFooter string
err := paseto.Decrypt(token, symmetricKey, &newJsonToken, &newFooter)

Create token using asymetric key (public mode):

b, _ := hex.DecodeString("b4cbfb43df4ce210727d953e4a713307fa19bb7d9f85041438d9e11b942a37741eb9dbbbbc047c03fd70604e0071f0987e16b28b757225c11f00415d0e20b1a2")
privateKey := ed25519.PrivateKey(b)

b, _ = hex.DecodeString("1eb9dbbbbc047c03fd70604e0071f0987e16b28b757225c11f00415d0e20b1a2")
publicKey := ed25519.PublicKey(b)

// or create a new keypair 
// publicKey, privateKey, err := ed25519.GenerateKey(nil)

jsonToken := paseto.JSONToken{
        Expiration: time.Now().Add(24 * time.Hour),
        }
        
// Add custom claim    to the token    
jsonToken.Set("data", "this is a signed message")
footer := "some footer"

// Sign data
token, err := paseto.Sign(privateKey, jsonToken, footer)
// token = "v2.public.eyJkYXRhIjoidGhpcyBpcyBhIHNpZ25lZCBtZXNzYWdlIiwiZXhwIjoiMjAxOC0wMy0xMlQxOTowODo1NCswMTowMCJ9Ojv0uXlUNXSFhR88KXb568LheLRdeGy2oILR3uyOM_-b7r7i_fX8aljFYUiF-MRr5IRHMBcWPtM0fmn9SOd6Aw.c29tZSBmb290ZXI"

// Verify data
var newJsonToken paseto.JSONToken
var newFooter string
err := paseto.Verify(token, publicKey, &newJsonToken, &newFooter)

Use Parse() function to parse all supported token versions:

IMPORTANT: Version 1 of the protocol is deprecated

b, err := hex.DecodeString("2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0d0a4d494942496a414e42676b71686b6947397730424151454641414f43415138414d49494243674b43415145417878636e47724e4f6136426c41523458707050640d0a746146576946386f7279746c4b534d6a66446831314c687956627a4335416967556b706a457274394d7649482f46384d444a72324f39486b36594b454b574b6f0d0a72333566364b6853303679357a714f722b7a4e34312b39626a52365633322b527345776d5a737a3038375258764e41334e687242633264593647736e57336c5a0d0a34356f5341564a755639553667335a334a574138355972362b6350776134793755632f56726f6d7a674679627355656e33476f724254626a783142384f514a440d0a73652f4b6b6855433655693358384264514f473974523455454775742f6c39703970732b3661474d4c57694357495a54615456784d4f75653133596b777038740d0a3148467635747a6872493055635948687638464a6b315a6435386759464158634e797975737834346e6a6152594b595948646e6b4f6a486e33416b534c4d306b0d0a6c774944415141420d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d")
block, _ := pem.Decode(b)
rsaPubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
v1PublicKey := rsaPubInterface.(*rsa.PublicKey)

b, _ = hex.DecodeString("1eb9dbbbbc047c03fd70604e0071f0987e16b28b757225c11f00415d0e20b1a2")
v2PublicKey := ed25519.PublicKey(b)


var payload JSONToken
var footer string
version, err := paseto.Parse(token, &payload, &footer, symmetricKey, map[paseto.Version]crypto.PublicKey{paseto.V1: v1PublicKey, paseto.V2: v2PublicKey})

For more information see *_test.go files.

Benchmarks

MacBook Pro (15-inch, 2018) CPU: 2,6 GHz Intel Core i7 RAM: 32 GB 2400 MHz DDR4 OS: macOS 10.14.6 GO: 1.13.7

$ go test -bench . -benchmem

Benchmark_V2_JSONToken_Encrypt-12         137578              8532 ns/op            4186 B/op         59 allocs/op
Benchmark_V2_JSONToken_Decrypt-12         139309              7970 ns/op            2048 B/op         63 allocs/op
Benchmark_V2_JSONToken_Sign-12             21598             55817 ns/op            4426 B/op         60 allocs/op
Benchmark_V2_JSONToken_Verify-12            8772            132142 ns/op            2528 B/op         64 allocs/op
Benchmark_V2_String_Encrypt-12            544958              2051 ns/op            1176 B/op         23 allocs/op
Benchmark_V2_String_Decrypt-12           1000000              1054 ns/op             568 B/op         18 allocs/op
Benchmark_V2_String_Sign-12                25144             47645 ns/op            1144 B/op         23 allocs/op
Benchmark_V2_String_Verify-12               9408            125524 ns/op             744 B/op         18 allocs/op

Supported PASETO Versions

Version 2

Version 2 (the recommended version by the specification) is fully supported.

Version 1

Version 1 (the compatibility version) is fully supported.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].