Package paseto provide a simple, ready to use, opinionated implementation of Platform-Agnostic SEcurity TOkens (PASETOs) v2 as defined in draft of RFC 01 [1].


This implementation only support PASETO Protocol v2.

Local mode

The local mode use crypto/rand package to generate random nonce and hashed with blake2b.

Public mode

The public mode focus on signing and verifing data, everything else is handled and filled automatically.

Steps for sender when generating new token, the Pack() method,

* Prepare the JSON token claims, set
** Issuer "iss" to PublicMode.our.ID
** Subject "sub" to subject value from parameter
** Audience "aud" to audience value from parameter
** IssuedAt to current time
** NotBefore to current time
** ExpiredAt to current time + 60 seconds
** Data field to base64 encoded of data value from parameter
* Prepare the JSON footer, set
** Key ID "kid" to PublicMode.our.ID

The user's claims data is stored using key "data" inside the JSON token, encoded using base64 (with padding). Additional footer data can be added on the Data field.

Overall, the following JSONToken and JSONFooter is generated for each token,

	"iss": <Key.ID>,
	"sub": <Subject parameter>,
	"aud": <Audience parameter>
	"exp": <time.Now() + TTL>,
	"iat": <time.Now()>,
	"nbf": <time.Now()>,
	"data": <base64.StdEncoding.EncodeToString(userData)>,
	"kid": <Key.ID>,
	"data": {}

