Skip to content

Commit 44cd20f

Browse files
Add. Integration of Refresh token rotation to user apis
1 parent ed41529 commit 44cd20f

File tree

4 files changed

+88
-2
lines changed

4 files changed

+88
-2
lines changed

handlers/userHandler.go

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ type UserHandler interface {
2020

2121
type userHandler struct {
2222
us services.UserService
23+
as services.AuthService
2324
}
2425

25-
func NewUserHandler(us services.UserService) UserHandler {
26+
func NewUserHandler(us services.UserService, as services.AuthService) UserHandler {
2627
fmt.Println("[NewUserHandler] Initiating New User Handler")
2728
return &userHandler{
2829
us: us,
30+
as: as,
2931
}
3032
}
3133

@@ -50,6 +52,14 @@ func (uh *userHandler) UserByUsernameHandler(c *gin.Context) {
5052
return
5153
}
5254

55+
if !uh.isUserProvidesValidToken(c) {
56+
errMessage := constants.MaliciousTokenErrorMessage
57+
fmt.Println("[UserByUsernameHandler]", errMessage)
58+
errRes := helpers.CreateErrorResponse(http.StatusUnauthorized, errMessage)
59+
c.JSON(http.StatusUnauthorized, errRes)
60+
return
61+
}
62+
5363
user, err := uh.us.UserByUsername(username)
5464
if err != nil {
5565
fmt.Println("[UserByUsernameHandler]", err.Error())
@@ -76,6 +86,14 @@ func (uh *userHandler) GetAllUsers(c *gin.Context) {
7686
return
7787
}
7888

89+
if !uh.isUserProvidesValidToken(c) {
90+
errMessage := constants.MaliciousTokenErrorMessage
91+
fmt.Println("[GetAllUsersHandler]", errMessage)
92+
errRes := helpers.CreateErrorResponse(http.StatusUnauthorized, errMessage)
93+
c.JSON(http.StatusUnauthorized, errRes)
94+
return
95+
}
96+
7997
userList, err := uh.us.GetAllUsers()
8098
if err != nil {
8199
fmt.Println("[GetAllUsersHandler]", err.Error())
@@ -95,6 +113,30 @@ func (uh *userHandler) GetAllUsers(c *gin.Context) {
95113
c.JSON(http.StatusOK, res)
96114
}
97115

116+
func (uh *userHandler) isUserProvidesValidToken(c *gin.Context) bool {
117+
clientToken := c.Request.Header.Get("Authorization")
118+
tokenString := strings.Replace(clientToken, "Bearer ", "", 1)
119+
username := c.GetString("username")
120+
121+
tokens, err := uh.as.FindTokensByUsername(username)
122+
if err != nil {
123+
fmt.Println("[UserByUsernameHandler]", err.Error())
124+
return false
125+
}
126+
127+
if !areTokensEqual(tokenString, tokens.AccessToken) {
128+
errMessage := constants.MaliciousTokenErrorMessage
129+
fmt.Println("[UserByUsernameHandler]", errMessage)
130+
return false
131+
}
132+
133+
return true
134+
}
135+
136+
func areTokensEqual(tokenOne string, tokenTwo string) bool {
137+
return tokenOne == tokenTwo
138+
}
139+
98140
func isUserMatchesWith(c *gin.Context, inputUsername string) bool {
99141
if isAdmin(c) {
100142
return true

main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func main() {
2222
as := services.NewAuthService(ar)
2323

2424
ah := handlers.NewAuthHandler(us, as)
25-
uh := handlers.NewUserHandler(us)
25+
uh := handlers.NewUserHandler(us, as)
2626

2727
app := gin.Default()
2828

repositories/authRepository.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
type AuthRepository interface {
1212
SaveTokens(string, string, string) error
13+
FindTokensByUsername(string) (models.Tokens, error)
1314
}
1415

1516
type authRepository struct {
@@ -42,3 +43,22 @@ func (ar *authRepository) SaveTokens(username string, accessToken string, refres
4243
fmt.Println("[SaveTokensRepository] Tokens are saved")
4344
return nil
4445
}
46+
47+
func (ar *authRepository) FindTokensByUsername(username string) (models.Tokens, error) {
48+
fmt.Println("[FindTokensByUsernameRepository] Hitting find tokens by username function in auth repository")
49+
50+
var tokens models.Tokens
51+
res := ar.db.Where("username = ?", username).Find(&tokens)
52+
if res.Error != nil {
53+
fmt.Println("[FindTokensByUsernameRepository] Error while finding tokens by username")
54+
return models.Tokens{}, res.Error
55+
}
56+
57+
if res.RowsAffected == 0 {
58+
fmt.Println("[FindTokensByUsernameRepository] Tokens are not found with username")
59+
return models.Tokens{}, gorm.ErrRecordNotFound
60+
}
61+
62+
fmt.Println("[FindTokensByUsernameRepository] Tokens are found")
63+
return tokens, nil
64+
}

services/authService.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
package services
22

33
import (
4+
"errors"
45
"fmt"
56

7+
"github.com/shaikrasheed99/golang-user-jwt-authentication/constants"
8+
"github.com/shaikrasheed99/golang-user-jwt-authentication/models"
69
"github.com/shaikrasheed99/golang-user-jwt-authentication/repositories"
10+
"gorm.io/gorm"
711
)
812

913
type AuthService interface {
1014
SaveTokensByUsername(string, string, string) error
15+
FindTokensByUsername(string) (models.Tokens, error)
1116
}
1217

1318
type authService struct {
@@ -33,3 +38,22 @@ func (as *authService) SaveTokensByUsername(username string, accessToken string,
3338
fmt.Println("[SaveTokensByUsernameService] Tokens are saved")
3439
return nil
3540
}
41+
42+
func (as *authService) FindTokensByUsername(username string) (models.Tokens, error) {
43+
fmt.Println("[FindTokensByUsernameService] Hitting tokens by username function in auth service")
44+
45+
tokens, err := as.ar.FindTokensByUsername(username)
46+
if err == gorm.ErrRecordNotFound {
47+
errMessage := constants.TokensNotFoundErrorMessage
48+
fmt.Println("[FindTokensByUsernameService]", errMessage)
49+
return models.Tokens{}, errors.New(errMessage)
50+
}
51+
52+
if err != nil {
53+
fmt.Println("[FindTokensByUsernameService]", err.Error())
54+
return models.Tokens{}, err
55+
}
56+
57+
fmt.Println("[FindTokensByUsernameService] Returned tokens from repository")
58+
return tokens, nil
59+
}

0 commit comments

Comments
 (0)