-
Notifications
You must be signed in to change notification settings - Fork 2
/
auth.go
107 lines (89 loc) · 2.69 KB
/
auth.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package auth
import (
"crypto/rsa"
"strings"
"time"
app "github.com/duc-cnzj/mars/v4/internal/app/helper"
"github.com/duc-cnzj/mars/v4/internal/contracts"
"github.com/duc-cnzj/mars/v4/internal/models"
"github.com/golang-jwt/jwt"
)
type Authn struct {
Authns []contracts.Authenticator
signFunc func(info contracts.UserInfo) (*contracts.SignData, error)
}
func NewAuthn(signFunc func(info contracts.UserInfo) (*contracts.SignData, error), authns ...contracts.Authenticator) *Authn {
return &Authn{Authns: authns, signFunc: signFunc}
}
func (a *Authn) VerifyToken(s string) (*contracts.JwtClaims, bool) {
for _, authn := range a.Authns {
if token, ok := authn.VerifyToken(s); ok {
return token, true
}
}
return nil, false
}
func (a *Authn) Sign(info contracts.UserInfo) (*contracts.SignData, error) {
return a.signFunc(info)
}
type jwtAuth struct {
priKey *rsa.PrivateKey
pubKey *rsa.PublicKey
}
func NewJwtAuth(priKey *rsa.PrivateKey, pubKey *rsa.PublicKey) contracts.AuthInterface {
return &jwtAuth{priKey: priKey, pubKey: pubKey}
}
func (a *jwtAuth) VerifyToken(t string) (*contracts.JwtClaims, bool) {
var token string = t
if len(t) > 6 && strings.EqualFold("bearer", t[0:6]) {
token = strings.TrimSpace(t[6:])
}
if token != "" {
parse, err := jwt.ParseWithClaims(token, &contracts.JwtClaims{}, func(token *jwt.Token) (any, error) {
return a.pubKey, nil
})
if err == nil && parse.Valid {
return parse.Claims.(*contracts.JwtClaims), true
}
}
return nil, false
}
func (a *jwtAuth) Sign(info contracts.UserInfo) (*contracts.SignData, error) {
token := jwt.NewWithClaims(jwt.SigningMethodRS256, &contracts.JwtClaims{
StandardClaims: &jwt.StandardClaims{
ExpiresAt: time.Now().Add(contracts.Expired).Unix(),
Issuer: "mars",
IssuedAt: time.Now().Unix(),
Subject: info.Email,
},
UserInfo: info,
})
signedString, err := token.SignedString(a.priKey)
if err != nil {
return nil, err
}
return &contracts.SignData{
Token: signedString,
ExpiredIn: int64(contracts.Expired.Seconds()),
}, nil
}
type accessTokenAuth struct {
app contracts.ApplicationInterface
}
func NewAccessTokenAuth(app contracts.ApplicationInterface) contracts.Authenticator {
return &accessTokenAuth{app: app}
}
func (a *accessTokenAuth) VerifyToken(t string) (*contracts.JwtClaims, bool) {
var token string = t
if len(t) > 6 && strings.EqualFold("bearer", t[0:6]) {
token = strings.TrimSpace(t[6:])
}
if token != "" {
var at models.AccessToken
if err := app.DB().Where("`token` = ?", token).First(&at).Error; err == nil {
app.DB().Model(&at).Update("last_used_at", time.Now())
return &contracts.JwtClaims{UserInfo: at.GetUserInfo()}, true
}
}
return nil, false
}