Skip to content

Commit

Permalink
chore(auth): some improvements
Browse files Browse the repository at this point in the history
- Add interceptors: selector, auth
- Remove: extraction from payload
- Fix docker compose depends name
  • Loading branch information
ripls56 committed Aug 21, 2024
1 parent 456cf3a commit 1aa1a42
Show file tree
Hide file tree
Showing 24 changed files with 410 additions and 335 deletions.
28 changes: 5 additions & 23 deletions compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ services:
image: postgres:16
restart: always
ports:
- 54321:5432
- "54321:5432"
environment:
POSTGRES_USER: taskem
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
Expand All @@ -20,46 +20,28 @@ services:
image: redis
restart: always
ports:
- 63798:6379
- "63798:6379"
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD}
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "token-cli", "--raw", "incr", "ping"]
test: [ "CMD", "token-cli", "--raw", "incr", "ping" ]
interval: 10s
timeout: 5s
retries: 5


# minio:
# image: quay.io/minio/minio
# restart: always
# command: server /data --console-address ":9001"
# ports:
# - "12200:9000"
# - "9001:9001"
# environment:
# MINIO_ROOT_USER: root
# MINIO_ROOT_PASSWORD: YOUR_PASSWORD
# MINIO_DOMAIN: minio
# networks:
# default:
# aliases:
# - users.minio
# - teams.minio

server:
env_file: ".env"
build:
context: .
target: final
depends_on:
- db
- token
- redis
ports:
- 50051:50051
- "50051:50051"

volumes:
db-data:
Expand Down
2 changes: 2 additions & 0 deletions internal/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"taskem-server/internal/app/task"
"taskem-server/internal/app/team"
"taskem-server/internal/config"
"taskem-server/internal/grpc/interceptors"
)

