89 lines
1.8 KiB
Go
89 lines
1.8 KiB
Go
package auth
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/kataras/golog"
|
|
"github.com/kataras/iris/v12"
|
|
"github.com/kataras/iris/v12/middleware/jwt"
|
|
"github.com/kataras/iris/v12/sessions"
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
type JWTAuthOption func(j *JWTAuth)
|
|
|
|
type StandardClaim struct {
|
|
Name string `json:"name"`
|
|
}
|
|
|
|
func defaultClaim() any {
|
|
return new(StandardClaim)
|
|
}
|
|
|
|
type JWTAuth struct {
|
|
signer *jwt.Signer
|
|
claimFn func() any
|
|
Middleware func(ctx iris.Context)
|
|
}
|
|
|
|
func NewJWTAuth(secret string, lifeTime time.Duration, options ...JWTAuthOption) *JWTAuth {
|
|
secretBytes := []byte(secret)
|
|
|
|
j := &JWTAuth{
|
|
signer: jwt.NewSigner(jwt.HS256, secretBytes, lifeTime),
|
|
claimFn: defaultClaim,
|
|
}
|
|
|
|
for _, jo := range options {
|
|
jo(j)
|
|
}
|
|
|
|
verifier := jwt.NewVerifier(jwt.HS256, secretBytes)
|
|
verifier.WithDefaultBlocklist()
|
|
|
|
extractor := func(ctx iris.Context) string {
|
|
session := sessions.Get(ctx)
|
|
return session.GetString("token")
|
|
}
|
|
|
|
verifier.Extractors = append(verifier.Extractors, extractor)
|
|
|
|
j.Middleware = verifier.Verify(func() any {
|
|
return j.claimFn()
|
|
})
|
|
|
|
return j
|
|
}
|
|
|
|
func WithCustomClaim(fn func() any) JWTAuthOption {
|
|
return func(j *JWTAuth) {
|
|
j.claimFn = fn
|
|
}
|
|
}
|
|
|
|
func (j *JWTAuth) Sign(claim any) ([]byte, error) {
|
|
return j.signer.Sign(claim)
|
|
}
|
|
|
|
func (j *JWTAuth) GenerateRandomSecret() string {
|
|
return j.HashAndSalt(string(jwt.MustGenerateRandom(64)))
|
|
}
|
|
|
|
func (j *JWTAuth) HashAndSalt(pwd string) string {
|
|
hash, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
golog.Fatalf("Failed to hash password: %v", err)
|
|
}
|
|
|
|
return string(hash)
|
|
}
|
|
|
|
func (j *JWTAuth) ComparePasswords(hashedPwd string, plainPwd string) bool {
|
|
err := bcrypt.CompareHashAndPassword([]byte(hashedPwd), []byte(plainPwd))
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|