-
Notifications
You must be signed in to change notification settings - Fork 5
/
authentication_middleware.go
154 lines (129 loc) · 3.45 KB
/
authentication_middleware.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package authentication_middleware
import (
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
"github.com/gocms-io/gocms/context"
"github.com/gocms-io/gocms/context/consts"
"github.com/gocms-io/gocms/init/service"
"github.com/gocms-io/gocms/routes"
"github.com/gocms-io/gocms/utility/errors"
"net/http"
"github.com/gocms-io/gocms/utility/api_utility"
"github.com/gocms-io/gocms/utility/log"
)
type AuthMiddleware struct {
ServicesGroup *service.ServicesGroup
}
func DefaultAuthMiddleware(sg *service.ServicesGroup) *AuthMiddleware {
authMiddleware := &AuthMiddleware{
ServicesGroup: sg,
}
return authMiddleware
}
func (am *AuthMiddleware) ApplyAuthToRoutes(routes *routes.Routes) {
log.Debugf("Adding Authentication Middleware\n")
routes.Auth.Use(am.RequireAuthenticatedUser())
routes.PreTwofactor = routes.Auth
if context.Config.DbVars.UseTwoFactor {
routes.Auth.Use(am.RequireAuthenticatedDevice())
}
}
// middleware
func (am *AuthMiddleware) AddUserToContextIfValidToken() gin.HandlerFunc {
log.Debugf("Adding USER Context Middleware\n")
return am.addUserToContextIfValidToken
}
func (am *AuthMiddleware) RequireAuthenticatedUser() gin.HandlerFunc {
return am.requireAuthedUser
}
func (am *AuthMiddleware) RequireAuthenticatedDevice() gin.HandlerFunc {
return am.requireAuthedDevice
}
// getAuthedUserIfPresent
func (am *AuthMiddleware) addUserToContextIfValidToken(c *gin.Context) {
// get token
authHeader := c.Request.Header.Get("X-AUTH-TOKEN")
if authHeader == "" {
c.Next()
return
} else {
// parse token
token, err := am.verifyToken(authHeader)
if err != nil {
c.Next()
return
} else {
userId, ok := token.Claims.(jwt.MapClaims)["userId"].(float64)
if !ok {
c.Next()
return
} else {
// get user
user, err := am.ServicesGroup.UserService.Get(int64(userId))
if err != nil {
c.Next()
return
} else {
// verify user is enabled
if !user.Enabled {
c.Next()
return
}
c.Set(consts.USER_KEY_FOR_GIN_CONTEXT, *user)
// continue
c.Next()
return
}
}
}
}
}
// requireAuthedUser middleware
func (am *AuthMiddleware) requireAuthedUser(c *gin.Context) {
user, ok := api_utility.GetUserFromContext(c)
if !ok {
errors.Response(c, http.StatusUnauthorized, errors.ApiError_UserToken, nil)
return
}
if user == nil {
errors.Response(c, http.StatusUnauthorized, errors.ApiError_UserToken, nil)
return
}
c.Next()
}
// requireAuthedDevice
func (am *AuthMiddleware) requireAuthedDevice(c *gin.Context) {
// get for deviceAuthToken header if it exists
authDeviceHeader := c.Request.Header.Get("X-DEVICE-TOKEN")
// if auth token is empty fail
if authDeviceHeader == "" {
errors.Response(c, http.StatusUnauthorized, errors.ApiError_DeviceToken, nil)
return
}
// parse token
_, err := am.verifyToken(authDeviceHeader)
if err != nil {
errors.Response(c, http.StatusUnauthorized, errors.ApiError_DeviceToken, err)
return
}
// continue
c.Next()
}
// verifyToken
func (am *AuthMiddleware) verifyToken(authHeader string) (*jwt.Token, error) {
token, err := jwt.Parse(authHeader, func(token *jwt.Token) (interface{}, error) {
if jwt.SigningMethodRS256 != token.Method {
return nil, errors.New("Token signing method does not match.")
}
return context.Config.DbVars.RSAPub, nil
})
// check for parsing error
if err != nil {
return nil, err
}
// check if token is valid
if !token.Valid {
return nil, err
}
return token, nil
}