ginpaseto

package module
v0.0.0-...-7921973 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 2, 2022 License: Apache-2.0 Imports: 11 Imported by: 0

README

Gin PASETO token middleware

This is a middleware for Gin framework.

It uses pvx to provide a PASETO authentication middleware. Currently, middleware supports paseto version 4 local and public.

Usage

Download and install using go module:

export GO111MODULE=on
go get -u github.com/Livenux/gin-paseto

Import it in your code:

import "github.com/Livenux/ginpaseto"

Example

Claims

claims are pieces of information asserted about a subject.

Create Claims simple

clamis := ginpaseto.NewClaims(time.Hour * 1, time.Hour*24)

Create Claims with option(Issuer, Subject, Audience)

clamis := ginpaseto.NewClaims(time.Hour * 1, time.Hour*24,
 ginpaeto.WithClaimsOption("api.example.com", 
	 "authToken", "web.example.com"))
Local PASETO
package main

import (
	"errors"
	"net/http"
	"time"

	ginpaseto "github.com/Livenux/gin-paseto"
	"github.com/gin-gonic/gin"
)

func main() {
	// hex string key
	key := "707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f"
	maker := ginpaseto.NewPasetoLocalMaker(key)
	authMiddleware := ginpaseto.PasetoMiddleware{
		Issuer:       "api.example.com",
		Subject:      "authToken",
		Audience:     ".example.com",
		Expired:         time.Hour * 2,  // token expired
		MaxRefresh:      time.Hour * 24, // token max age
		RefreshTokenURL: "/auth/refresh",
		BaseLoginURL:    "/auth/login",
		LogoutURL:       "/auth/logout",
		TokenHeadName:   "Authorization",
		CookieName:      "auth",
		CookieSameSite:  1,
		SendCookie:      false,
		SecureCookie:    false,
		CookieHTTPOnly:  false,
	}
	// Completion property
	authMiddleware.Init(maker)



	r := gin.Default()

	// binding login handler
	r.POST(authMiddleware.BaseLoginURL, authMiddleware.LoginHandler(loginHandler))

	// need auth router group
	privateGroup := r.Group("/")
	privateGroup.Use(authMiddleware.Authorization())
	privateGroup.GET("", func(c *gin.Context) {
		c.String(http.StatusOK, "hello world")
	})
	// refresh token route
	privateGroup.GET(authMiddleware.RefreshTokenURL, authMiddleware.RefreshToken())
	// logout route
	privateGroup.GET(authMiddleware.LogoutURL, authMiddleware.LogOut())

	r.Run()

}

func loginHandler(c *gin.Context) (data any, err error) {
	user := loginUser{
		Id:       1,
		Username: "admin",
		Password: "chan9eMe",
	}
	requestUser := new(loginUser)
	if err := c.ShouldBindJSON(requestUser); err != nil {
		return nil, err
	}

	if requestUser.Username == user.Username && requestUser.Password == user.Password {
		return user, nil
	}
	return nil, errors.New("auth failed")

}

type loginUser struct {
	Id       int64  `json:"id"`
	Username string `json:"username"`
	Password string `json:"password"`
}

example start

go run main.go

login example user get token

 curl -XPOST -d '{"username": "admin", "password": "chan9eMe"}' -H "Content-Type: application/json" http://localhos
t:8080/auth/login

response token example:

{"code":200,"message":"login successful","data":{"expire":"2022-09-30T18:21:48.09772Z","token":"v4.local.qLBoiHYgkE19moyOZ0PcvhLUKTlx2QGQQ3EQ6TTLDBGMPrmqAd1jHNAf6iz6-RqAe90YFtNkWQIU3amhKPGlyyH9vKCb2pkPoW_oxft1_Q9yZzSwpuovg6Vs3xyv3eoVU8c-FepXzfcOfkNW6zUfe_WJGjAAxKn23LyO8p9wiFdRpGtzFOzlSF7nVm_iX_KZRNyQ4-91wMbm_1EUHNc3f7Jsk5mfaEWKKRP1Ez6a3A2dvQGMibPTakgpS4gmHyradbXViBKaUlkbFVX5-Qb27d1CUWu5-bIG-yOLpDgnZt7rTsOx79IkVNW29J4PEJXID_UgQzX2kXD-EN5D"}}

refresh token use exists token:

curl -XGET -H "Authorization: Bearer v4.local.qLBoiHYgkE19moyOZ0PcvhLUKTlx2QGQQ3EQ6TTLDBGMPrmqAd1jHNAf6iz6-RqAe90YFtNkWQIU3amhKPGlyyH9vKCb2pkPoW_oxft1_Q9yZzSwpuovg6Vs3xyv3eoVU8c-FepXzfcOfkNW6zUfe_WJGjAAxKn23LyO8p9wiFdRpGtzFOzlSF7nVm_iX_KZRNyQ4-91wMbm_1EUHNc3f7Jsk5mfaEWKKRP1Ez6a3A2dvQGMibPTakgpS4gmHyradbXViBKaUlkbFVX5-Qb27d1CUWu5-bIG-yOLpDgnZt7rTsOx79IkVNW29J4PEJXID_UgQzX2kXD-EN5D" http://localhost:8080/auth/refresh

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrTokenExpired    = errors.New("token has expired")
	ErrTokenMaxRefresh = errors.New("token is expired max refresh time")
)
View Source
var (
	ErrNoAuthorizationHeader     = errors.New("no Authorization header or the Authorization header is empty")
	ErrAuthorizationHeaderFormat = errors.New("incorrectly formatted Authorization header")
	ErrNoAuthorizationCookieSet  = errors.New("no Authorization Cookie set or cookie value is empty")
)
View Source
var (
	ErrNotEdPrivateKey = errors.New("key is not a valid Ed25519 private key")
	ErrNotEdPublicKey  = errors.New("key is not a valid Ed25519 public key")
)

