From ec4199e53f98daa9cabca35794863a8f1a0a4495 Mon Sep 17 00:00:00 2001 From: AK Katung <88624598+AKKatung159@users.noreply.github.com> Date: Thu, 11 Jan 2024 16:53:32 +0700 Subject: [PATCH] feat: gen staff token (#32) * feat: gen staff token * fix: change gen-staff-token to .sh * feat: add faculty-wide --- .env.example | 2 ++ cfgldr/cfgldr.go | 14 ++++++++ go.mod | 1 + go.sum | 2 ++ internal/middleware/auth.middleware.go | 24 ++++++++++++-- tools/gen-staff-token.sh | 46 ++++++++++++++++++++++++++ 6 files changed, 86 insertions(+), 3 deletions(-) create mode 100755 tools/gen-staff-token.sh diff --git a/.env.example b/.env.example index 060bc43..a009b33 100644 --- a/.env.example +++ b/.env.example @@ -14,3 +14,5 @@ OAUTH2_REDIRECT_URL=http://localhost:3000/auth/callback OAUTH2_SCOPES=openid,email CORS_ORIGINS=https://openhouse.chula.ac.th,https://isd-sgcu.in.th,https://openhouse.isd-sgcu.in.th + +JWT_SECRET_KEY=secret \ No newline at end of file diff --git a/cfgldr/cfgldr.go b/cfgldr/cfgldr.go index d8edb53..dd5fbd9 100644 --- a/cfgldr/cfgldr.go +++ b/cfgldr/cfgldr.go @@ -9,6 +9,7 @@ type Config struct { AppConfig AppConfig RedisConfig RedisConfig OAuth2Config OAuth2Config + JWTConfig JWTConfig CorsConfig CorsConfig } @@ -34,6 +35,9 @@ type OAuth2Config struct { ClientSecret string `mapstructure:"CLIENT_SECRET"` Scopes []string `mapstructure:"SCOPES"` } +type JWTConfig struct { + SecretKey string `mapstructure:"SECRET_KEY"` +} type CorsConfig struct { AllowOrigins string `mapstructure:"ORIGINS"` @@ -76,6 +80,15 @@ func LoadConfig() (*Config, error) { return nil, err } + jwtCfgLdr := viper.New() + jwtCfgLdr.SetEnvPrefix("JWT") + jwtCfgLdr.AutomaticEnv() + jwtCfgLdr.AllowEmptyEnv(false) + jwtConfig := JWTConfig{} + if err := jwtCfgLdr.Unmarshal(&jwtConfig); err != nil { + return nil, err + } + corsConfigLdr := viper.New() corsConfigLdr.SetEnvPrefix("CORS") corsConfigLdr.AutomaticEnv() @@ -90,6 +103,7 @@ func LoadConfig() (*Config, error) { AppConfig: appConfig, RedisConfig: redisConfig, OAuth2Config: oauth2Config, + JWTConfig: jwtConfig, CorsConfig: corsConfig, }, nil } diff --git a/go.mod b/go.mod index d60cde1..44b7b86 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,7 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.1 // indirect + github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect diff --git a/go.sum b/go.sum index c73ebac..0276ebf 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= diff --git a/internal/middleware/auth.middleware.go b/internal/middleware/auth.middleware.go index f47dc7a..f4f1090 100644 --- a/internal/middleware/auth.middleware.go +++ b/internal/middleware/auth.middleware.go @@ -3,6 +3,7 @@ package middleware import ( "strings" + "github.com/dgrijalva/jwt-go" "github.com/gin-gonic/gin" "github.com/isd-sgcu/oph66-backend/apperror" "github.com/isd-sgcu/oph66-backend/cfgldr" @@ -31,9 +32,26 @@ func NewAuthMiddleware(userRepo auth.Repository, cfg *cfgldr.Config) AuthMiddlew token, err := idtoken.Validate(c, tokenString, cfg.OAuth2Config.ClientId) if err != nil { - utils.ReturnError(c, apperror.InvalidToken) - c.Abort() - return + SecretKey := cfg.JWTConfig.SecretKey + staffToken, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { + return []byte(SecretKey), nil + }) + if err != nil { + utils.ReturnError(c, apperror.InvalidToken) + c.Abort() + return + } + if staffToken.Valid && staffToken.Claims.(jwt.MapClaims)["role"] == "staff" { + c.Set("faculty", staffToken.Claims.(jwt.MapClaims)["faculty"]) + c.Set("department", staffToken.Claims.(jwt.MapClaims)["department"]) + c.Set("faculty-wide", staffToken.Claims.(jwt.MapClaims)["faculty-wide"]) + c.Next() + return + } else { + utils.ReturnError(c, apperror.InvalidToken) + c.Abort() + return + } } if email, ok := token.Claims["email"].(string); ok { diff --git a/tools/gen-staff-token.sh b/tools/gen-staff-token.sh new file mode 100755 index 0000000..35f4de2 --- /dev/null +++ b/tools/gen-staff-token.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +## Usage: +## ./tools/gen-staff-token.sh +## ./tools/gen-staff-token.sh 23 0 true + +if [ -f .env ]; then + source .env +else + echo "Error: .env file not found!" + exit 1 +fi + +if [ "$#" -ne 3 ]; then + echo "Usage: $0 " + exit 1 +fi + +faculty=$1 +department=$2 +faculty_wide=$3 + +if [ -z "$faculty" ] || [ -z "$department" ]; then + echo "Invalid input. Faculty and Department cannot be empty." + exit 1 +fi + +if [ -z "$JWT_SECRET_KEY" ]; then + echo "Error: JWT_SECRET_KEY is not set in .env file!" + exit 1 +fi + +SECRET_KEY="$JWT_SECRET_KEY" + +HEADER="{\"alg\":\"HS256\",\"typ\":\"JWT\"}" + +PAYLOAD="{\"role\":\"staff\",\"faculty\":$faculty,\"department\":$department,\"faculty-wide\":$faculty_wide}" + +HEADER_ENCODED=$(echo -n "$HEADER" | base64 | tr -d '=' | tr '/+' '_-') +PAYLOAD_ENCODED=$(echo -n "$PAYLOAD" | base64 | tr -d '=' | tr '/+' '_-') + +TOKEN="$HEADER_ENCODED.$PAYLOAD_ENCODED" + +SIGNATURE=$(echo -n "$TOKEN" | openssl dgst -sha256 -hmac "$SECRET_KEY" -binary | base64 | tr -d '=' | tr '/+' '_-') + +echo "Token: $TOKEN.$SIGNATURE"