feat(auth): Complete Auth Service implementation and fix Consul health checks
- Add VerifyPassword RPC to Identity Service - Added to proto file and generated code - Implemented in Identity Service gRPC server - Added to Identity Service client interface and gRPC client - Complete RefreshToken implementation - Store refresh tokens in database using RefreshToken entity - Validate refresh tokens with expiration checking - Revoke refresh tokens on logout and token rotation - Integrate Authz Service for role retrieval - Added AuthzServiceClient to Auth Service - Get user roles during login and token refresh - Gracefully handle Authz Service failures - Require JWT secret in configuration - Removed default secret fallback - Service fails to start if JWT secret is not configured - Fix Consul health checks for Docker - Services now register with Docker service names (e.g., audit-service) - Allows Consul (in Docker) to reach services via Docker DNS - Health checks use gRPC service names instead of localhost This completes all TODOs in auth_service_fx.go and fixes the Consul health check failures in Docker environments.
This commit is contained in:
@@ -914,6 +914,104 @@ func (x *ResetPasswordResponse) GetSuccess() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// VerifyPasswordRequest contains email and password.
|
||||
type VerifyPasswordRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"`
|
||||
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *VerifyPasswordRequest) Reset() {
|
||||
*x = VerifyPasswordRequest{}
|
||||
mi := &file_identity_proto_msgTypes[17]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *VerifyPasswordRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*VerifyPasswordRequest) ProtoMessage() {}
|
||||
|
||||
func (x *VerifyPasswordRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_identity_proto_msgTypes[17]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use VerifyPasswordRequest.ProtoReflect.Descriptor instead.
|
||||
func (*VerifyPasswordRequest) Descriptor() ([]byte, []int) {
|
||||
return file_identity_proto_rawDescGZIP(), []int{17}
|
||||
}
|
||||
|
||||
func (x *VerifyPasswordRequest) GetEmail() string {
|
||||
if x != nil {
|
||||
return x.Email
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *VerifyPasswordRequest) GetPassword() string {
|
||||
if x != nil {
|
||||
return x.Password
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// VerifyPasswordResponse contains the user if password is valid.
|
||||
type VerifyPasswordResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *VerifyPasswordResponse) Reset() {
|
||||
*x = VerifyPasswordResponse{}
|
||||
mi := &file_identity_proto_msgTypes[18]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *VerifyPasswordResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*VerifyPasswordResponse) ProtoMessage() {}
|
||||
|
||||
func (x *VerifyPasswordResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_identity_proto_msgTypes[18]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use VerifyPasswordResponse.ProtoReflect.Descriptor instead.
|
||||
func (*VerifyPasswordResponse) Descriptor() ([]byte, []int) {
|
||||
return file_identity_proto_rawDescGZIP(), []int{18}
|
||||
}
|
||||
|
||||
func (x *VerifyPasswordResponse) GetUser() *User {
|
||||
if x != nil {
|
||||
return x.User
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_identity_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_identity_proto_rawDesc = "" +
|
||||
@@ -978,7 +1076,12 @@ const file_identity_proto_rawDesc = "" +
|
||||
"\x05token\x18\x01 \x01(\tR\x05token\x12!\n" +
|
||||
"\fnew_password\x18\x02 \x01(\tR\vnewPassword\"1\n" +
|
||||
"\x15ResetPasswordResponse\x12\x18\n" +
|
||||
"\asuccess\x18\x01 \x01(\bR\asuccess2\xb6\x05\n" +
|
||||
"\asuccess\x18\x01 \x01(\bR\asuccess\"I\n" +
|
||||
"\x15VerifyPasswordRequest\x12\x14\n" +
|
||||
"\x05email\x18\x01 \x01(\tR\x05email\x12\x1a\n" +
|
||||
"\bpassword\x18\x02 \x01(\tR\bpassword\"?\n" +
|
||||
"\x16VerifyPasswordResponse\x12%\n" +
|
||||
"\x04user\x18\x01 \x01(\v2\x11.identity.v1.UserR\x04user2\x91\x06\n" +
|
||||
"\x0fIdentityService\x12D\n" +
|
||||
"\aGetUser\x12\x1b.identity.v1.GetUserRequest\x1a\x1c.identity.v1.GetUserResponse\x12Y\n" +
|
||||
"\x0eGetUserByEmail\x12\".identity.v1.GetUserByEmailRequest\x1a#.identity.v1.GetUserByEmailResponse\x12M\n" +
|
||||
@@ -990,7 +1093,8 @@ const file_identity_proto_rawDesc = "" +
|
||||
"DeleteUser\x12\x1e.identity.v1.DeleteUserRequest\x1a\x1f.identity.v1.DeleteUserResponse\x12P\n" +
|
||||
"\vVerifyEmail\x12\x1f.identity.v1.VerifyEmailRequest\x1a .identity.v1.VerifyEmailResponse\x12k\n" +
|
||||
"\x14RequestPasswordReset\x12(.identity.v1.RequestPasswordResetRequest\x1a).identity.v1.RequestPasswordResetResponse\x12V\n" +
|
||||
"\rResetPassword\x12!.identity.v1.ResetPasswordRequest\x1a\".identity.v1.ResetPasswordResponseBMZKgit.dcentral.systems/toolz/goplt/api/proto/generated/identity/v1;identityv1b\x06proto3"
|
||||
"\rResetPassword\x12!.identity.v1.ResetPasswordRequest\x1a\".identity.v1.ResetPasswordResponse\x12Y\n" +
|
||||
"\x0eVerifyPassword\x12\".identity.v1.VerifyPasswordRequest\x1a#.identity.v1.VerifyPasswordResponseBMZKgit.dcentral.systems/toolz/goplt/api/proto/generated/identity/v1;identityv1b\x06proto3"
|
||||
|
||||
var (
|
||||
file_identity_proto_rawDescOnce sync.Once
|
||||
@@ -1004,7 +1108,7 @@ func file_identity_proto_rawDescGZIP() []byte {
|
||||
return file_identity_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_identity_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
|
||||
var file_identity_proto_msgTypes = make([]protoimpl.MessageInfo, 19)
|
||||
var file_identity_proto_goTypes = []any{
|
||||
(*User)(nil), // 0: identity.v1.User
|
||||
(*GetUserRequest)(nil), // 1: identity.v1.GetUserRequest
|
||||
@@ -1023,33 +1127,38 @@ var file_identity_proto_goTypes = []any{
|
||||
(*RequestPasswordResetResponse)(nil), // 14: identity.v1.RequestPasswordResetResponse
|
||||
(*ResetPasswordRequest)(nil), // 15: identity.v1.ResetPasswordRequest
|
||||
(*ResetPasswordResponse)(nil), // 16: identity.v1.ResetPasswordResponse
|
||||
(*VerifyPasswordRequest)(nil), // 17: identity.v1.VerifyPasswordRequest
|
||||
(*VerifyPasswordResponse)(nil), // 18: identity.v1.VerifyPasswordResponse
|
||||
}
|
||||
var file_identity_proto_depIdxs = []int32{
|
||||
0, // 0: identity.v1.GetUserResponse.user:type_name -> identity.v1.User
|
||||
0, // 1: identity.v1.GetUserByEmailResponse.user:type_name -> identity.v1.User
|
||||
0, // 2: identity.v1.CreateUserResponse.user:type_name -> identity.v1.User
|
||||
0, // 3: identity.v1.UpdateUserResponse.user:type_name -> identity.v1.User
|
||||
1, // 4: identity.v1.IdentityService.GetUser:input_type -> identity.v1.GetUserRequest
|
||||
3, // 5: identity.v1.IdentityService.GetUserByEmail:input_type -> identity.v1.GetUserByEmailRequest
|
||||
5, // 6: identity.v1.IdentityService.CreateUser:input_type -> identity.v1.CreateUserRequest
|
||||
7, // 7: identity.v1.IdentityService.UpdateUser:input_type -> identity.v1.UpdateUserRequest
|
||||
9, // 8: identity.v1.IdentityService.DeleteUser:input_type -> identity.v1.DeleteUserRequest
|
||||
11, // 9: identity.v1.IdentityService.VerifyEmail:input_type -> identity.v1.VerifyEmailRequest
|
||||
13, // 10: identity.v1.IdentityService.RequestPasswordReset:input_type -> identity.v1.RequestPasswordResetRequest
|
||||
15, // 11: identity.v1.IdentityService.ResetPassword:input_type -> identity.v1.ResetPasswordRequest
|
||||
2, // 12: identity.v1.IdentityService.GetUser:output_type -> identity.v1.GetUserResponse
|
||||
4, // 13: identity.v1.IdentityService.GetUserByEmail:output_type -> identity.v1.GetUserByEmailResponse
|
||||
6, // 14: identity.v1.IdentityService.CreateUser:output_type -> identity.v1.CreateUserResponse
|
||||
8, // 15: identity.v1.IdentityService.UpdateUser:output_type -> identity.v1.UpdateUserResponse
|
||||
10, // 16: identity.v1.IdentityService.DeleteUser:output_type -> identity.v1.DeleteUserResponse
|
||||
12, // 17: identity.v1.IdentityService.VerifyEmail:output_type -> identity.v1.VerifyEmailResponse
|
||||
14, // 18: identity.v1.IdentityService.RequestPasswordReset:output_type -> identity.v1.RequestPasswordResetResponse
|
||||
16, // 19: identity.v1.IdentityService.ResetPassword:output_type -> identity.v1.ResetPasswordResponse
|
||||
12, // [12:20] is the sub-list for method output_type
|
||||
4, // [4:12] is the sub-list for method input_type
|
||||
4, // [4:4] is the sub-list for extension type_name
|
||||
4, // [4:4] is the sub-list for extension extendee
|
||||
0, // [0:4] is the sub-list for field type_name
|
||||
0, // 4: identity.v1.VerifyPasswordResponse.user:type_name -> identity.v1.User
|
||||
1, // 5: identity.v1.IdentityService.GetUser:input_type -> identity.v1.GetUserRequest
|
||||
3, // 6: identity.v1.IdentityService.GetUserByEmail:input_type -> identity.v1.GetUserByEmailRequest
|
||||
5, // 7: identity.v1.IdentityService.CreateUser:input_type -> identity.v1.CreateUserRequest
|
||||
7, // 8: identity.v1.IdentityService.UpdateUser:input_type -> identity.v1.UpdateUserRequest
|
||||
9, // 9: identity.v1.IdentityService.DeleteUser:input_type -> identity.v1.DeleteUserRequest
|
||||
11, // 10: identity.v1.IdentityService.VerifyEmail:input_type -> identity.v1.VerifyEmailRequest
|
||||
13, // 11: identity.v1.IdentityService.RequestPasswordReset:input_type -> identity.v1.RequestPasswordResetRequest
|
||||
15, // 12: identity.v1.IdentityService.ResetPassword:input_type -> identity.v1.ResetPasswordRequest
|
||||
17, // 13: identity.v1.IdentityService.VerifyPassword:input_type -> identity.v1.VerifyPasswordRequest
|
||||
2, // 14: identity.v1.IdentityService.GetUser:output_type -> identity.v1.GetUserResponse
|
||||
4, // 15: identity.v1.IdentityService.GetUserByEmail:output_type -> identity.v1.GetUserByEmailResponse
|
||||
6, // 16: identity.v1.IdentityService.CreateUser:output_type -> identity.v1.CreateUserResponse
|
||||
8, // 17: identity.v1.IdentityService.UpdateUser:output_type -> identity.v1.UpdateUserResponse
|
||||
10, // 18: identity.v1.IdentityService.DeleteUser:output_type -> identity.v1.DeleteUserResponse
|
||||
12, // 19: identity.v1.IdentityService.VerifyEmail:output_type -> identity.v1.VerifyEmailResponse
|
||||
14, // 20: identity.v1.IdentityService.RequestPasswordReset:output_type -> identity.v1.RequestPasswordResetResponse
|
||||
16, // 21: identity.v1.IdentityService.ResetPassword:output_type -> identity.v1.ResetPasswordResponse
|
||||
18, // 22: identity.v1.IdentityService.VerifyPassword:output_type -> identity.v1.VerifyPasswordResponse
|
||||
14, // [14:23] is the sub-list for method output_type
|
||||
5, // [5:14] is the sub-list for method input_type
|
||||
5, // [5:5] is the sub-list for extension type_name
|
||||
5, // [5:5] is the sub-list for extension extendee
|
||||
0, // [0:5] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_identity_proto_init() }
|
||||
@@ -1064,7 +1173,7 @@ func file_identity_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_identity_proto_rawDesc), len(file_identity_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 17,
|
||||
NumMessages: 19,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
||||
@@ -27,6 +27,7 @@ const (
|
||||
IdentityService_VerifyEmail_FullMethodName = "/identity.v1.IdentityService/VerifyEmail"
|
||||
IdentityService_RequestPasswordReset_FullMethodName = "/identity.v1.IdentityService/RequestPasswordReset"
|
||||
IdentityService_ResetPassword_FullMethodName = "/identity.v1.IdentityService/ResetPassword"
|
||||
IdentityService_VerifyPassword_FullMethodName = "/identity.v1.IdentityService/VerifyPassword"
|
||||
)
|
||||
|
||||
// IdentityServiceClient is the client API for IdentityService service.
|
||||
@@ -51,6 +52,8 @@ type IdentityServiceClient interface {
|
||||
RequestPasswordReset(ctx context.Context, in *RequestPasswordResetRequest, opts ...grpc.CallOption) (*RequestPasswordResetResponse, error)
|
||||
// ResetPassword resets a user's password using a reset token.
|
||||
ResetPassword(ctx context.Context, in *ResetPasswordRequest, opts ...grpc.CallOption) (*ResetPasswordResponse, error)
|
||||
// VerifyPassword verifies a user's password.
|
||||
VerifyPassword(ctx context.Context, in *VerifyPasswordRequest, opts ...grpc.CallOption) (*VerifyPasswordResponse, error)
|
||||
}
|
||||
|
||||
type identityServiceClient struct {
|
||||
@@ -141,6 +144,16 @@ func (c *identityServiceClient) ResetPassword(ctx context.Context, in *ResetPass
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *identityServiceClient) VerifyPassword(ctx context.Context, in *VerifyPasswordRequest, opts ...grpc.CallOption) (*VerifyPasswordResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(VerifyPasswordResponse)
|
||||
err := c.cc.Invoke(ctx, IdentityService_VerifyPassword_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// IdentityServiceServer is the server API for IdentityService service.
|
||||
// All implementations must embed UnimplementedIdentityServiceServer
|
||||
// for forward compatibility.
|
||||
@@ -163,6 +176,8 @@ type IdentityServiceServer interface {
|
||||
RequestPasswordReset(context.Context, *RequestPasswordResetRequest) (*RequestPasswordResetResponse, error)
|
||||
// ResetPassword resets a user's password using a reset token.
|
||||
ResetPassword(context.Context, *ResetPasswordRequest) (*ResetPasswordResponse, error)
|
||||
// VerifyPassword verifies a user's password.
|
||||
VerifyPassword(context.Context, *VerifyPasswordRequest) (*VerifyPasswordResponse, error)
|
||||
mustEmbedUnimplementedIdentityServiceServer()
|
||||
}
|
||||
|
||||
@@ -197,6 +212,9 @@ func (UnimplementedIdentityServiceServer) RequestPasswordReset(context.Context,
|
||||
func (UnimplementedIdentityServiceServer) ResetPassword(context.Context, *ResetPasswordRequest) (*ResetPasswordResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ResetPassword not implemented")
|
||||
}
|
||||
func (UnimplementedIdentityServiceServer) VerifyPassword(context.Context, *VerifyPasswordRequest) (*VerifyPasswordResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method VerifyPassword not implemented")
|
||||
}
|
||||
func (UnimplementedIdentityServiceServer) mustEmbedUnimplementedIdentityServiceServer() {}
|
||||
func (UnimplementedIdentityServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
@@ -362,6 +380,24 @@ func _IdentityService_ResetPassword_Handler(srv interface{}, ctx context.Context
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _IdentityService_VerifyPassword_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(VerifyPasswordRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(IdentityServiceServer).VerifyPassword(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: IdentityService_VerifyPassword_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(IdentityServiceServer).VerifyPassword(ctx, req.(*VerifyPasswordRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// IdentityService_ServiceDesc is the grpc.ServiceDesc for IdentityService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@@ -401,6 +437,10 @@ var IdentityService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "ResetPassword",
|
||||
Handler: _IdentityService_ResetPassword_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "VerifyPassword",
|
||||
Handler: _IdentityService_VerifyPassword_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "identity.proto",
|
||||
|
||||
Reference in New Issue
Block a user