gwt

package module
v1.0.5 Latest Latest
Warning

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

Go to latest
Published: Feb 5, 2022 License: MIT Imports: 9 Imported by: 0

README

gin-jwt tests codecov codebeat badge

jwt package for gin go applications

Usage

Download using go module:

go get github.com/ennaque/go-gin-jwt@v1.0.5

Import it in your code:

import gwt "github.com/ennaque/go-gin-jwt"
import gwtstorage "github.com/ennaque/go-gin-jwt/storage"

Example

package main

import (
	gwt "github.com/ennaque/go-gin-jwt"
	gwtstorage "github.com/ennaque/go-gin-jwt/storage"
	"github.com/go-redis/redis/v8"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
)

func main() {
	router := gin.Default()

	// GetDBConnectionData() - user func, must return dns string
	// postgres is not required, other drivers can be used here
	db, err := gorm.Open(postgres.Open(GetDBConnectionData()))
	if err != nil {
		panic("db con failed")
	}

	// init gorm storage
	gs, err := gwtstorage.InitGormStorage(db, "jwt1234_")
	if err != nil {
		panic(err)
	}

	// init redis storage
	// GetRedisOptions() - user func, must return *redis.Options
	rs := gwtstorage.InitRedisStorage(redis.NewClient(GetRedisOptions()))

	auth, _ := gwt.Init(gwt.Settings{
		Authenticator: func(c *gin.Context) (string, error) { // required
			// LoginCredentials - your login credentials model, can be differ
			var loginCredentials LoginCredentials
			if err := c.ShouldBind(&loginCredentials); err != nil {
				return "", errors.New("bad request")
			}
			// GetUserByCredentials - user func, must return user model
			user, err := GetUserByCredentials(&loginCredentials)
			if err != nil {
				return "", errors.New("unauthorized")
			}
			return user.GetId(), nil
		},
		AccessSecretKey:  []byte("access_super_secret"), // required
		RefreshSecretKey: []byte("refresh_super_secret"), // optional, default - AccessSecretKey
		Storage:          gs, // required, use gorm or redis storage
		// Storage: rs,
		GetUserFunc: func(userId string) (interface{}, error) { // required
			return GetUserById(userId)
		},
		AccessLifetime:  time.Minute * 15, // optional, default - time.Minute * 15
		RefreshLifetime: time.Hour * 24, // optional, default - time.Hour * 24
		SigningMethod:   "HS256", // optional, default - HS256
		AuthHeadName:    "Bearer", // optional, default - Bearer
	})

	a := router.Group("auth")
	{
		a.POST("/logout", auth.Handler.GetLogoutHandler())
		a.POST("/login", auth.Handler.GetLoginHandler())
		a.POST("/refresh", auth.Handler.GetRefreshHandler())
		a.POST("/force-logout", auth.Handler.GetForceLogoutHandler())
	}

	router.Group("/api").Use(auth.Middleware.GetAuthMiddleware()).GET("/get-user-id", func(c *gin.Context) {
		user, _ := c.Get("user")
		c.JSON(http.StatusOK, gin.H{
			"userId": user.(*models.User).ID,
		})
	})

	err := router.Run(":8000")
	if err != nil {
		panic("err")
	}
}

Get tokens

curl -X POST -d "username=<user_name>&password=<password>" http://localhost:8000/auth/login

username and password params may differ depending on your login credentials

Response 200 OK:

{
    "access_expire": "1633653988",
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NfdXVpZCI6IjlkODFmNjRkLWY0ZWYtNDA2NC04YTY3LTRjNjMzY2MxNjExOCIsImV4cCI6MTYzMzY1Mzk4OCwicmVmcmVzaF91dWlkIjoiOTU3NWU5ZDEtNWFjOS00YmIzLTkwOGItODA3MmJkNDdmOTM2IiwidXNlcl9pZCI6IjI5In0.0CfHPjkVFiQixa4SdE5EUhu23imNri02QMFsDDXJHzg",
    "refresh_expire": "1633739788",
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NfdXVpZCI6IjlkODFmNjRkLWY0ZWYtNDA2NC04YTY3LTRjNjMzY2MxNjExOCIsImV4cCI6MTYzMzczOTc4OCwicmVmcmVzaF91dWlkIjoiOTU3NWU5ZDEtNWFjOS00YmIzLTkwOGItODA3MmJkNDdmOTM2IiwidXNlcl9pZCI6IjI5In0.UvPTvVaNkAgFVTrAEoaUK1n4iIYFGh1yNqPzzNbtUUM"
}

