Skip to content
This repository has been archived by the owner on May 2, 2023. It is now read-only.

Commit

Permalink
feat: populate token
Browse files Browse the repository at this point in the history
  • Loading branch information
mohammadne committed Sep 12, 2021
1 parent 34acdb6 commit 51a7c17
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 140 deletions.
95 changes: 0 additions & 95 deletions services/auth/internal/jwt/failures.go

This file was deleted.

91 changes: 52 additions & 39 deletions services/auth/internal/jwt/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const (
type Jwt interface {
CreateJwt(context.Context, uint64) (*models.Jwt, failures.Failure)
ExtractTokenMetadata(context.Context, string, TokenType) (*models.AccessDetails, failures.Failure)
TokenValid(context.Context, string, TokenType) failures.Failure
// TokenValid(context.Context, string, TokenType) failures.Failure
}

type jwt struct {
Expand All @@ -38,8 +38,14 @@ func New(cfg *Config, lg logger.Logger, tr trace.Tracer) Jwt {
return &jwt{config: cfg, logger: lg, tracer: tr}
}

var (
createTokenFailure = failures.Jwt{}.NewInternal("token creation failed, please try later")
invalidClaimsFailure = failures.Jwt{}.NewInternal("token metadata is invalid, please try later")
invalidTokenFailure = failures.Jwt{}.NewInvalid("invalid token given")
)

func (jwt *jwt) CreateJwt(ctx context.Context, userId uint64) (*models.Jwt, failures.Failure) {
ctx, span := jwt.tracer.Start(ctx, "jwt.create_jwt")
_, span := jwt.tracer.Start(ctx, "jwt.create_jwt")
defer span.End()

accessExpires := time.Duration(jwt.config.AccessExpires) * time.Hour
Expand All @@ -58,18 +64,16 @@ func (jwt *jwt) CreateJwt(ctx context.Context, userId uint64) (*models.Jwt, fail

accessErr := createToken(userId, jwt.config.AccessSecret, tokenDetail.AccessToken)
if accessErr != nil {
failure := Failure{}.NewUnprocessableEntity("unprocessable access token")
jwt.logger.Error(failure.Message(), logger.Error(accessErr))
jwt.logger.Error(createTokenFailure.Message(), logger.Error(accessErr))
span.RecordError(accessErr)
return nil, failure
return nil, createTokenFailure
}

refreshErr := createToken(userId, jwt.config.RefreshSecret, tokenDetail.RefreshToken)
if refreshErr != nil {
failure := Failure{}.NewUnprocessableEntity("unprocessable refresh token")
jwt.logger.Error(failure.Message(), logger.Error(refreshErr))
jwt.logger.Error(createTokenFailure.Message(), logger.Error(refreshErr))
span.RecordError(refreshErr)
return nil, failure
return nil, createTokenFailure
}

return tokenDetail, nil
Expand All @@ -93,55 +97,60 @@ func createToken(userId uint64, secret string, token *models.Token) error {
return nil
}

// failureUnprocessableEntity
// failureUnautorized = failures.Network{}.NewUnauthorized("unauthorized")
// failureUnautorized
func (jwt *jwt) ExtractTokenMetadata(ctx context.Context, tokenString string, tokenType TokenType) (*models.AccessDetails, failures.Failure) {
ctx, span := jwt.tracer.Start(ctx, "jwt.extract_token_metadata")
_, span := jwt.tracer.Start(ctx, "jwt.extract_token_metadata")
defer span.End()

token, failure := jwt.verifyToken(tokenString, tokenType)
if failure != nil {
span.RecordError(failure)
return nil, failure
token, err := jwt.verifyToken(tokenString, tokenType)
if err != nil {
jwt.logger.Error(invalidTokenFailure.Message(), logger.Error(err))
span.RecordError(err)
return nil, invalidTokenFailure
}

claims, ok := token.Claims.(jwtPkg.MapClaims)
if ok && token.Valid {
tokenUuid, ok := claims["token_uuid"].(string)
if !ok {
return nil, err
}
if !ok {
err = fmt.Errorf("invalid map claims: %v", token.Claims)
jwt.logger.Error(invalidClaimsFailure.Message(), logger.Error(err))
span.RecordError(err)
return nil, invalidClaimsFailure
}

userIdStr := fmt.Sprintf("%.f", claims["user_id"])
userId, err := strconv.ParseUint(userIdStr, 10, 64)
if err != nil {
span.RecordError(err)
return nil, err
}
tokenUuid, ok := claims["token_uuid"].(string)
if !ok {
err = fmt.Errorf("ivalid claims: %v", claims)
jwt.logger.Error(invalidTokenFailure.Message(), logger.Error(err))
span.RecordError(err)
return nil, invalidTokenFailure
}

return &models.AccessDetails{TokenUuid: tokenUuid, UserId: userId}, nil
userIdStr := fmt.Sprintf("%.f", claims["user_id"])
userId, err := strconv.ParseUint(userIdStr, 10, 64)
if err != nil {
err = fmt.Errorf("ivalid claims: %v, err:%v", claims, err)
jwt.logger.Error(invalidTokenFailure.Message(), logger.Error(err))
span.RecordError(err)
return nil, invalidTokenFailure
}

err = errors.New("invalid token")
span.RecordError(err)
return nil, err
return &models.AccessDetails{TokenUuid: tokenUuid, UserId: userId}, nil
}

func (jwt *jwt) TokenValid(ctx context.Context, tokenString string, tokenType TokenType) failures.Failure {
token, err := jwt.verifyToken(tokenString, tokenType)
if err != nil {
return err
}
_, span := jwt.tracer.Start(ctx, "jwt.token_valid")
defer span.End()

if !token.Valid {
return errors.New("invalid token")
_, err := jwt.verifyToken(tokenString, tokenType)
if err != nil {
jwt.logger.Error(invalidTokenFailure.Message(), logger.Error(err))
span.RecordError(err)
return invalidTokenFailure
}

return nil
}

func (jwt *jwt) verifyToken(tokenString string, tokenType TokenType) (*jwtPkg.Token, failures.Failure) {
func (jwt *jwt) verifyToken(tokenString string, tokenType TokenType) (*jwtPkg.Token, error) {
var secret string
if tokenType == Access {
secret = jwt.config.AccessSecret
Expand All @@ -154,6 +163,10 @@ func (jwt *jwt) verifyToken(tokenString string, tokenType TokenType) (*jwtPkg.To
return nil, err
}

if !token.Valid {
return nil, errors.New("invalid token")
}

return token, nil
}

Expand All @@ -162,7 +175,7 @@ func (jwt *jwt) checkSigningMethod(secret string) jwtPkg.Keyfunc {
return func(token *jwtPkg.Token) (interface{}, error) {
if _, ok := token.Method.(*jwtPkg.SigningMethodHMAC); !ok {
s := token.Header["alg"]
jwt.logger.Error("unexpected signing method", logger.Unknown("token", s))
jwt.logger.Error("unexpected signing method", logger.Any("token", s))
return nil, fmt.Errorf("unexpected signing method: %v", s)
}

Expand Down
2 changes: 1 addition & 1 deletion services/auth/internal/network/grpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (s *grpcServer) Serve(<-chan struct{}) {

func (s *grpcServer) TokenMetadata(ctx context.Context, token *pb.TokenContract,
) (*pb.TokenMetadataResponse, error) {
accessDetails, err := s.jwt.ExtractTokenMetadata(token.Token, jwt.Access)
accessDetails, err := s.jwt.ExtractTokenMetadata(ctx, token.Token, jwt.Access)
if err != nil {
return nil, err
}
Expand Down
6 changes: 3 additions & 3 deletions services/auth/internal/network/rest_api/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func (handler restServer) signOut(c echo.Context) error {
defer span.End()

tokenString := extractToken(c.Request())
accessDetails, failure := handler.jwt.ExtractTokenMetadata(tokenString, jwt.Access)
accessDetails, failure := handler.jwt.ExtractTokenMetadata(ctx, tokenString, jwt.Access)
if failure != nil {
span.RecordError(failure)
return c.JSON(failure.Status(), failure)
Expand Down Expand Up @@ -106,7 +106,7 @@ func (handler restServer) refreshToken(c echo.Context) error {
return c.JSON(failureInvalidBody.Status(), failureInvalidBody)
}

accessDetails, failure := handler.jwt.ExtractTokenMetadata(body.RefreshToken, jwt.Refresh)
accessDetails, failure := handler.jwt.ExtractTokenMetadata(ctx, body.RefreshToken, jwt.Refresh)
if failure != nil {
span.RecordError(failure)
return c.JSON(failure.Status(), failure)
Expand All @@ -128,7 +128,7 @@ func (handler restServer) refreshToken(c echo.Context) error {
}

func (handler restServer) generateTokens(ctx context.Context, userId uint64) (map[string]string, failures.Failure) {
jwt, failure := handler.jwt.CreateJwt(userId)
jwt, failure := handler.jwt.CreateJwt(ctx, userId)
if failure != nil {
return nil, failure
}
Expand Down
72 changes: 72 additions & 0 deletions services/auth/pkg/failures/jwt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package failures

import (
"fmt"
"net/http"
)

type jwtFailure struct {
FailureMessage string `json:"message"`
FailureStatus int `json:"status"`
FailureCauses []string `json:"causes"`
}

// ==============================================================> methods

func (f *jwtFailure) Message() string {
return f.FailureMessage
}

func (f *jwtFailure) Status() int {
return f.FailureStatus
}

func (f *jwtFailure) Causes() []string {
return f.FailureCauses
}

func (f *jwtFailure) Error() string {
return fmt.Sprintf(
"message: %s - status: %d - causes: %v",
f.FailureMessage, f.FailureStatus, f.FailureCauses,
)
}

// ==============================================================> constructors

type Jwt struct{}

func (Jwt) New(message string, status int, causes []string) Failure {
return &jwtFailure{
FailureMessage: message,
FailureStatus: status,
FailureCauses: causes,
}
}

func (Jwt) NewUnprocessableToken(message string) Failure {
return &jwtFailure{
FailureMessage: message,
FailureStatus: http.StatusUnprocessableEntity,
}
}

func (Jwt) NewInvalid(message string) Failure {
return &jwtFailure{
FailureMessage: message,
FailureStatus: http.StatusUnauthorized,
}
}

func (Jwt) NewInternal(message string, errors ...error) Failure {
causes := make([]string, 0, len(errors))
for index := 0; index < len(errors); index++ {
causes = append(causes, errors[index].Error())
}

return &jwtFailure{
FailureMessage: message,
FailureStatus: http.StatusInternalServerError,
FailureCauses: causes,
}
}
4 changes: 2 additions & 2 deletions services/auth/pkg/logger/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ type Field struct {
Type FieldType
}

// Unknown constructs a field with the given key and value.
func Unknown(key string, val interface{}) Field {
// Any constructs a field with the given key and value.
func Any(key string, val interface{}) Field {
return Field{Key: key, Value: val, Type: UnknownType}
}

Expand Down

0 comments on commit 51a7c17

Please sign in to comment.