The server for Open Course World
1package api
2
3import (
4 "context"
5 "fmt"
6 "net/http"
7 "smm2_gameserver/orm"
8 "strconv"
9 "time"
10
11 "github.com/dgrijalva/jwt-go"
12)
13
14// Define a function to create a new JWT token
15func createToken(userID orm.BigInt) (string, error) {
16 // Create the claims for the token
17 claims := jwt.MapClaims{
18 "sub": userID,
19 "exp": time.Now().Add(time.Hour * 24 * 14).Unix(), // Token will expire in 2 weeks
20 }
21
22 // Create the token object with claims and sign it with the secret key
23 token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
24 signedToken, err := token.SignedString(jwtSecret)
25 if err != nil {
26 return "", err
27 }
28
29 return signedToken, nil
30}
31
32func JwtMiddleware(next http.Handler) http.Handler {
33 return jwtMiddleware(next)
34}
35
36func readAuthHeaders(r *http.Request) (*http.Request, error) {
37 // Get the token from the Authorization header
38 authHeader := r.Header.Get("Authorization")
39 if authHeader == "" {
40 return nil, fmt.Errorf("empty auth header")
41 }
42
43 // Parse the token and verify it with the secret key
44 tokenString := authHeader[len("Bearer "):]
45 token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
46 if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
47 return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
48 }
49 return jwtSecret, nil
50 })
51
52 if err != nil {
53 return nil, err
54 }
55
56 claims, ok := token.Claims.(jwt.MapClaims)
57
58 if !ok || !token.Valid {
59 return nil, fmt.Errorf("invalid token")
60 }
61
62 // Extract the userID from the token claims and set it in the request context
63 userID, err := strconv.ParseInt(claims["sub"].(string), 10, 64)
64 if err != nil {
65 return nil, fmt.Errorf("invalid format for user id")
66 }
67
68 ctx := context.WithValue(r.Context(), "userID", userID)
69
70 return r.WithContext(ctx), nil
71}
72
73// Define a middleware function to verify the JWT token and set the user in the request context
74func jwtMiddleware(next http.Handler) http.Handler {
75 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
76 newReq, err := readAuthHeaders(r)
77
78 if err != nil {
79 http.Error(w, "Unauthorized", http.StatusUnauthorized)
80 return
81 }
82
83 next.ServeHTTP(w, newReq)
84 })
85}
86
87func getUserId(r *http.Request) int64 {
88 return r.Context().Value("userID").(int64)
89}
90
91// // Define a handler function that requires a valid JWT token to be present
92// func myHandler(w http.ResponseWriter, r *http.Request) {
93// // Get the userID from the request context
94// userID := r.Context().Value("userID").(string)
95//
96// // Do something with the userID
97// // ...
98// }