Refresh token

curl -X POST -d "refresh_token=<refresh_token>" http://localhost:8000/auth/refresh

Response 200 OK:

{
    "access_expire":"1633659261",
    "access_token":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NfdXVpZCI6ImJiNjBhYzlmLTQ4ZGEtNDlhZC04NTM1LTU5MTJhY2MwZDIwNyIsImV4cCI6MTYzMzY1OTI2MSwicmVmcmVza
F91dWlkIjoiNDkxMWYxZjUtYjk5Ni00ZTEwLWE4NGEtNDg3NGVmNjMzZDc4IiwidXNlcl9pZCI6IjI5In0.tupNFRnANQmOScjWzlnWXzncX0Kxs7M40rsbFs0Vpg-70Ucc7R7vX2e7uAFf1fiAMODfGS5d3PRK3Nwk4RoPzg",
    "refresh_expire":"1633831941",
    "refresh_token":"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NfdXVpZCI6ImJiNjBhYzlmLTQ4ZGEtNDlhZC04NTM1LTU5MTJhY2MwZDIwNyIsImV4cCI6MTYzMzgzMTk0MSwicmVmcmVz
aF91dWlkIjoiNDkxMWYxZjUtYjk5Ni00ZTEwLWE4NGEtNDg3NGVmNjMzZDc4IiwidXNlcl9pZCI6IjI5In0.lj2nS6-M4GT-T9PHj9ijNY4g6h5hyP0xdVTHCw1M-07aL4zp7HpFrXFrT-V6RWpofaGvM79o64f8WECEqRPjig"
}

Logout

curl -X POST -H "Authorization: Bearer <access_token>" http://localhost:8000/auth/logout

Response 200 OK:

{}

Force logout user

This endpoint should be used only by authorized user.

curl -X POST -H "Authorization: Bearer <access_token>" -d "user_id=<user_id_to_logout>" http://localhost:8000/auth/force-logout

Response 200 OK:

{}

Additionaly there is a public method gwt.Service.ForceLogoutUser(userId)

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrFailedToCreateAccessToken indicates access Token failed to create, reason unknown
	ErrFailedToCreateAccessToken = errors.New("failed to create access Token")

	// ErrFailedToCreateRefreshToken indicates refresh Token failed to create, reason unknown
	ErrFailedToCreateRefreshToken = errors.New("failed to create refresh Token")

	// ErrEmptyAccessSecretKey indicates access secret key is empty
	ErrEmptyAccessSecretKey = errors.New("empty access token secret key")

	// ErrEmptyGetUserFunc indicates get user func is empty
	ErrEmptyGetUserFunc = errors.New("empty get user by id func")

	// ErrEmptyAuthenticator indicates authentication function is empty
	ErrEmptyAuthenticator = errors.New("empty authentication function")

	// ErrEmptyStorage indicates storage is not provided
	ErrEmptyStorage = errors.New("empty storage")

	// ErrCannotSaveToken indicates token is failed to save, reason unknown
	ErrCannotSaveToken = errors.New("failed to save token from storage")

	// ErrCannotDeleteToken indicates token is failed to delete, reason unknown
	ErrCannotDeleteToken = errors.New("failed to delete token from storage")

	// ErrUnknownSigningMethod indicates unknown signing method provided
	ErrUnknownSigningMethod = errors.New("unknown signing method provided")

	// ErrInvalidSigningMethod indicates signing method id invalid
	ErrInvalidSigningMethod = errors.New("invalid signing method")

	// ErrTokenExpired indicates token has expired
	ErrTokenExpired = errors.New("token has expired")

	// ErrTokenInvalid indicates token is not valid
	ErrTokenInvalid = errors.New("token is not valid")

	// ErrRefreshTokenIsNotProvided indicates refresh token is not provided
	ErrRefreshTokenIsNotProvided = errors.New("refresh token is not provided")

	// ErrNoAuthHeader indicates no auth header is provided
	ErrNoAuthHeader = errors.New("no auth header provided")

	// ErrInvalidAuthHeader indicates auth header is not valid
	ErrInvalidAuthHeader = errors.New("invalid auth header")

	// ErrUserIdIsNotProvided indicates user id is not provided
	ErrUserIdIsNotProvided = errors.New("user id is not provided")

	// ErrNotAuthUser indicates user is not authenticated
	ErrNotAuthUser = errors.New("user is not authenticated")
)
View Source
var (
	UserKey = "user"
)

