feat: add validator for jwt
This commit is contained in:
@@ -382,6 +382,36 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"/session": {
|
||||||
|
"get": {
|
||||||
|
"description": "Returns user session data",
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"auth"
|
||||||
|
],
|
||||||
|
"summary": "Get user session",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Session data",
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Unauthorized",
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
|
|||||||
@@ -371,6 +371,36 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"/session": {
|
||||||
|
"get": {
|
||||||
|
"description": "Returns user session data",
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"auth"
|
||||||
|
],
|
||||||
|
"summary": "Get user session",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Session data",
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Unauthorized",
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
|
|||||||
@@ -272,6 +272,26 @@ paths:
|
|||||||
summary: Update post
|
summary: Update post
|
||||||
tags:
|
tags:
|
||||||
- posts
|
- posts
|
||||||
|
/session:
|
||||||
|
get:
|
||||||
|
description: Returns user session data
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: Session data
|
||||||
|
schema:
|
||||||
|
additionalProperties: true
|
||||||
|
type: object
|
||||||
|
"401":
|
||||||
|
description: Unauthorized
|
||||||
|
schema:
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
summary: Get user session
|
||||||
|
tags:
|
||||||
|
- auth
|
||||||
securityDefinitions:
|
securityDefinitions:
|
||||||
Bearer:
|
Bearer:
|
||||||
description: Type "Bearer" followed by a space and the JWT token.
|
description: Type "Bearer" followed by a space and the JWT token.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"gitea.d3m0k1d.ru/d3m0k1d/d3m0k1d.ru/backend/internal/storage"
|
"gitea.d3m0k1d.ru/d3m0k1d/d3m0k1d.ru/backend/internal/storage"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -18,6 +19,9 @@ func GenerateJWT(user storage.User) (string, error) {
|
|||||||
"email": user.Email,
|
"email": user.Email,
|
||||||
"login": user.GithubLogin,
|
"login": user.GithubLogin,
|
||||||
"github_id": user.GithubID,
|
"github_id": user.GithubID,
|
||||||
|
"avatar_url": user.AvatarURL,
|
||||||
|
"exp": time.Now().Add(30 * 24 * time.Hour).Unix(), // 30 дней
|
||||||
|
"iat": time.Now().Unix(),
|
||||||
})
|
})
|
||||||
tokenString, err := token.SignedString(jwtSecret)
|
tokenString, err := token.SignedString(jwtSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -113,3 +117,58 @@ func RequireAdmin() gin.HandlerFunc {
|
|||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ValidateJWT(tokenString string) (*storage.User, error) {
|
||||||
|
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
|
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||||
|
}
|
||||||
|
return jwtSecret, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil || !token.Valid {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
claims, ok := token.Claims.(jwt.MapClaims)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("invalid claims")
|
||||||
|
}
|
||||||
|
|
||||||
|
if exp, ok := claims["exp"].(float64); ok {
|
||||||
|
if time.Now().Unix() > int64(exp) {
|
||||||
|
return nil, fmt.Errorf("token expired")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
idFloat, ok := claims["id"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("invalid id in token")
|
||||||
|
}
|
||||||
|
|
||||||
|
githubIDFloat, ok := claims["github_id"].(float64)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("invalid github_id in token")
|
||||||
|
}
|
||||||
|
|
||||||
|
login, ok := claims["login"].(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("invalid login in token")
|
||||||
|
}
|
||||||
|
|
||||||
|
email, ok := claims["email"].(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("invalid email in token")
|
||||||
|
}
|
||||||
|
|
||||||
|
avatarURL, _ := claims["avatar_url"].(string)
|
||||||
|
|
||||||
|
user := &storage.User{
|
||||||
|
ID: int(idFloat),
|
||||||
|
GithubID: int(githubIDFloat),
|
||||||
|
GithubLogin: login,
|
||||||
|
Email: email,
|
||||||
|
AvatarURL: avatarURL,
|
||||||
|
}
|
||||||
|
|
||||||
|
return user, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -147,8 +147,45 @@ func (h *AuthHandlers) CallbackGithub(c *gin.Context) {
|
|||||||
|
|
||||||
h.logger.Info("Authentication successful for user: " + ghUser.GithubLogin)
|
h.logger.Info("Authentication successful for user: " + ghUser.GithubLogin)
|
||||||
|
|
||||||
|
c.SetCookie(
|
||||||
|
"auth_token",
|
||||||
|
jwtToken,
|
||||||
|
3600*24*30,
|
||||||
|
"/",
|
||||||
|
"",
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
|
||||||
|
c.Redirect(302, "https://d3m0k1d.ru")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSession godoc
|
||||||
|
// @Summary Get user session
|
||||||
|
// @Description Returns user session data
|
||||||
|
// @Tags auth
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200 {object} map[string]interface{} "Session data"
|
||||||
|
// @Failure 401 {object} map[string]string "Unauthorized"
|
||||||
|
// @Router /session [get]
|
||||||
|
func (h *AuthHandlers) GetSession(c *gin.Context) {
|
||||||
|
tokenString, err := c.Cookie("auth_token")
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(401, gin.H{"error": "unauthorized"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := auth.ValidateJWT(tokenString)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(401, gin.H{"error": "invalid token"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
c.JSON(200, gin.H{
|
c.JSON(200, gin.H{
|
||||||
"token": jwtToken,
|
"user": gin.H{
|
||||||
"user": ghUser,
|
"name": user.GithubLogin,
|
||||||
|
"email": user.Email,
|
||||||
|
"avatar": user.AvatarURL,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ func Register(router *gin.Engine, db *sql.DB) {
|
|||||||
v1 := router.Group("api/v1")
|
v1 := router.Group("api/v1")
|
||||||
v1.GET("/callback/github", handler_auth.CallbackGithub)
|
v1.GET("/callback/github", handler_auth.CallbackGithub)
|
||||||
v1.GET("/auth/github", handler_auth.LoginGithub)
|
v1.GET("/auth/github", handler_auth.LoginGithub)
|
||||||
|
v1.GET("/session", auth.JWTMiddleware(), handler_auth.GetSession)
|
||||||
posts := v1.Group("posts")
|
posts := v1.Group("posts")
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user