On the receiver side, they will have list of registered peers Key (include ID, public Key, and list of allowed subject).

	peers: map[Key.ID]Key{
		Public: <ed25519.PublicKey>,
		AllowedSubjects: map[string]struct{}{
			"/api/x": struct{}{},
			"/api/y:read": struct{}{},
			"/api/z:write": struct{}{},

Step for receiver to process the token, the Unpack() method,

* Decode the token footer
* Get the registered public key based on "kid" value in token footer
** If no peers key exist matched with "kid" value, reject the token
* Verify the token using the peer public key
** If verification failed, reject the token
* Validate the token
** The Issuer must equal to peer ID
** The Audience must equal to receiver ID
** If the peer AllowedSubjects is not empty, the Subject must be in
one of them
** The current time must be after IssuedAt
** The current time must be after NotBefore
** The current time must be before ExpiredAt
** If one of the above condition is not passed, it will return an error.






This section is empty.


View Source
var DefaultTTL = 60 * time.Second

    DefaultTTL define the time-to-live of each token, by setting ExpiredAt to current time + DefaultTTL. If you want longer token, increase this value before using Pack().


    func Decrypt

    func Decrypt(aead cipher.AEAD, token string) (plain, footer []byte, err error)

      Decrypt given a shared key and encrypted token, decrypt the token to get the message.

      func Encrypt

      func Encrypt(aead cipher.AEAD, plain, footer []byte) (token string, err error)

        Encrypt given the shared key, encrypt the plain message and generate the "local" token with optional footer.

        func Sign

        func Sign(sk ed25519.PrivateKey, m, f []byte) (token string, err error)

          Sign given an Ed25519 secret key "sk", a message "m", and optional footer "f" (which defaults to empty string); sign the message "m" and generate the public token.

          func Verify

          func Verify(pk ed25519.PublicKey, sm, f []byte) (msg []byte, err error)

            Verify given a public key "pk", a signed message "sm" (that has been decoded from base64), and optional footer "f" (also that has been decoded from base64 string); verify that the signature is valid for the message.


            type JSONFooter

            type JSONFooter struct {
            	KID  string                 `json:"kid"`
            	Data map[string]interface{} `json:"data,omitempty"`

            type JSONToken

            type JSONToken struct {
            	Issuer    string     `json:"iss,omitempty"`
            	Subject   string     `json:"sub,omitempty"`
            	Audience  string     `json:"aud,omitempty"`
            	ExpiredAt *time.Time `json:"exp,omitempty"`
            	NotBefore *time.Time `json:"nbf,omitempty"`
            	IssuedAt  *time.Time `json:"iat,omitempty"`
            	TokenID   string     `json:"jti,omitempty"`
            	Data      string     `json:"data"`

            func (*JSONToken) Validate

            func (jtoken *JSONToken) Validate(audience string, peer Key) (err error)

              Validate the JSON token fields,

              * The Issuer must equaal to peer.ID
              * The Audience must equal to received ID,
              * If peer.AllowedSubjects is not empty, the Subject value must be in
              one of them,
              * The current time must be after IssuedAt field,
              * The current time must after NotBefore "nbf" field,
              * The current time must before ExpiredAt field.

              If one of the above condition is not passed, it will return an error.

              type Key

              type Key struct {
              	// ID is a unique key ID.
              	ID string
              	// PrivateKey for signing public token.
              	Private ed25519.PrivateKey
              	// PublicKey for verifying public token.
              	Public ed25519.PublicKey
              	// AllowedSubjects contains list of subject that are allowed in the
              	// token's claim "sub" to be signed by this public key.
              	// This field is used by receiver to check the claim "sub" and compare
              	// it with this list.
              	// Empty list means allowing all subjects.
              	AllowedSubjects map[string]struct{}

              type LocalMode

              type LocalMode struct {
              	// contains filtered or unexported fields

                LocalMode implement the PASETO encrypt and decrypt using shared key.

                Receive data from sender: Hello receiver
                Receive footer from sender: >>> footer

                func NewLocalMode

                func NewLocalMode(key []byte) (local *LocalMode, err error)

                  NewLocalMode create and initialize new LocalMode using shared key.

                  func (*LocalMode) Pack

                  func (l *LocalMode) Pack(data, footer []byte) (token string, err error)

                    Pack encrypt the data and generate token with optional footer.

                    func (*LocalMode) Unpack

                    func (l *LocalMode) Unpack(token string) (data, footer []byte, err error)

                      Unpack decrypt the token and return the plain data and optional footer.

                      type PublicMode

                      type PublicMode struct {
                      	// contains filtered or unexported fields

                        PublicMode implement the PASETO public mode to signing and verifying data using private key and one or more shared public keys. The PublicMode contains list of peer public keys for verifying the incoming token.

                        Received data: hello receiver
                        Received footer: {KID:sender Data:map[FOOTER:HERE]}
                        token subject "unknown-subject" is not allowed for key "sender"

                        func NewPublicMode

                        func NewPublicMode(our Key) (auth *PublicMode, err error)

                          NewPublicMode create new PublicMode with our private key for signing outgoing token.

                          func (*PublicMode) AddPeer

                          func (auth *PublicMode) AddPeer(k Key) (err error)

                            AddPeer add a key to list of known peers for verifying incoming token. The Key.Public

                            func (*PublicMode) GetPeerKey

                            func (auth *PublicMode) GetPeerKey(id string) (k Key, ok bool)

                              GetPeerKey get the peer's key based on key ID.

                              func (*PublicMode) Pack

                              func (auth *PublicMode) Pack(audience, subject string, data []byte, footer map[string]interface{}) (
                              	token string, err error,

                                Pack the data into token.

                                func (*PublicMode) RemovePeer

                                func (auth *PublicMode) RemovePeer(id string)

                                  RemovePeer remove peer's key from list.

                                  func (*PublicMode) Unpack

                                  func (auth *PublicMode) Unpack(token string) (publicToken *PublicToken, err error)

                                    Unpack the token to get the JSONToken and the data.

                                    func (*PublicMode) UnpackHTTPRequest

                                    func (auth *PublicMode) UnpackHTTPRequest(req *http.Request) (
                                    	publicToken *PublicToken, err error,

                                      UnpackHTTPRequest unpack token from HTTP request header "Authorization" or from query parameter "access_token".

                                      type PublicToken

                                      type PublicToken struct {
                                      	Token  JSONToken
                                      	Data   []byte
                                      	Footer JSONFooter

                                        PublicToken contains the unpacked public token.