Skip to content

Commit ba032d3

Browse files
committed
feature: JWT authentication
1 parent 2e8d01c commit ba032d3

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed

app/middleware/auth/new.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package auth
22

33
import (
4+
"net/url"
45
"strings"
56

67
"github.com/gofiber/fiber/v2"
8+
"github.com/golang-jwt/jwt/v4"
79
"github.com/limanmys/render-engine/internal/liman"
10+
"github.com/limanmys/render-engine/pkg/helpers"
811
"github.com/limanmys/render-engine/pkg/logger"
912
)
1013

@@ -13,8 +16,33 @@ func New() fiber.Handler {
1316
return authorization
1417
}
1518

19+
type Cookie struct {
20+
Token string `cookie:"token"`
21+
}
22+
1623
// authorization Middleware auths users before requests
1724
func authorization(c *fiber.Ctx) error {
25+
cookie := new(Cookie)
26+
c.CookieParser(cookie)
27+
28+
if len(cookie.Token) > 0 {
29+
decoded, err := url.QueryUnescape(cookie.Token)
30+
if err != nil {
31+
logger.FiberError(fiber.StatusUnauthorized, "invalid authorization token (cookie), "+err.Error())
32+
}
33+
34+
if len(decoded) < 1 {
35+
return logger.FiberError(fiber.StatusUnauthorized, "authorization token is missing")
36+
}
37+
38+
code, err := helpers.LaravelAesDecrypt("token", decoded)
39+
if err != nil {
40+
return logger.FiberError(fiber.StatusUnauthorized, "invalid authorization token (cookie), "+err.Error())
41+
}
42+
43+
return jwtValidation(c, code)
44+
}
45+
1846
if len(c.FormValue("token")) > 0 {
1947
user, err := liman.AuthWithToken(
2048
strings.Trim(c.FormValue("token"), ""),
@@ -56,3 +84,23 @@ func authorization(c *fiber.Ctx) error {
5684

5785
return logger.FiberError(fiber.StatusUnauthorized, "authorization token is missing")
5886
}
87+
88+
func jwtValidation(c *fiber.Ctx, code string) error {
89+
token, err := jwt.Parse(code, func(token *jwt.Token) (interface{}, error) {
90+
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
91+
return nil, logger.FiberError(fiber.StatusUnauthorized, "invalid authorization token")
92+
}
93+
return []byte(helpers.Env("JWT_SECRET", "")), nil
94+
})
95+
96+
if err != nil {
97+
return logger.FiberError(fiber.StatusUnauthorized, "invalid authorization token")
98+
}
99+
100+
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
101+
c.Locals("user_id", claims["sub"])
102+
return c.Next()
103+
} else {
104+
return logger.FiberError(fiber.StatusUnauthorized, "invalid authorization token")
105+
}
106+
}

pkg/helpers/aes-decryptor.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package helpers
2+
3+
import (
4+
"crypto/aes"
5+
"crypto/cipher"
6+
"crypto/hmac"
7+
"crypto/sha1"
8+
"encoding/base64"
9+
"encoding/hex"
10+
"encoding/json"
11+
"errors"
12+
"strings"
13+
)
14+
15+
type laravelAesKey struct {
16+
Iv []byte `json:"iv"`
17+
Value []byte `json:"value"`
18+
Mac string `json:"mac"`
19+
Tag string `json:"tag"`
20+
}
21+
22+
func LaravelAesDecrypt(name, payload string) (string, error) {
23+
cipherText, err := base64.StdEncoding.DecodeString(payload)
24+
if err != nil {
25+
return "", err
26+
}
27+
28+
aesKey := laravelAesKey{}
29+
err = json.Unmarshal(cipherText, &aesKey)
30+
if err != nil {
31+
return "", err
32+
}
33+
34+
dummykey := Env("APP_KEY", "")
35+
dummykey = dummykey[7:]
36+
37+
key, err := base64.StdEncoding.DecodeString(dummykey)
38+
if err != nil {
39+
return "", err
40+
}
41+
42+
block, err := aes.NewCipher(key)
43+
if err != nil {
44+
return "", err
45+
}
46+
47+
if len(aesKey.Value)%aes.BlockSize != 0 {
48+
return "", errors.New("block size cant be zero")
49+
}
50+
51+
mode := cipher.NewCBCDecrypter(block, aesKey.Iv)
52+
mode.CryptBlocks(aesKey.Value, aesKey.Value)
53+
plainText := string(unpadding(aesKey.Value))
54+
55+
validator := createValidator(name, key)
56+
if strings.HasPrefix(plainText, validator) {
57+
plainText = strings.TrimPrefix(plainText, validator)
58+
} else {
59+
return "", errors.New("token cannot be validated")
60+
}
61+
62+
return plainText, nil
63+
}
64+
65+
func unpadding(src []byte) []byte {
66+
length := len(src)
67+
unpadding := int(src[length-1])
68+
69+
return src[:(length - unpadding)]
70+
}
71+
72+
func createValidator(cookieName string, key []byte) string {
73+
h := hmac.New(sha1.New, key)
74+
h.Write([]byte(cookieName + "v2"))
75+
return hex.EncodeToString(h.Sum(nil)) + "|"
76+
}

0 commit comments

Comments
 (0)