Functions

This section is empty.

Types

type DefaultErrResponse added in v1.0.3

type DefaultErrResponse struct {
	ErrorCode    int    `json:"error_code"`
	ErrorMessage string `json:"error_message"`
}

type DefaultLoginResponse added in v1.0.3

type DefaultLoginResponse struct {
	AccessToken   string `json:"access_token"`
	RefreshToken  string `json:"refresh_token"`
	AccessExpire  int64  `json:"access_expire"`
	RefreshExpire int64  `json:"refresh_expire"`
}

type DefaultLogoutResponse added in v1.0.3

type DefaultLogoutResponse struct{}

type Gwt

type Gwt struct {
	Service    *Service
	Handler    *Handler
	Middleware *Middleware
}

func Init

func Init(settings Settings) (*Gwt, error)

type Handler

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

func (*Handler) GetForceLogoutHandler

func (handler *Handler) GetForceLogoutHandler() func(c *gin.Context)

func (*Handler) GetLoginHandler

func (handler *Handler) GetLoginHandler() func(c *gin.Context)

func (*Handler) GetLogoutHandler

func (handler *Handler) GetLogoutHandler() func(c *gin.Context)

func (*Handler) GetRefreshHandler

func (handler *Handler) GetRefreshHandler() func(c *gin.Context)

type Middleware

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

func (*Middleware) GetAuthMiddleware

func (mw *Middleware) GetAuthMiddleware() gin.HandlerFunc

type RefreshRequestData added in v1.0.4

type RefreshRequestData struct {
	RefreshToken string `json:"refresh_token"`
}

type Service

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

func (*Service) ForceLogoutUser

func (service *Service) ForceLogoutUser(userId string) error

type Settings

type Settings struct {

	// SigningMethod signing algorithm - possible values are HS256, HS384, HS512
	// Optional, default is HS256.
	SigningMethod string

	// AccessSecretKey used for signing. Required.
	AccessSecretKey []byte

	// RefreshSecretKey used for signing. Optional, AccessSecretKey is used by default.
	RefreshSecretKey []byte

	// AccessLifetime is a duration that an access token is valid. Optional, ten minutes by defaults.
	AccessLifetime time.Duration

	// RefreshLifetime is a duration that a refresh token is valid. Optional, one day by defaults.
	RefreshLifetime time.Duration

	// AdditionalAuthHeader is the header that will be used with default Authorization header
	// data from this header will be copied into default
	// this feature can be used to avoid Safari bug
	// when safari gets 3xx response, Authentication header will be broken in next request
	AdditionalAuthHeader string

	// AuthHeadName is a string in the header. Default value is "Bearer"
	AuthHeadName string

	// Callback function that should perform the authentication of the user based on login info.
	// Must return user id as string. Required.
	Authenticator func(c *gin.Context) (string, error)

	// GetUserFunc is function than returns application user model
	GetUserFunc func(userId string) (interface{}, error)

	// LoginResponseFunc is function that returns data after successful authentication
	LoginResponseFunc func(c *gin.Context, code int, accessToken string,
		accessExpire int64, refreshToken string, refreshExpire int64)

	// LoginResponseFunc is function that returns data after successful logout
	LogoutResponseFunc func(c *gin.Context, code int)

	// LoginResponseFunc is function that returns data after an error has been happened
	ErrResponseFunc func(c *gin.Context, code int, message string)

	// Storage is struct than stores auth data
	Storage StorageInterface
}

type StorageInterface

type StorageInterface interface {
	DeleteTokens(userId string, uuid ...string) error
	SaveTokens(userId string, accessUuid string, refreshUuid string, accessExpire int64,
		refreshExpire int64, accessToken string, refreshToken string) error
	HasRefreshToken(uuid string, token string, userId string) error
	HasAccessToken(uuid string, token string, userId string) error
	DeleteAllTokens(userId string) error
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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