Functions

func LoadEd25519Key

func LoadEd25519Key(ed25519PublicKey, ed25519PrivateKey string) (ed25519.PublicKey, ed25519.PrivateKey, error)

LoadEd25519Key Load Edwards curve key-pair from key block string

func ParseEdPrivateKeyBlock

func ParseEdPrivateKeyBlock(key []byte) (ed25519.PrivateKey, error)

ParseEdPrivateKeyBlock parses a pem.Block.Bytes Edwards curve private key

func ParseEdPublicKeyBlock

func ParseEdPublicKeyBlock(key []byte) (ed25519.PublicKey, error)

ParseEdPublicKeyBlock parses pem.Block.Bytes Edwards curve public key

Types

type Claims

type Claims struct {
	Issuer       string    `json:"issuer,omitempty"`
	Subject      string    `json:"subject,omitempty"`
	Audience     string    `json:"audience,omitempty"`
	IssuedAt     time.Time `json:"issued_at"`
	ExpiredAt    time.Time `json:"expired_at"`
	MaxRefreshAt time.Time `json:"max_refresh_at"`
	Data         any       `json:"data"`
}

func NewClaims

func NewClaims(expired, maxRefresh time.Duration, opts ...ClaimsOption) *Claims

NewClaims create a new token payload with data and duration

func (*Claims) Valid

func (c *Claims) Valid() error

Valid checks token has expired

type ClaimsOption

type ClaimsOption = func(c *Claims)

func WithClaimsOption

func WithClaimsOption(issuer, subject, audience string) ClaimsOption

WithClaimsOption options with issuer, subject audience

type Maker

type Maker interface {
	// CreateToken create a new token for authentication data and time duration
	CreateToken(claims *Claims) (token string, err error)
	// VerifyToken check if the token is verified or not
	VerifyToken(token string) (*Claims, error)
	// RefreshToken refresh token on Claims.MaxRefreshAt before
	RefreshToken(claims *Claims, duration time.Duration) (token string, err error)
	// RevokeToken expire the token
	RevokeToken(claims *Claims) error
}

func NewPasetoLocalMaker

func NewPasetoLocalMaker(key string) Maker

NewPasetoLocalMaker create paseto maker from ed25519 key

func NewPasetoPublicMaker

func NewPasetoPublicMaker(ed25519PublicKey, ed25519PrivateKey string) Maker

NewPasetoPublicMaker create paseto maker from ed25519 key

type PasetoLocalMaker

type PasetoLocalMaker struct {
	// contains filtered or unexported fields
}

func (*PasetoLocalMaker) CreateToken

func (maker *PasetoLocalMaker) CreateToken(claims *Claims) (string, error)

func (*PasetoLocalMaker) RefreshToken

func (maker *PasetoLocalMaker) RefreshToken(claims *Claims, duration time.Duration) (string, error)

func (*PasetoLocalMaker) RevokeToken

func (maker *PasetoLocalMaker) RevokeToken(claims *Claims) error

func (*PasetoLocalMaker) VerifyToken

func (maker *PasetoLocalMaker) VerifyToken(token string) (*Claims, error)

type PasetoMiddleware

type PasetoMiddleware struct {
	Issuer          string `json:"issuer,omitempty"`
	Subject         string `json:"subject,omitempty"`
	Audience        string `json:"audience,omitempty"`
	Maker           Maker
	Claims          *Claims
	Expired         time.Duration
	MaxRefresh      time.Duration
	RefreshTokenURL string
	BaseLoginURL    string
	LogoutURL       string
	TokenHeadName   string
	TokenLookup     map[string]string
	CookieName      string
	CookieSameSite  http.SameSite
	SendCookie      bool
	SecureCookie    bool
	CookieHTTPOnly  bool
}

func (*PasetoMiddleware) Authorization

func (pm *PasetoMiddleware) Authorization() gin.HandlerFunc

Authorization gin authorization middleware handler

func (*PasetoMiddleware) Init

func (pm *PasetoMiddleware) Init(maker Maker)

Init parse PasetoMiddleware attributes to claims

func (*PasetoMiddleware) LogOut

func (pm *PasetoMiddleware) LogOut() gin.HandlerFunc

func (*PasetoMiddleware) LoginHandler

func (pm *PasetoMiddleware) LoginHandler(loginFunc func(c *gin.Context) (data any, err error)) gin.HandlerFunc

LoginHandler from gin context get login data to claim create token

func (*PasetoMiddleware) RefreshToken

func (pm *PasetoMiddleware) RefreshToken() gin.HandlerFunc

RefreshToken refresh token before max refresh time

type PasetoPublicMaker

type PasetoPublicMaker struct {
	// contains filtered or unexported fields
}

func (*PasetoPublicMaker) CreateToken

func (maker *PasetoPublicMaker) CreateToken(claims *Claims) (string, error)

func (*PasetoPublicMaker) RefreshToken

func (maker *PasetoPublicMaker) RefreshToken(claims *Claims, duration time.Duration) (string, error)

func (*PasetoPublicMaker) RevokeToken

func (maker *PasetoPublicMaker) RevokeToken(claims *Claims) error

func (*PasetoPublicMaker) VerifyToken

func (maker *PasetoPublicMaker) VerifyToken(token string) (*Claims, error)

type Response

type Response struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
	Href    string `json:"href,omitempty"`
	Data    any    `json:"data,omitempty"`
}

type TokenResponse

type TokenResponse struct {
	Expire time.Time `json:"expire"`
	Token  string    `json:"token"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL