Skip to content

Commit 7445f8c

Browse files
committed
Add JWT Login feature
1 parent 2dc1d99 commit 7445f8c

File tree

3 files changed

+89
-0
lines changed

3 files changed

+89
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package controllers
2+
3+
import (
4+
"net/http"
5+
6+
"authentication-service/models"
7+
"authentication-service/services"
8+
"authentication-service/utils"
9+
"github.com/golang-jwt/jwt"
10+
"github.com/gin-gonic/gin"
11+
)
12+
13+
// Handles JWT token requests
14+
func TokenLogin(c *gin.Context) {
15+
// Get the token from the request query string
16+
var tokenString = c.Query("token")
17+
if tokenString == "" {
18+
c.JSON(http.StatusBadRequest, gin.H{"error": "Token not provided"})
19+
return
20+
}
21+
22+
// Verify the token using the utility function
23+
token, err := utils.VerifyToken(tokenString)
24+
if err != nil {
25+
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid or expired token"})
26+
return
27+
}
28+
29+
// Extract claims from the token (e.g., the user's email)
30+
claims, ok := token.Claims.(jwt.MapClaims)
31+
if !ok || !token.Valid {
32+
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token claims"})
33+
return
34+
}
35+
36+
// Retrieve user details based on the email claim
37+
email, ok := claims["email"].(string)
38+
if !ok {
39+
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token claims"})
40+
return
41+
}
42+
43+
var user models.UserModel
44+
err = services.GetUserByEmail(c.Request.Context(), email, &user)
45+
if err != nil {
46+
c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
47+
return
48+
}
49+
50+
// Return the user's account details
51+
c.JSON(http.StatusOK, gin.H{
52+
"email": user.Email,
53+
"name": user.Name,
54+
})
55+
}

authentication-service/routes/routes.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ import (
88
func InitialiseRoutes(r *gin.Engine) {
99
r.POST("/register", controllers.RegisterUser)
1010
r.POST("/login", controllers.LoginUser)
11+
r.GET("/jwt", controllers.TokenLogin)
1112
}

authentication-service/utils/jwt_utils.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package utils
33
import (
44
"os"
55
"log"
6+
"errors"
67
"time"
78

89
"authentication-service/models"
@@ -28,3 +29,35 @@ func GenerateToken(user models.UserModel) (string, error) {
2829
// Sign the token with the secret key
2930
return token.SignedString(jwtSecret)
3031
}
32+
33+
func VerifyToken(tokenString string) (*jwt.Token, error) {
34+
err := godotenv.Load(".env.dev")
35+
if err != nil {
36+
return nil, errors.New("error loading .env file")
37+
}
38+
var jwtSecret = []byte(os.Getenv("JWT_SECRET_KEY"))
39+
40+
// Parse the token
41+
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
42+
// Validate the algorithm
43+
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
44+
return nil, errors.New("unexpected signing method")
45+
}
46+
return jwtSecret, nil
47+
})
48+
49+
if err != nil {
50+
return nil, err
51+
}
52+
53+
// Verify if token is valid and not expired
54+
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
55+
expiry := int64(claims["exp"].(float64))
56+
if expiry < time.Now().Unix() {
57+
return nil, errors.New("token has expired")
58+
}
59+
return token, nil
60+
}
61+
62+
return nil, errors.New("invalid token")
63+
}

0 commit comments

Comments
 (0)