-
Notifications
You must be signed in to change notification settings - Fork 0
/
auth.go
120 lines (109 loc) · 3.02 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
108
109
110
111
112
113
114
115
116
117
118
119
120
package auth
import (
"context"
"fmt"
"time"
jwt "github.com/dgrijalva/jwt-go"
"github.com/golang/protobuf/ptypes"
"github.com/navaz-alani/oryx/pb/go/pb/auth"
)
type AuthService struct {
auth.UnimplementedAuthServer
jwtSecret string
users map[string]bool
}
type JwtClaims struct {
jwt.StandardClaims
Username string
}
func NewAuthService(secret string) (*AuthService, error) {
if secret == "" {
return nil, fmt.Errorf("[auth] cannot initialize - empty secret")
}
return &AuthService{
jwtSecret: secret,
users: make(map[string]bool),
}, nil
}
func (a *AuthService) GetCert(ctx context.Context, req *auth.Request) (*auth.Cert, error) {
var username string
if req.GetRequestedUsername() == "" {
for {
if _, ok := a.users[username]; username != "" && ok {
a.users[username] = true
break
} else {
username = GenerateRandomName()
}
}
} else {
if _, ok := a.users[username]; ok {
return nil, fmt.Errorf("[auth] username taken")
}
}
expirationTime := time.Now().Add(5 * time.Minute)
claims := &JwtClaims{
StandardClaims: jwt.StandardClaims{
ExpiresAt: expirationTime.Unix(),
},
Username: username,
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
if tokenString, err := token.SignedString(a.jwtSecret); err != nil {
return nil, err
} else {
tsProto, _ := ptypes.TimestampProto(expirationTime)
return &auth.Cert{
Jwt: tokenString,
Username: username,
Expiration: tsProto,
}, nil
}
}
func (a *AuthService) jwtDecode(jwtToken string) (*jwt.Token, *JwtClaims, error) {
claims := &JwtClaims{}
if tkn, err := jwt.ParseWithClaims(jwtToken, claims,
func(token *jwt.Token) (interface{}, error) {
return a.jwtSecret, nil
}); err != nil {
if err == jwt.ErrSignatureInvalid {
return nil, nil, fmt.Errorf("[auth] signature validation fail")
}
return nil, nil, fmt.Errorf("[auth] token parse fail")
} else if !tkn.Valid {
return nil, nil, fmt.Errorf("[auth] token validation fail")
} else {
return tkn, claims, nil
}
}
func (a *AuthService) VerifCert(ctx context.Context, c *auth.Cert) (*auth.CertStatus, error) {
if _, claims, err := a.jwtDecode(c.GetJwt()); err != nil {
return nil, err
} else {
if claims.Username == c.Username {
return nil, fmt.Errorf("[auth] token validation fail")
}
var ret auth.CertStatus
ret.Status= auth.CertStatus_VALID
return &ret, nil
}
}
func (a *AuthService) RenewCert(ctx context.Context, c *auth.Cert) (*auth.Cert, error) {
if _, claims, err := a.jwtDecode(c.GetJwt()); err != nil {
return nil, err
} else if time.Unix(claims.ExpiresAt, 0).Sub(time.Now()) > 30*time.Second {
return c, nil;
} else {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
if tokenString, err := token.SignedString(a.jwtSecret); err != nil {
return nil, err
} else {
tsProto, _ := ptypes.TimestampProto(time.Now().Add(5 * time.Minute))
return &auth.Cert{
Jwt: tokenString,
Username: c.GetUsername(),
Expiration: tsProto,
}, nil
}
}
}