const (
Expand All @@ -38,6 +39,7 @@ var App = fx.Options(
team.App,
task.App,

fx.Provide(interceptors.New),
fx.Provide(grpcsrv.New),

fx.Invoke(
Expand Down
6 changes: 6 additions & 0 deletions internal/app/grpc/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ package grpc
import (
"context"
"fmt"
authMd "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/selector"
"go.uber.org/fx"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"taskem-server/internal/grpc/auth"
"taskem-server/internal/grpc/interceptors"
"taskem-server/internal/grpc/team"
v1 "taskem-server/tools/gen/grpc/v1"
)
Expand All @@ -20,6 +23,7 @@ type Opts struct {
AuthServer *auth.Server
TeamServer *team.Server
Log *zap.Logger
Ic *interceptors.Interceptor
}

type App struct {
Expand All @@ -44,10 +48,12 @@ func New(opts Opts) App {

srv := grpc.NewServer(
grpc.ChainUnaryInterceptor(
selector.UnaryServerInterceptor(authMd.UnaryServerInterceptor(opts.Ic.Auth), selector.MatchFunc(opts.Ic.AuthMatcher)),
recovery.UnaryServerInterceptor(recoveryOpts...),
logging.UnaryServerInterceptor(interceptorLogger(opts.Log), logOpts...),
),
grpc.ChainStreamInterceptor(
selector.StreamServerInterceptor(authMd.StreamServerInterceptor(opts.Ic.Auth), selector.MatchFunc(opts.Ic.AuthMatcher)),
recovery.StreamServerInterceptor(recoveryOpts...),
logging.StreamServerInterceptor(interceptorLogger(opts.Log), logOpts...),
),
Expand Down
36 changes: 19 additions & 17 deletions internal/grpc/auth/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
"taskem-server/internal/config"
"taskem-server/internal/grpc"
"taskem-server/internal/repositories/token"
"regexp"
"taskem-server/internal/config"
"taskem-server/internal/pkg/jwt"
"taskem-server/internal/pkg/validation"
"taskem-server/internal/repositories/token"
"taskem-server/internal/repositories/user"
"taskem-server/internal/service/auth"
"taskem-server/tools/gen/grpc/v1"
Expand All @@ -24,23 +24,23 @@ type Opts struct {
Auth auth.Service
Logger *zap.Logger
Config config.Config
RedisRepo token.Repository
TokenRepo token.Repository
}

type Server struct {
v1.UnimplementedAuthServer
auth auth.Service
logger *zap.Logger
config config.Config
redisRepo token.Repository
tokenRepo token.Repository
}

func New(opts Opts) *Server {
return &Server{
auth: opts.Auth,
logger: opts.Logger,
config: opts.Config,
redisRepo: opts.RedisRepo,
tokenRepo: opts.TokenRepo,
}
}

Expand Down Expand Up @@ -73,7 +73,7 @@ func (s *Server) Login(
case errors.Is(err, auth.ErrPwdMatch):
return nil, status.Error(codes.InvalidArgument, "Wrong password")
}
return nil, err
return nil, status.Error(codes.InvalidArgument, err.Error())
}

return &v1.LoginResponse{
Expand Down Expand Up @@ -117,37 +117,39 @@ func (s *Server) SignUp(
})
if err != nil {
s.logger.Sugar().Error(err)
return nil, err
return nil, status.Error(codes.Internal, err.Error())
}

return &emptypb.Empty{}, nil
}

func (s *Server) RefreshToken(
ctx context.Context,
req *emptypb.Empty,
req *v1.RefreshTokenRequest,
) (*v1.RefreshTokenResponse, error) {
payload, err := grpc.ExtractTokenPayload(ctx, s.config.TokenSecret, s.redisRepo)

payload, err := jwt.GetPayload(req.Token, s.config.TokenSecret)
if err != nil {
return nil, err
return nil, status.Error(codes.InvalidArgument, err.Error())
}

var uid uuid.UUID
uid, err = uuid.Parse(payload["uid"].(string))
uid, err = uuid.Parse((*payload)["uid"].(string))

if err != nil {
return nil, err
return nil, status.Error(codes.InvalidArgument, err.Error())
}

resp, err := s.auth.RefreshToken(
ctx,
auth.RefreshTokenOpts{UserID: uid},
auth.RefreshTokenOpts{
UserID: uid,
Token: req.Token,
},
)

if err != nil {
s.logger.Sugar().Error(err)
return nil, err
s.logger.Sugar().Warn(err)
return nil, status.Error(codes.InvalidArgument, err.Error())
}

return &v1.RefreshTokenResponse{
Expand Down
77 changes: 0 additions & 77 deletions internal/grpc/extract_token.go

This file was deleted.

59 changes: 59 additions & 0 deletions internal/grpc/interceptors/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package interceptors

import (
"context"
"fmt"
"github.com/go-faster/errors"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"taskem-server/internal/pkg/jwt"
"taskem-server/internal/repositories/token"
)

const TokenKey = "token"
const TokenPayload = "tokenPayload"

// Auth get token from grpc request metadata
//
// Already throws formated grpc with status.Errorf
func (i *Interceptor) Auth(ctx context.Context) (context.Context, error) {
tokenMd, err := auth.AuthFromMD(ctx, "bearer")
if err != nil {
return nil, err
}

claims, err := jwt.GetPayload(tokenMd, i.c.TokenSecret)

if err != nil {
switch {
case errors.Is(err, jwt.ErrTokenExpired):
return nil, status.Errorf(codes.Unauthenticated, "Token expired")
case errors.Is(err, jwt.ErrTokenParse):
return nil, status.Errorf(codes.InvalidArgument, "Token parse error")
case errors.Is(err, jwt.ErrTokenValidation):
return nil, status.Errorf(codes.Unauthenticated, "Token validation error")
default:
return nil, status.Errorf(codes.Internal, "Internal error")
}
}

payload := *claims

_, err = i.tokenRepo.GetToken(ctx, fmt.Sprintf("%s:%s", payload["type"].(string), payload["uid"].(string)))
if err != nil {
switch {
case errors.Is(err, token.ErrNotFound):
return nil, status.Errorf(codes.Unauthenticated, "Wrong token")
default:
return nil, status.Errorf(codes.Internal, "Internal error")
}
}

ctx = logging.InjectFields(ctx, logging.Fields{"auth.sub", payload})
ctx = context.WithValue(ctx, TokenKey, tokenMd)

Check notice on line 55 in internal/grpc/interceptors/auth.go

View check run for this annotation

codefactor.io / CodeFactor

internal/grpc/interceptors/auth.go#L55

Should not use basic type string as key in context.WithValue. (context-keys-type)
ctx = context.WithValue(ctx, TokenPayload, payload)

Check notice on line 56 in internal/grpc/interceptors/auth.go

View check run for this annotation

codefactor.io / CodeFactor

internal/grpc/interceptors/auth.go#L56

Should not use basic type string as key in context.WithValue. (context-keys-type)

return ctx, nil
}
25 changes: 25 additions & 0 deletions internal/grpc/interceptors/interceptor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package interceptors

import (
"go.uber.org/fx"
"taskem-server/internal/config"
"taskem-server/internal/repositories/token"
)

type Opts struct {
fx.In
Config config.Config
TokenRepo token.Repository
}

type Interceptor struct {
c config.Config
tokenRepo token.Repository
}

func New(opts Opts) *Interceptor {
return &Interceptor{
c: opts.Config,
tokenRepo: opts.TokenRepo,
}
}
Loading

0 comments on commit 1aa1a42

Please sign in to comment.