forked from gofiber/jwt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
113 lines (99 loc) Β· 2.84 KB
/
main.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
// π Fiber is an Express inspired web framework written in Go with π
// π API Documentation: https://fiber.wiki
// π Github Repository: https://github.com/gofiber/fiber
package jwt
import (
"github.com/dgrijalva/jwt-go"
"github.com/gofiber/fiber"
"strings"
)
type Config struct {
// Filter defines a function to skip middleware.
// Optional. Default: nil
Filter func(*fiber.Ctx) bool
// List of endpoints that doesn't require auth.
// Optional. Default: []string
NotAuth []string
// Password needs to check sign
// Required. Default: ""
TokenPassword string
// Unauthorized defines the response body for unauthorized responses.
// Optional. Default: nil
Unauthorized func(*fiber.Ctx)
// The model is needed to describe
// in what form we want to write to the jwt body
// Required. Default: struct with jwt.StandardClaims
Model struct {
User string
jwt.StandardClaims
}
// Error message we want to return in the absence of a token
// Optional.
ErrorMessage map[string]interface{}
}
func New(config ...Config) func(*fiber.Ctx) {
// Init config
var cfg Config
if len(config) > 0 {
cfg = config[0]
}
if cfg.ErrorMessage == nil {
cfg.ErrorMessage = map[string]interface{}{
"status": false,
"message": "Unauthorized",
"statusCode": 401,
}
}
if cfg.Unauthorized == nil {
cfg.Unauthorized = func(c *fiber.Ctx) {
c.Set(fiber.HeaderContentType, fiber.MIMEApplicationJSON)
c.SendStatus(401)
if cfg.ErrorMessage != nil {
_ = c.JSON(cfg.ErrorMessage)
}
}
}
// Return middleware handler
return func(c *fiber.Ctx) {
// Filter request to skip middleware
if cfg.Filter != nil && cfg.Filter(c) {
c.Next()
return
}
requestPath := c.Path() // Current request path
// Check if request does not need authentication, serve the request if it doesn't need it
for _, value := range cfg.NotAuth {
if value == requestPath {
c.Next()
return
}
}
tokenHeader := c.Get(fiber.HeaderAuthorization) // Grab the token from the header
// Check if token is missing
if len(tokenHeader) > 6 && strings.ToLower(tokenHeader[:6]) == "bearer" {
// The token normally comes in format `Bearer {token-body}`,
// we check if the retrieved token matched this requirement
splitted := strings.Split(tokenHeader, " ")
if len(splitted) == 2 {
tokenPart := splitted[1] // Grab the token part, what we are truly interested in
tk := &cfg.Model
token, err := jwt.ParseWithClaims(tokenPart, tk, func(token *jwt.Token) (interface{}, error) {
return []byte(cfg.TokenPassword), nil
})
if err != nil { // Malformed token
cfg.Unauthorized(c)
return
} else {
if !token.Valid { // Token is invalid, maybe not signed on this server
cfg.Unauthorized(c)
return
}
c.Next()
return
}
}
}
// Authentication failed
cfg.Unauthorized(c)
}
}