From e5774af935bddf2f70e00206a390aca8fc6245f9 Mon Sep 17 00:00:00 2001 From: NitiwatOwen Date: Sat, 23 Dec 2023 15:54:56 +0700 Subject: [PATCH 01/11] feat: create jwtStrategyMock --- src/mocks/strategy/strategy.mock.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/mocks/strategy/strategy.mock.go diff --git a/src/mocks/strategy/strategy.mock.go b/src/mocks/strategy/strategy.mock.go new file mode 100644 index 0000000..fe71def --- /dev/null +++ b/src/mocks/strategy/strategy.mock.go @@ -0,0 +1,18 @@ +package strategy + +import ( + "github.com/golang-jwt/jwt/v4" + "github.com/stretchr/testify/mock" +) + +type JwtStrategyMock struct { + mock.Mock +} + +func (m *JwtStrategyMock) AuthDecode(token *jwt.Token) (interface{}, error) { + args := m.Called(token) + if args.Get(0) != nil { + return args.Get(0), nil + } + return nil, args.Error(1) +} From ff0b3357f83738e0ea47941191cd2fdc3a0f8be0 Mon Sep 17 00:00:00 2001 From: NitiwatOwen Date: Sat, 23 Dec 2023 15:55:07 +0700 Subject: [PATCH 02/11] feat: create JwtUtil --- src/internal/utils/jwt.utils.go | 26 ++++++++++++++++++++++++++ src/mocks/utils/jwt.mock.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/internal/utils/jwt.utils.go create mode 100644 src/mocks/utils/jwt.mock.go diff --git a/src/internal/utils/jwt.utils.go b/src/internal/utils/jwt.utils.go new file mode 100644 index 0000000..9f22ef7 --- /dev/null +++ b/src/internal/utils/jwt.utils.go @@ -0,0 +1,26 @@ +package utils + +import ( + "github.com/golang-jwt/jwt/v4" + "time" +) + +type IJwtUtil interface { + GenerateJwtToken(method jwt.SigningMethod, payloads jwt.Claims) *jwt.Token + GetNumericDate(time time.Time) *jwt.NumericDate + SignedTokenString(token *jwt.Token, secret string) (string, error) +} + +type JwtUtil struct{} + +func (u *JwtUtil) GenerateJwtToken(method jwt.SigningMethod, payloads jwt.Claims) *jwt.Token { + return jwt.NewWithClaims(method, payloads) +} + +func (u *JwtUtil) GetNumericDate(time time.Time) *jwt.NumericDate { + return jwt.NewNumericDate(time) +} + +func (u *JwtUtil) SignedTokenString(token *jwt.Token, secret string) (string, error) { + return token.SignedString([]byte(secret)) +} diff --git a/src/mocks/utils/jwt.mock.go b/src/mocks/utils/jwt.mock.go new file mode 100644 index 0000000..a96a96f --- /dev/null +++ b/src/mocks/utils/jwt.mock.go @@ -0,0 +1,30 @@ +package utils + +import ( + "github.com/golang-jwt/jwt/v4" + "github.com/stretchr/testify/mock" + "time" +) + +type JwtUtilMock struct { + mock.Mock +} + +func (m *JwtUtilMock) GenerateJwtToken(method jwt.SigningMethod, payloads jwt.Claims) *jwt.Token { + args := m.Called(method, payloads) + return args.Get(0).(*jwt.Token) +} + +func (m *JwtUtilMock) GetNumericDate(time time.Time) *jwt.NumericDate { + args := m.Called() + return args.Get(0).(*jwt.NumericDate) +} + +func (m *JwtUtilMock) SignedTokenString(token *jwt.Token, secret string) (string, error) { + args := m.Called(token, secret) + if args.Get(0) != nil { + return args.Get(0).(string), nil + } + + return "", args.Error(1) +} From d47814f10b4b0358e0ef4eac2f98f11810c6fd4d Mon Sep 17 00:00:00 2001 From: NitiwatOwen Date: Sat, 23 Dec 2023 16:02:34 +0700 Subject: [PATCH 03/11] feat: implement SignAuth method --- src/internal/domain/dto/token/token.dto.go | 10 +- .../repository/user/user.repository_test.go | 2 +- src/internal/service/jwt/jwt.service.go | 28 ++++- src/internal/service/jwt/jwt.service_test.go | 104 +++++++++++++++++- src/mocks/utils/jwt.mock.go | 2 +- src/pkg/service/jwt/jwt.service.go | 5 +- 6 files changed, 140 insertions(+), 11 deletions(-) diff --git a/src/internal/domain/dto/token/token.dto.go b/src/internal/domain/dto/token/token.dto.go index bee6c8f..a8212da 100644 --- a/src/internal/domain/dto/token/token.dto.go +++ b/src/internal/domain/dto/token/token.dto.go @@ -1,8 +1,16 @@ package token -import "github.com/isd-sgcu/johnjud-auth/src/internal/constant" +import ( + "github.com/golang-jwt/jwt/v4" + "github.com/isd-sgcu/johnjud-auth/src/internal/constant" +) type UserCredential struct { UserId string `json:"user_id"` Role constant.Role `json:"role"` } + +type AuthPayload struct { + jwt.RegisteredClaims + UserId string `json:"user_id"` +} diff --git a/src/internal/repository/user/user.repository_test.go b/src/internal/repository/user/user.repository_test.go index 3f96f93..b462b9c 100644 --- a/src/internal/repository/user/user.repository_test.go +++ b/src/internal/repository/user/user.repository_test.go @@ -33,7 +33,7 @@ func (t *UserRepositoryTest) SetupTest() { err = db.AutoMigrate(&model.User{}) assert.NoError(t.T(), err) - userRepository := &repositoryImpl{Db: db} + userRepository := NewRepository(db) initialUser := &model.User{ Email: faker.Email(), diff --git a/src/internal/service/jwt/jwt.service.go b/src/internal/service/jwt/jwt.service.go index ea77094..cca52eb 100644 --- a/src/internal/service/jwt/jwt.service.go +++ b/src/internal/service/jwt/jwt.service.go @@ -1,22 +1,44 @@ package jwt import ( + "fmt" _jwt "github.com/golang-jwt/jwt/v4" "github.com/isd-sgcu/johnjud-auth/src/config" + tokenDto "github.com/isd-sgcu/johnjud-auth/src/internal/domain/dto/token" + "github.com/isd-sgcu/johnjud-auth/src/internal/utils" "github.com/isd-sgcu/johnjud-auth/src/pkg/strategy" + "github.com/pkg/errors" + "time" ) type serviceImpl struct { config config.Jwt strategy strategy.JwtStrategy + jwtUtil utils.IJwtUtil } -func NewService(config config.Jwt, strategy strategy.JwtStrategy) *serviceImpl { - return &serviceImpl{config: config, strategy: strategy} +func NewService(config config.Jwt, strategy strategy.JwtStrategy, jwtUtil utils.IJwtUtil) *serviceImpl { + return &serviceImpl{config: config, strategy: strategy, jwtUtil: jwtUtil} } func (s *serviceImpl) SignAuth(userId string) (string, error) { - return "", nil + payloads := tokenDto.AuthPayload{ + RegisteredClaims: _jwt.RegisteredClaims{ + Issuer: s.config.Issuer, + ExpiresAt: s.jwtUtil.GetNumericDate(time.Now().Add(time.Second * time.Duration(s.config.ExpiresIn))), + IssuedAt: s.jwtUtil.GetNumericDate(time.Now()), + }, + UserId: userId, + } + + token := s.jwtUtil.GenerateJwtToken(_jwt.SigningMethodHS256, payloads) + + tokenStr, err := s.jwtUtil.SignedTokenString(token, s.config.Secret) + if err != nil { + return "", errors.New(fmt.Sprintf("Error while signing the token due to: %s", err.Error())) + } + + return tokenStr, nil } func (s *serviceImpl) VerifyAuth(token string) (*_jwt.Token, error) { diff --git a/src/internal/service/jwt/jwt.service_test.go b/src/internal/service/jwt/jwt.service_test.go index 3b00a66..fdc1ba8 100644 --- a/src/internal/service/jwt/jwt.service_test.go +++ b/src/internal/service/jwt/jwt.service_test.go @@ -1,16 +1,23 @@ package jwt import ( + "fmt" + "github.com/go-faker/faker/v4" + "github.com/golang-jwt/jwt/v4" "github.com/isd-sgcu/johnjud-auth/src/config" - "github.com/isd-sgcu/johnjud-auth/src/pkg/strategy" + tokenDto "github.com/isd-sgcu/johnjud-auth/src/internal/domain/dto/token" + "github.com/isd-sgcu/johnjud-auth/src/mocks/strategy" + "github.com/isd-sgcu/johnjud-auth/src/mocks/utils" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/suite" "testing" + "time" ) type JwtServiceTest struct { suite.Suite - config config.Jwt - strategy *strategy.JwtStrategy + config config.Jwt } func TestJwtService(t *testing.T) { @@ -18,5 +25,96 @@ func TestJwtService(t *testing.T) { } func (t *JwtServiceTest) SetupTest() { + config := config.Jwt{ + Secret: "testSecret", + ExpiresIn: 3600, + Issuer: "testIssuer", + } + + t.config = config +} + +func (t *JwtServiceTest) TestSignAuthSuccess() { + userId := faker.UUIDDigit() + expected := "signedTokenStr" + + numericDate := jwt.NewNumericDate(time.Now()) + payloads := tokenDto.AuthPayload{ + RegisteredClaims: jwt.RegisteredClaims{ + Issuer: t.config.Issuer, + ExpiresAt: numericDate, + IssuedAt: numericDate, + }, + UserId: userId, + } + token := &jwt.Token{ + Header: map[string]interface{}{ + "typ": "JWT", + "alg": jwt.SigningMethodHS256.Alg(), + }, + Method: jwt.SigningMethodHS256, + Claims: payloads, + } + + jwtStrategy := strategy.JwtStrategyMock{} + jwtUtil := utils.JwtUtilMock{} + + jwtUtil.On("GetNumericDate").Return(numericDate) + jwtUtil.On("GenerateJwtToken", jwt.SigningMethodHS256, payloads).Return(token) + jwtUtil.On("SignedTokenString", token, t.config.Secret).Return(expected, nil) + + jwtSvc := NewService(t.config, &jwtStrategy, &jwtUtil) + actual, err := jwtSvc.SignAuth(userId) + + assert.Nil(t.T(), err) + assert.Equal(t.T(), expected, actual) +} + +func (t *JwtServiceTest) TestSignAuthSignedStringFailed() { + userId := faker.UUIDDigit() + signedTokenError := errors.New("Some Error") + expected := errors.New(fmt.Sprintf("Error while signing the token due to: %s", signedTokenError.Error())) + + numericDate := jwt.NewNumericDate(time.Now()) + payloads := tokenDto.AuthPayload{ + RegisteredClaims: jwt.RegisteredClaims{ + Issuer: t.config.Issuer, + ExpiresAt: numericDate, + IssuedAt: numericDate, + }, + UserId: userId, + } + token := &jwt.Token{ + Header: map[string]interface{}{ + "typ": "JWT", + "alg": jwt.SigningMethodHS256.Alg(), + }, + Method: jwt.SigningMethodHS256, + Claims: payloads, + } + + jwtStrategy := strategy.JwtStrategyMock{} + jwtUtil := utils.JwtUtilMock{} + + jwtUtil.On("GetNumericDate").Return(numericDate) + jwtUtil.On("GenerateJwtToken", jwt.SigningMethodHS256, payloads).Return(token) + jwtUtil.On("SignedTokenString", token, t.config.Secret).Return("", signedTokenError) + + jwtSvc := NewService(t.config, &jwtStrategy, &jwtUtil) + actual, err := jwtSvc.SignAuth(userId) + + assert.Equal(t.T(), "", actual) + assert.Equal(t.T(), expected.Error(), err.Error()) +} + +func (t *JwtServiceTest) TestVerifyAuthSuccess() { + +} + +func (t *JwtServiceTest) TestVerifyAuthFailed() { + +} + +func (t *JwtServiceTest) TestGetConfigSuccess() { } diff --git a/src/mocks/utils/jwt.mock.go b/src/mocks/utils/jwt.mock.go index a96a96f..0ce04c9 100644 --- a/src/mocks/utils/jwt.mock.go +++ b/src/mocks/utils/jwt.mock.go @@ -22,7 +22,7 @@ func (m *JwtUtilMock) GetNumericDate(time time.Time) *jwt.NumericDate { func (m *JwtUtilMock) SignedTokenString(token *jwt.Token, secret string) (string, error) { args := m.Called(token, secret) - if args.Get(0) != nil { + if args.Get(0) != "" { return args.Get(0).(string), nil } diff --git a/src/pkg/service/jwt/jwt.service.go b/src/pkg/service/jwt/jwt.service.go index db66000..df33d01 100644 --- a/src/pkg/service/jwt/jwt.service.go +++ b/src/pkg/service/jwt/jwt.service.go @@ -4,6 +4,7 @@ import ( _jwt "github.com/golang-jwt/jwt/v4" "github.com/isd-sgcu/johnjud-auth/src/config" "github.com/isd-sgcu/johnjud-auth/src/internal/service/jwt" + "github.com/isd-sgcu/johnjud-auth/src/internal/utils" "github.com/isd-sgcu/johnjud-auth/src/pkg/strategy" ) @@ -13,6 +14,6 @@ type Service interface { GetConfig() *config.Jwt } -func NewService(config config.Jwt, strategy strategy.JwtStrategy) Service { - return jwt.NewService(config, strategy) +func NewService(config config.Jwt, strategy strategy.JwtStrategy, jwtUtil utils.IJwtUtil) Service { + return jwt.NewService(config, strategy, jwtUtil) } From f7bf3b2fddacd296d8370fd6ac406c66959aacef Mon Sep 17 00:00:00 2001 From: NitiwatOwen Date: Sat, 23 Dec 2023 16:33:53 +0700 Subject: [PATCH 04/11] feat: implement VerifyAuth method --- src/internal/service/jwt/jwt.service.go | 2 +- src/internal/service/jwt/jwt.service_test.go | 84 ++++++++++++-------- src/internal/utils/jwt.utils.go | 5 ++ src/mocks/utils/jwt.mock.go | 11 ++- 4 files changed, 66 insertions(+), 36 deletions(-) diff --git a/src/internal/service/jwt/jwt.service.go b/src/internal/service/jwt/jwt.service.go index cca52eb..a20fbae 100644 --- a/src/internal/service/jwt/jwt.service.go +++ b/src/internal/service/jwt/jwt.service.go @@ -42,7 +42,7 @@ func (s *serviceImpl) SignAuth(userId string) (string, error) { } func (s *serviceImpl) VerifyAuth(token string) (*_jwt.Token, error) { - return nil, nil + return s.jwtUtil.ParseToken(token, s.strategy.AuthDecode) } func (s *serviceImpl) GetConfig() *config.Jwt { diff --git a/src/internal/service/jwt/jwt.service_test.go b/src/internal/service/jwt/jwt.service_test.go index fdc1ba8..1e54a47 100644 --- a/src/internal/service/jwt/jwt.service_test.go +++ b/src/internal/service/jwt/jwt.service_test.go @@ -10,6 +10,7 @@ import ( "github.com/isd-sgcu/johnjud-auth/src/mocks/utils" "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" "testing" "time" @@ -17,7 +18,11 @@ import ( type JwtServiceTest struct { suite.Suite - config config.Jwt + config config.Jwt + userId string + numericDate *jwt.NumericDate + payloads tokenDto.AuthPayload + token *jwt.Token } func TestJwtService(t *testing.T) { @@ -31,14 +36,9 @@ func (t *JwtServiceTest) SetupTest() { Issuer: "testIssuer", } - t.config = config -} - -func (t *JwtServiceTest) TestSignAuthSuccess() { userId := faker.UUIDDigit() - expected := "signedTokenStr" - numericDate := jwt.NewNumericDate(time.Now()) + payloads := tokenDto.AuthPayload{ RegisteredClaims: jwt.RegisteredClaims{ Issuer: t.config.Issuer, @@ -47,6 +47,7 @@ func (t *JwtServiceTest) TestSignAuthSuccess() { }, UserId: userId, } + token := &jwt.Token{ Header: map[string]interface{}{ "typ": "JWT", @@ -56,63 +57,78 @@ func (t *JwtServiceTest) TestSignAuthSuccess() { Claims: payloads, } + t.config = config + t.userId = userId + t.numericDate = numericDate + t.payloads = payloads + t.token = token +} + +func (t *JwtServiceTest) TestSignAuthSuccess() { + expected := "signedTokenStr" + jwtStrategy := strategy.JwtStrategyMock{} jwtUtil := utils.JwtUtilMock{} - jwtUtil.On("GetNumericDate").Return(numericDate) - jwtUtil.On("GenerateJwtToken", jwt.SigningMethodHS256, payloads).Return(token) - jwtUtil.On("SignedTokenString", token, t.config.Secret).Return(expected, nil) + jwtUtil.On("GetNumericDate", mock.AnythingOfType("time.Time")).Return(t.numericDate) + jwtUtil.On("GenerateJwtToken", jwt.SigningMethodHS256, t.payloads).Return(t.token) + jwtUtil.On("SignedTokenString", t.token, t.config.Secret).Return(expected, nil) jwtSvc := NewService(t.config, &jwtStrategy, &jwtUtil) - actual, err := jwtSvc.SignAuth(userId) + actual, err := jwtSvc.SignAuth(t.userId) assert.Nil(t.T(), err) assert.Equal(t.T(), expected, actual) } func (t *JwtServiceTest) TestSignAuthSignedStringFailed() { - userId := faker.UUIDDigit() signedTokenError := errors.New("Some Error") expected := errors.New(fmt.Sprintf("Error while signing the token due to: %s", signedTokenError.Error())) - numericDate := jwt.NewNumericDate(time.Now()) - payloads := tokenDto.AuthPayload{ - RegisteredClaims: jwt.RegisteredClaims{ - Issuer: t.config.Issuer, - ExpiresAt: numericDate, - IssuedAt: numericDate, - }, - UserId: userId, - } - token := &jwt.Token{ - Header: map[string]interface{}{ - "typ": "JWT", - "alg": jwt.SigningMethodHS256.Alg(), - }, - Method: jwt.SigningMethodHS256, - Claims: payloads, - } - jwtStrategy := strategy.JwtStrategyMock{} jwtUtil := utils.JwtUtilMock{} - jwtUtil.On("GetNumericDate").Return(numericDate) - jwtUtil.On("GenerateJwtToken", jwt.SigningMethodHS256, payloads).Return(token) - jwtUtil.On("SignedTokenString", token, t.config.Secret).Return("", signedTokenError) + jwtUtil.On("GetNumericDate", mock.AnythingOfType("time.Time")).Return(t.numericDate) + jwtUtil.On("GenerateJwtToken", jwt.SigningMethodHS256, t.payloads).Return(t.token) + jwtUtil.On("SignedTokenString", t.token, t.config.Secret).Return("", signedTokenError) jwtSvc := NewService(t.config, &jwtStrategy, &jwtUtil) - actual, err := jwtSvc.SignAuth(userId) + actual, err := jwtSvc.SignAuth(t.userId) assert.Equal(t.T(), "", actual) assert.Equal(t.T(), expected.Error(), err.Error()) } func (t *JwtServiceTest) TestVerifyAuthSuccess() { + tokenStr := "validSignedToken" + expected := t.token + jwtStrategy := strategy.JwtStrategyMock{} + jwtUtil := utils.JwtUtilMock{} + + jwtUtil.On("ParseToken", tokenStr, mock.AnythingOfType("jwt.Keyfunc")).Return(expected, nil) + + jwtSvc := NewService(t.config, &jwtStrategy, &jwtUtil) + actual, err := jwtSvc.VerifyAuth(tokenStr) + + assert.Nil(t.T(), err) + assert.Equal(t.T(), *expected, *actual) } func (t *JwtServiceTest) TestVerifyAuthFailed() { + tokenStr := "invalidSignedToken" + expected := errors.New("invalid token") + + jwtStrategy := strategy.JwtStrategyMock{} + jwtUtil := utils.JwtUtilMock{} + + jwtUtil.On("ParseToken", tokenStr, mock.AnythingOfType("jwt.Keyfunc")).Return(nil, expected) + + jwtSvc := NewService(t.config, &jwtStrategy, &jwtUtil) + actual, err := jwtSvc.VerifyAuth(tokenStr) + assert.Nil(t.T(), actual) + assert.Equal(t.T(), expected, err) } func (t *JwtServiceTest) TestGetConfigSuccess() { diff --git a/src/internal/utils/jwt.utils.go b/src/internal/utils/jwt.utils.go index 9f22ef7..b43d9b5 100644 --- a/src/internal/utils/jwt.utils.go +++ b/src/internal/utils/jwt.utils.go @@ -9,6 +9,7 @@ type IJwtUtil interface { GenerateJwtToken(method jwt.SigningMethod, payloads jwt.Claims) *jwt.Token GetNumericDate(time time.Time) *jwt.NumericDate SignedTokenString(token *jwt.Token, secret string) (string, error) + ParseToken(tokenStr string, keyFunc jwt.Keyfunc) (*jwt.Token, error) } type JwtUtil struct{} @@ -24,3 +25,7 @@ func (u *JwtUtil) GetNumericDate(time time.Time) *jwt.NumericDate { func (u *JwtUtil) SignedTokenString(token *jwt.Token, secret string) (string, error) { return token.SignedString([]byte(secret)) } + +func (u *JwtUtil) ParseToken(tokenStr string, keyFunc jwt.Keyfunc) (*jwt.Token, error) { + return jwt.Parse(tokenStr, keyFunc) +} diff --git a/src/mocks/utils/jwt.mock.go b/src/mocks/utils/jwt.mock.go index 0ce04c9..f2f8746 100644 --- a/src/mocks/utils/jwt.mock.go +++ b/src/mocks/utils/jwt.mock.go @@ -16,7 +16,7 @@ func (m *JwtUtilMock) GenerateJwtToken(method jwt.SigningMethod, payloads jwt.Cl } func (m *JwtUtilMock) GetNumericDate(time time.Time) *jwt.NumericDate { - args := m.Called() + args := m.Called(time) return args.Get(0).(*jwt.NumericDate) } @@ -28,3 +28,12 @@ func (m *JwtUtilMock) SignedTokenString(token *jwt.Token, secret string) (string return "", args.Error(1) } + +func (m *JwtUtilMock) ParseToken(tokenStr string, keyFunc jwt.Keyfunc) (*jwt.Token, error) { + args := m.Called(tokenStr, keyFunc) + if args.Get(0) != nil { + return args.Get(0).(*jwt.Token), nil + } + + return nil, args.Error(1) +} From 1ffaa5573c28bc082b379981da593989fd557912 Mon Sep 17 00:00:00 2001 From: NitiwatOwen Date: Sat, 23 Dec 2023 16:35:38 +0700 Subject: [PATCH 05/11] feat: implement GetConfig method --- src/internal/service/jwt/jwt.service.go | 2 +- src/internal/service/jwt/jwt.service_test.go | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/internal/service/jwt/jwt.service.go b/src/internal/service/jwt/jwt.service.go index a20fbae..df68f12 100644 --- a/src/internal/service/jwt/jwt.service.go +++ b/src/internal/service/jwt/jwt.service.go @@ -46,5 +46,5 @@ func (s *serviceImpl) VerifyAuth(token string) (*_jwt.Token, error) { } func (s *serviceImpl) GetConfig() *config.Jwt { - return nil + return &s.config } diff --git a/src/internal/service/jwt/jwt.service_test.go b/src/internal/service/jwt/jwt.service_test.go index 1e54a47..9848250 100644 --- a/src/internal/service/jwt/jwt.service_test.go +++ b/src/internal/service/jwt/jwt.service_test.go @@ -132,5 +132,13 @@ func (t *JwtServiceTest) TestVerifyAuthFailed() { } func (t *JwtServiceTest) TestGetConfigSuccess() { + expected := &t.config + jwtStrategy := strategy.JwtStrategyMock{} + jwtUtil := utils.JwtUtilMock{} + + jwtSvc := NewService(t.config, &jwtStrategy, &jwtUtil) + actual := jwtSvc.GetConfig() + + assert.Equal(t.T(), *expected, *actual) } From 0939b629604dc3c934028b6749e97765130251d3 Mon Sep 17 00:00:00 2001 From: NitiwatOwen Date: Sat, 23 Dec 2023 16:37:34 +0700 Subject: [PATCH 06/11] chore: chore --- src/internal/utils/jwt.utils.go | 14 +++++++++----- src/main.go | 4 +++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/internal/utils/jwt.utils.go b/src/internal/utils/jwt.utils.go index b43d9b5..3a4694e 100644 --- a/src/internal/utils/jwt.utils.go +++ b/src/internal/utils/jwt.utils.go @@ -12,20 +12,24 @@ type IJwtUtil interface { ParseToken(tokenStr string, keyFunc jwt.Keyfunc) (*jwt.Token, error) } -type JwtUtil struct{} +type jwtUtilImpl struct{} -func (u *JwtUtil) GenerateJwtToken(method jwt.SigningMethod, payloads jwt.Claims) *jwt.Token { +func NewJwtUtil() *jwtUtilImpl { + return &jwtUtilImpl{} +} + +func (u *jwtUtilImpl) GenerateJwtToken(method jwt.SigningMethod, payloads jwt.Claims) *jwt.Token { return jwt.NewWithClaims(method, payloads) } -func (u *JwtUtil) GetNumericDate(time time.Time) *jwt.NumericDate { +func (u *jwtUtilImpl) GetNumericDate(time time.Time) *jwt.NumericDate { return jwt.NewNumericDate(time) } -func (u *JwtUtil) SignedTokenString(token *jwt.Token, secret string) (string, error) { +func (u *jwtUtilImpl) SignedTokenString(token *jwt.Token, secret string) (string, error) { return token.SignedString([]byte(secret)) } -func (u *JwtUtil) ParseToken(tokenStr string, keyFunc jwt.Keyfunc) (*jwt.Token, error) { +func (u *jwtUtilImpl) ParseToken(tokenStr string, keyFunc jwt.Keyfunc) (*jwt.Token, error) { return jwt.Parse(tokenStr, keyFunc) } diff --git a/src/main.go b/src/main.go index c09348b..7ebd4d1 100644 --- a/src/main.go +++ b/src/main.go @@ -6,6 +6,7 @@ import ( "github.com/isd-sgcu/johnjud-auth/src/config" "github.com/isd-sgcu/johnjud-auth/src/database" "github.com/isd-sgcu/johnjud-auth/src/internal/strategy" + "github.com/isd-sgcu/johnjud-auth/src/internal/utils" "github.com/isd-sgcu/johnjud-auth/src/pkg/repository/user" "github.com/isd-sgcu/johnjud-auth/src/pkg/service/auth" "github.com/isd-sgcu/johnjud-auth/src/pkg/service/jwt" @@ -110,7 +111,8 @@ func main() { userRepo := user.NewRepository(db) jwtStrategy := strategy.NewJwtStrategy(conf.Jwt.Secret) - jwtService := jwt.NewService(conf.Jwt, jwtStrategy) + jwtUtil := utils.NewJwtUtil() + jwtService := jwt.NewService(conf.Jwt, jwtStrategy, jwtUtil) tokenService := token.NewService(jwtService) From 797d48b883b79b7402bfbc45cb12f638c96bcb19 Mon Sep 17 00:00:00 2001 From: NitiwatOwen Date: Sat, 23 Dec 2023 18:41:28 +0700 Subject: [PATCH 07/11] feat: add jwt.strategy_test.go --- src/internal/strategy/jwt.strategy_test.go | 55 ++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/internal/strategy/jwt.strategy_test.go diff --git a/src/internal/strategy/jwt.strategy_test.go b/src/internal/strategy/jwt.strategy_test.go new file mode 100644 index 0000000..865f8bb --- /dev/null +++ b/src/internal/strategy/jwt.strategy_test.go @@ -0,0 +1,55 @@ +package strategy + +import ( + "fmt" + "github.com/golang-jwt/jwt/v4" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + "testing" +) + +type JwtStrategyTest struct { + suite.Suite + secret string +} + +func TestJwtStrategy(t *testing.T) { + suite.Run(t, new(JwtStrategyTest)) +} + +func (t *JwtStrategyTest) SetupTest() { + secret := "testSecret" + + t.secret = secret +} + +func (t *JwtStrategyTest) TestAuthDecodeSuccess() { + token := &jwt.Token{ + Method: jwt.SigningMethodHS256, + } + expected := []byte(t.secret) + + jwtStrategy := NewJwtStrategy(t.secret) + actual, err := jwtStrategy.AuthDecode(token) + + assert.Nil(t.T(), err) + assert.Equal(t.T(), expected, actual) +} + +func (t *JwtStrategyTest) TestAuthDecodeFailed() { + token := &jwt.Token{ + Method: jwt.SigningMethodES256, + Header: map[string]interface{}{ + "typ": "JWT", + "alg": jwt.SigningMethodES256.Alg(), + }, + } + expected := errors.New(fmt.Sprintf("invalid token %v\n", token.Header["alg"])) + + jwtStrategy := NewJwtStrategy(t.secret) + actual, err := jwtStrategy.AuthDecode(token) + + assert.Nil(t.T(), actual) + assert.Equal(t.T(), expected.Error(), err.Error()) +} From 511d129d41a838f760b0aaa3324bbb5ffb43dbb4 Mon Sep 17 00:00:00 2001 From: NitiwatOwen Date: Sat, 23 Dec 2023 20:19:26 +0700 Subject: [PATCH 08/11] feat: add role parameter in SignAuth method --- src/internal/domain/dto/token/token.dto.go | 3 ++- src/internal/service/jwt/jwt.service.go | 4 +++- src/internal/service/jwt/jwt.service_test.go | 9 +++++++-- src/pkg/service/jwt/jwt.service.go | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/internal/domain/dto/token/token.dto.go b/src/internal/domain/dto/token/token.dto.go index a8212da..76f5962 100644 --- a/src/internal/domain/dto/token/token.dto.go +++ b/src/internal/domain/dto/token/token.dto.go @@ -12,5 +12,6 @@ type UserCredential struct { type AuthPayload struct { jwt.RegisteredClaims - UserId string `json:"user_id"` + UserId string `json:"user_id"` + Role constant.Role `json:"role"` } diff --git a/src/internal/service/jwt/jwt.service.go b/src/internal/service/jwt/jwt.service.go index df68f12..6388166 100644 --- a/src/internal/service/jwt/jwt.service.go +++ b/src/internal/service/jwt/jwt.service.go @@ -4,6 +4,7 @@ import ( "fmt" _jwt "github.com/golang-jwt/jwt/v4" "github.com/isd-sgcu/johnjud-auth/src/config" + "github.com/isd-sgcu/johnjud-auth/src/internal/constant" tokenDto "github.com/isd-sgcu/johnjud-auth/src/internal/domain/dto/token" "github.com/isd-sgcu/johnjud-auth/src/internal/utils" "github.com/isd-sgcu/johnjud-auth/src/pkg/strategy" @@ -21,7 +22,7 @@ func NewService(config config.Jwt, strategy strategy.JwtStrategy, jwtUtil utils. return &serviceImpl{config: config, strategy: strategy, jwtUtil: jwtUtil} } -func (s *serviceImpl) SignAuth(userId string) (string, error) { +func (s *serviceImpl) SignAuth(userId string, role constant.Role) (string, error) { payloads := tokenDto.AuthPayload{ RegisteredClaims: _jwt.RegisteredClaims{ Issuer: s.config.Issuer, @@ -29,6 +30,7 @@ func (s *serviceImpl) SignAuth(userId string) (string, error) { IssuedAt: s.jwtUtil.GetNumericDate(time.Now()), }, UserId: userId, + Role: role, } token := s.jwtUtil.GenerateJwtToken(_jwt.SigningMethodHS256, payloads) diff --git a/src/internal/service/jwt/jwt.service_test.go b/src/internal/service/jwt/jwt.service_test.go index 9848250..564041d 100644 --- a/src/internal/service/jwt/jwt.service_test.go +++ b/src/internal/service/jwt/jwt.service_test.go @@ -5,6 +5,7 @@ import ( "github.com/go-faker/faker/v4" "github.com/golang-jwt/jwt/v4" "github.com/isd-sgcu/johnjud-auth/src/config" + "github.com/isd-sgcu/johnjud-auth/src/internal/constant" tokenDto "github.com/isd-sgcu/johnjud-auth/src/internal/domain/dto/token" "github.com/isd-sgcu/johnjud-auth/src/mocks/strategy" "github.com/isd-sgcu/johnjud-auth/src/mocks/utils" @@ -20,6 +21,7 @@ type JwtServiceTest struct { suite.Suite config config.Jwt userId string + role constant.Role numericDate *jwt.NumericDate payloads tokenDto.AuthPayload token *jwt.Token @@ -37,6 +39,7 @@ func (t *JwtServiceTest) SetupTest() { } userId := faker.UUIDDigit() + role := constant.USER numericDate := jwt.NewNumericDate(time.Now()) payloads := tokenDto.AuthPayload{ @@ -46,6 +49,7 @@ func (t *JwtServiceTest) SetupTest() { IssuedAt: numericDate, }, UserId: userId, + Role: role, } token := &jwt.Token{ @@ -59,6 +63,7 @@ func (t *JwtServiceTest) SetupTest() { t.config = config t.userId = userId + t.role = role t.numericDate = numericDate t.payloads = payloads t.token = token @@ -75,7 +80,7 @@ func (t *JwtServiceTest) TestSignAuthSuccess() { jwtUtil.On("SignedTokenString", t.token, t.config.Secret).Return(expected, nil) jwtSvc := NewService(t.config, &jwtStrategy, &jwtUtil) - actual, err := jwtSvc.SignAuth(t.userId) + actual, err := jwtSvc.SignAuth(t.userId, t.role) assert.Nil(t.T(), err) assert.Equal(t.T(), expected, actual) @@ -93,7 +98,7 @@ func (t *JwtServiceTest) TestSignAuthSignedStringFailed() { jwtUtil.On("SignedTokenString", t.token, t.config.Secret).Return("", signedTokenError) jwtSvc := NewService(t.config, &jwtStrategy, &jwtUtil) - actual, err := jwtSvc.SignAuth(t.userId) + actual, err := jwtSvc.SignAuth(t.userId, t.role) assert.Equal(t.T(), "", actual) assert.Equal(t.T(), expected.Error(), err.Error()) diff --git a/src/pkg/service/jwt/jwt.service.go b/src/pkg/service/jwt/jwt.service.go index df33d01..b760d3c 100644 --- a/src/pkg/service/jwt/jwt.service.go +++ b/src/pkg/service/jwt/jwt.service.go @@ -9,7 +9,7 @@ import ( ) type Service interface { - SignAuth(userId string) (string, error) + SignAuth(userId string, role string) (string, error) VerifyAuth(token string) (*_jwt.Token, error) GetConfig() *config.Jwt } From fe45113760b89395a3ba0f4e3af4ff94dccbac0d Mon Sep 17 00:00:00 2001 From: NitiwatOwen Date: Sat, 23 Dec 2023 20:23:49 +0700 Subject: [PATCH 09/11] feat: update CreateCredential Signature --- src/internal/service/token/token.service.go | 2 +- src/pkg/service/token/token.service.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internal/service/token/token.service.go b/src/internal/service/token/token.service.go index 8beda60..1208f70 100644 --- a/src/internal/service/token/token.service.go +++ b/src/internal/service/token/token.service.go @@ -14,7 +14,7 @@ func NewService(jwtService jwt.Service) *serviceImpl { return &serviceImpl{jwtService: jwtService} } -func (s *serviceImpl) CreateCredential(userId string, secret string) (*authProto.Credential, error) { +func (s *serviceImpl) CreateCredential(userId string, role string) (*authProto.Credential, error) { return nil, nil } diff --git a/src/pkg/service/token/token.service.go b/src/pkg/service/token/token.service.go index a212cd7..eaf4d7f 100644 --- a/src/pkg/service/token/token.service.go +++ b/src/pkg/service/token/token.service.go @@ -8,7 +8,7 @@ import ( ) type Service interface { - CreateCredential(userId string, secret string) (*authProto.Credential, error) + CreateCredential(userId string, role string) (*authProto.Credential, error) Validate(token string) (*tokenDto.UserCredential, error) } From 443eb0eedf752e0f276f67aed7104b472b2a8f17 Mon Sep 17 00:00:00 2001 From: NitiwatOwen Date: Sat, 23 Dec 2023 20:24:26 +0700 Subject: [PATCH 10/11] fix: SignAuth signature --- src/pkg/service/jwt/jwt.service.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pkg/service/jwt/jwt.service.go b/src/pkg/service/jwt/jwt.service.go index b760d3c..35314d9 100644 --- a/src/pkg/service/jwt/jwt.service.go +++ b/src/pkg/service/jwt/jwt.service.go @@ -3,13 +3,14 @@ package jwt import ( _jwt "github.com/golang-jwt/jwt/v4" "github.com/isd-sgcu/johnjud-auth/src/config" + "github.com/isd-sgcu/johnjud-auth/src/internal/constant" "github.com/isd-sgcu/johnjud-auth/src/internal/service/jwt" "github.com/isd-sgcu/johnjud-auth/src/internal/utils" "github.com/isd-sgcu/johnjud-auth/src/pkg/strategy" ) type Service interface { - SignAuth(userId string, role string) (string, error) + SignAuth(userId string, role constant.Role) (string, error) VerifyAuth(token string) (*_jwt.Token, error) GetConfig() *config.Jwt } From 7f7df9234e1b2d7aa603b537fe421422f9c8e9e2 Mon Sep 17 00:00:00 2001 From: NitiwatOwen Date: Sat, 23 Dec 2023 20:25:46 +0700 Subject: [PATCH 11/11] fix: CreateCredential signature --- src/internal/service/token/token.service.go | 3 ++- src/pkg/service/token/token.service.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/internal/service/token/token.service.go b/src/internal/service/token/token.service.go index 1208f70..5ca80d9 100644 --- a/src/internal/service/token/token.service.go +++ b/src/internal/service/token/token.service.go @@ -1,6 +1,7 @@ package token import ( + "github.com/isd-sgcu/johnjud-auth/src/internal/constant" tokenDto "github.com/isd-sgcu/johnjud-auth/src/internal/domain/dto/token" "github.com/isd-sgcu/johnjud-auth/src/pkg/service/jwt" authProto "github.com/isd-sgcu/johnjud-go-proto/johnjud/auth/auth/v1" @@ -14,7 +15,7 @@ func NewService(jwtService jwt.Service) *serviceImpl { return &serviceImpl{jwtService: jwtService} } -func (s *serviceImpl) CreateCredential(userId string, role string) (*authProto.Credential, error) { +func (s *serviceImpl) CreateCredential(userId string, role constant.Role) (*authProto.Credential, error) { return nil, nil } diff --git a/src/pkg/service/token/token.service.go b/src/pkg/service/token/token.service.go index eaf4d7f..038b8f0 100644 --- a/src/pkg/service/token/token.service.go +++ b/src/pkg/service/token/token.service.go @@ -1,6 +1,7 @@ package token import ( + "github.com/isd-sgcu/johnjud-auth/src/internal/constant" tokenDto "github.com/isd-sgcu/johnjud-auth/src/internal/domain/dto/token" "github.com/isd-sgcu/johnjud-auth/src/internal/service/token" "github.com/isd-sgcu/johnjud-auth/src/pkg/service/jwt" @@ -8,7 +9,7 @@ import ( ) type Service interface { - CreateCredential(userId string, role string) (*authProto.Credential, error) + CreateCredential(userId string, role constant.Role) (*authProto.Credential, error) Validate(token string) (*tokenDto.UserCredential, error) }