add login and register api
This commit is contained in:
parent
40812db5bf
commit
bbb6b4b746
|
@ -59,6 +59,7 @@ type (
|
||||||
// --- 4. 權杖刷新 ---
|
// --- 4. 權杖刷新 ---
|
||||||
// RefreshTokenReq 更新 AccessToken
|
// RefreshTokenReq 更新 AccessToken
|
||||||
RefreshTokenReq {
|
RefreshTokenReq {
|
||||||
|
AccessToken string `json:"access_token" validate:"required"`
|
||||||
RefreshToken string `json:"refresh_token" validate:"required"`
|
RefreshToken string `json:"refresh_token" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,3 +2,4 @@ package domain
|
||||||
|
|
||||||
const SuccessCode = 10200
|
const SuccessCode = 10200
|
||||||
const SuccessMessage = "success"
|
const SuccessMessage = "success"
|
||||||
|
const DefaultScope = "gateway"
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"backend/internal/svc"
|
||||||
|
"backend/internal/types"
|
||||||
|
"backend/pkg/permission/domain/entity"
|
||||||
|
"backend/pkg/permission/domain/token"
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 生成 Token
|
||||||
|
func generateToken(svc *svc.ServiceContext, ctx context.Context, req *types.LoginReq, uid string) (entity.TokenResp, error) {
|
||||||
|
// scope role 要修改,refresh tl
|
||||||
|
role := "user"
|
||||||
|
|
||||||
|
tk, err := svc.TokenUC.NewToken(ctx, entity.AuthorizationReq{
|
||||||
|
GrantType: token.ClientCredentials.ToString(),
|
||||||
|
DeviceID: uid, // TODO 沒傳暫時先用UID 替代
|
||||||
|
Scope: "gateway",
|
||||||
|
IsRefreshToken: true,
|
||||||
|
Expires: time.Now().UTC().Add(svc.Config.Token.AccessTokenExpiry).Unix(),
|
||||||
|
Data: map[string]string{
|
||||||
|
"uid": uid,
|
||||||
|
},
|
||||||
|
Role: role,
|
||||||
|
Account: req.LoginID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return entity.TokenResp{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity.TokenResp{
|
||||||
|
AccessToken: tk.AccessToken,
|
||||||
|
TokenType: tk.TokenType,
|
||||||
|
ExpiresIn: tk.ExpiresIn,
|
||||||
|
RefreshToken: tk.RefreshToken,
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,10 @@
|
||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"backend/pkg/library/errs"
|
||||||
|
"backend/pkg/library/errs/code"
|
||||||
|
memberD "backend/pkg/member/domain/member"
|
||||||
|
member "backend/pkg/member/domain/usecase"
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"backend/internal/svc"
|
"backend/internal/svc"
|
||||||
|
@ -15,7 +19,7 @@ type LoginLogic struct {
|
||||||
svcCtx *svc.ServiceContext
|
svcCtx *svc.ServiceContext
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用者登入
|
// NewLoginLogic 使用者登入
|
||||||
func NewLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LoginLogic {
|
func NewLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LoginLogic {
|
||||||
return &LoginLogic{
|
return &LoginLogic{
|
||||||
Logger: logx.WithContext(ctx),
|
Logger: logx.WithContext(ctx),
|
||||||
|
@ -25,7 +29,65 @@ func NewLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LoginLogic
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LoginLogic) Login(req *types.LoginReq) (resp *types.LoginResp, err error) {
|
func (l *LoginLogic) Login(req *types.LoginReq) (resp *types.LoginResp, err error) {
|
||||||
// todo: add your logic here and delete this line
|
//var result member.VerifyAuthResultResponse
|
||||||
|
switch req.AuthMethod {
|
||||||
|
case "credentials":
|
||||||
|
cr, err := l.svcCtx.AccountUC.VerifyPlatformAuthResult(l.ctx, member.VerifyAuthResultRequest{
|
||||||
|
Account: req.LoginID,
|
||||||
|
Token: req.Credentials.Password,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return
|
if !cr.Status {
|
||||||
|
return nil, errs.Unauthorized("failed to verify password")
|
||||||
|
}
|
||||||
|
case "platform":
|
||||||
|
switch req.Platform.Provider {
|
||||||
|
case memberD.Google.ToString():
|
||||||
|
_, err := l.svcCtx.AccountUC.VerifyGoogleAuthResult(l.ctx, member.VerifyAuthResultRequest{
|
||||||
|
Account: req.LoginID,
|
||||||
|
Token: req.Platform.Token,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
case memberD.Line.ToString():
|
||||||
|
// 原始平台驗證
|
||||||
|
accessToken, err := l.svcCtx.AccountUC.LineCodeToAccessToken(l.ctx, req.LoginID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// 換資料
|
||||||
|
userInfo, err := l.svcCtx.AccountUC.LineGetProfileByAccessToken(l.ctx, accessToken.AccessToken)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.LoginID = userInfo.UserID
|
||||||
|
default:
|
||||||
|
return nil, errs.InvalidFormatWithScope(code.CloudEPMember, "unsupported 3 party platform")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, errs.InvalidFormatWithScope(code.CloudEPMember, "failed to get correct auth method")
|
||||||
|
}
|
||||||
|
|
||||||
|
account, err := l.svcCtx.AccountUC.GetUIDByAccount(l.ctx, member.GetUIDByAccountRequest{
|
||||||
|
Account: req.LoginID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tk, err := generateToken(l.svcCtx, l.ctx, req, account.UID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.LoginResp{
|
||||||
|
UID: account.UID,
|
||||||
|
AccessToken: tk.AccessToken,
|
||||||
|
RefreshToken: tk.RefreshToken,
|
||||||
|
TokenType: tk.TokenType,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"backend/internal/domain"
|
||||||
|
"backend/pkg/permission/domain/entity"
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
"backend/internal/svc"
|
"backend/internal/svc"
|
||||||
"backend/internal/types"
|
"backend/internal/types"
|
||||||
|
@ -15,7 +18,7 @@ type RefreshTokenLogic struct {
|
||||||
svcCtx *svc.ServiceContext
|
svcCtx *svc.ServiceContext
|
||||||
}
|
}
|
||||||
|
|
||||||
// 刷新 Access Token
|
// NewRefreshTokenLogic 刷新 Access Token
|
||||||
func NewRefreshTokenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RefreshTokenLogic {
|
func NewRefreshTokenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RefreshTokenLogic {
|
||||||
return &RefreshTokenLogic{
|
return &RefreshTokenLogic{
|
||||||
Logger: logx.WithContext(ctx),
|
Logger: logx.WithContext(ctx),
|
||||||
|
@ -25,7 +28,24 @@ func NewRefreshTokenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Refr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *RefreshTokenLogic) RefreshToken(req *types.RefreshTokenReq) (resp *types.RefreshTokenResp, err error) {
|
func (l *RefreshTokenLogic) RefreshToken(req *types.RefreshTokenReq) (resp *types.RefreshTokenResp, err error) {
|
||||||
// todo: add your logic here and delete this line
|
data, err := l.svcCtx.TokenUC.ReadTokenBasicData(l.ctx, req.AccessToken)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return
|
tk, err := l.svcCtx.TokenUC.RefreshToken(l.ctx, entity.RefreshTokenReq{
|
||||||
|
Token: req.RefreshToken,
|
||||||
|
Scope: domain.DefaultScope,
|
||||||
|
Expires: time.Now().UTC().Add(l.svcCtx.Config.Token.RefreshTokenExpiry).Unix(),
|
||||||
|
DeviceID: data["uid"],
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.RefreshTokenResp{
|
||||||
|
AccessToken: tk.Token,
|
||||||
|
RefreshToken: tk.OneTimeToken,
|
||||||
|
TokenType: tk.TokenType,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,7 @@ import (
|
||||||
"backend/pkg/library/errs/code"
|
"backend/pkg/library/errs/code"
|
||||||
mb "backend/pkg/member/domain/member"
|
mb "backend/pkg/member/domain/member"
|
||||||
member "backend/pkg/member/domain/usecase"
|
member "backend/pkg/member/domain/usecase"
|
||||||
"backend/pkg/permission/domain/entity"
|
|
||||||
"backend/pkg/permission/domain/token"
|
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
@ -82,7 +78,7 @@ func (l *RegisterLogic) Register(req *types.LoginReq) (resp *types.LoginResp, er
|
||||||
|
|
||||||
// Step 5: 生成 Token
|
// Step 5: 生成 Token
|
||||||
req.LoginID = bd.CreateAccountReq.LoginID
|
req.LoginID = bd.CreateAccountReq.LoginID
|
||||||
tk, err := l.generateToken(req, account.UID)
|
tk, err := generateToken(l.svcCtx, l.ctx, req, account.UID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -184,34 +180,3 @@ func buildLineData(ctx context.Context, req *types.LoginReq, svc *svc.ServiceCon
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成 Token
|
|
||||||
func (l *RegisterLogic) generateToken(req *types.LoginReq, uid string) (entity.TokenResp, error) {
|
|
||||||
// scope role 要修改,refresh tl
|
|
||||||
role := "user"
|
|
||||||
|
|
||||||
tk, err := l.svcCtx.TokenUC.NewToken(l.ctx, entity.AuthorizationReq{
|
|
||||||
GrantType: token.ClientCredentials.ToString(),
|
|
||||||
DeviceID: uid, // TODO 沒傳暫時先用UID 替代
|
|
||||||
Scope: "gateway",
|
|
||||||
IsRefreshToken: true,
|
|
||||||
Expires: time.Now().UTC().Add(l.svcCtx.Config.Token.AccessTokenExpiry).Unix(),
|
|
||||||
Data: map[string]string{
|
|
||||||
"uid": uid,
|
|
||||||
"role": role,
|
|
||||||
},
|
|
||||||
Role: role,
|
|
||||||
Account: req.LoginID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return entity.TokenResp{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return entity.TokenResp{
|
|
||||||
AccessToken: tk.AccessToken,
|
|
||||||
TokenType: tk.TokenType,
|
|
||||||
ExpiresIn: tk.ExpiresIn,
|
|
||||||
RefreshToken: tk.RefreshToken,
|
|
||||||
}, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ type RequestPasswordResetLogic struct {
|
||||||
svcCtx *svc.ServiceContext
|
svcCtx *svc.ServiceContext
|
||||||
}
|
}
|
||||||
|
|
||||||
// 請求發送密碼重設驗證碼
|
|
||||||
func NewRequestPasswordResetLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RequestPasswordResetLogic {
|
func NewRequestPasswordResetLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RequestPasswordResetLogic {
|
||||||
return &RequestPasswordResetLogic{
|
return &RequestPasswordResetLogic{
|
||||||
Logger: logx.WithContext(ctx),
|
Logger: logx.WithContext(ctx),
|
||||||
|
@ -24,6 +23,7 @@ func NewRequestPasswordResetLogic(ctx context.Context, svcCtx *svc.ServiceContex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RequestPasswordReset 請求發送密碼重設驗證碼 aka 忘記密碼
|
||||||
func (l *RequestPasswordResetLogic) RequestPasswordReset(req *types.RequestPasswordResetReq) (resp *types.RespOK, err error) {
|
func (l *RequestPasswordResetLogic) RequestPasswordReset(req *types.RequestPasswordResetReq) (resp *types.RespOK, err error) {
|
||||||
// todo: add your logic here and delete this line
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ type VerifyPasswordResetCodeLogic struct {
|
||||||
svcCtx *svc.ServiceContext
|
svcCtx *svc.ServiceContext
|
||||||
}
|
}
|
||||||
|
|
||||||
// 校驗密碼重設驗證碼
|
|
||||||
func NewVerifyPasswordResetCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *VerifyPasswordResetCodeLogic {
|
func NewVerifyPasswordResetCodeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *VerifyPasswordResetCodeLogic {
|
||||||
return &VerifyPasswordResetCodeLogic{
|
return &VerifyPasswordResetCodeLogic{
|
||||||
Logger: logx.WithContext(ctx),
|
Logger: logx.WithContext(ctx),
|
||||||
|
@ -24,6 +23,7 @@ func NewVerifyPasswordResetCodeLogic(ctx context.Context, svcCtx *svc.ServiceCon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VerifyPasswordResetCode 校驗密碼重設驗證碼(頁面需求,預先檢查看看, 顯示表演用)
|
||||||
func (l *VerifyPasswordResetCodeLogic) VerifyPasswordResetCode(req *types.VerifyCodeReq) (resp *types.RespOK, err error) {
|
func (l *VerifyPasswordResetCodeLogic) VerifyPasswordResetCode(req *types.VerifyCodeReq) (resp *types.RespOK, err error) {
|
||||||
// todo: add your logic here and delete this line
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ type PlatformPayload struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RefreshTokenReq struct {
|
type RefreshTokenReq struct {
|
||||||
|
AccessToken string `json:"access_token" validate:"required"`
|
||||||
RefreshToken string `json:"refresh_token" validate:"required"`
|
RefreshToken string `json:"refresh_token" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -174,12 +174,13 @@ func (use *TokenUseCase) RefreshToken(ctx context.Context, req entity.RefreshTok
|
||||||
credentials := token.ClientCredentials
|
credentials := token.ClientCredentials
|
||||||
newToken, err := use.newToken(ctx, &entity.AuthorizationReq{
|
newToken, err := use.newToken(ctx, &entity.AuthorizationReq{
|
||||||
GrantType: credentials.ToString(),
|
GrantType: credentials.ToString(),
|
||||||
Scope: req.Scope,
|
Scope: claimsData.Scope(),
|
||||||
DeviceID: req.DeviceID,
|
DeviceID: req.DeviceID,
|
||||||
Data: claimsData,
|
Data: claimsData,
|
||||||
Expires: req.Expires,
|
Expires: req.Expires,
|
||||||
IsRefreshToken: true,
|
IsRefreshToken: true,
|
||||||
Account: req.DeviceID,
|
Account: claimsData.Account(),
|
||||||
|
Role: claimsData.Role(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return entity.RefreshTokenResp{},
|
return entity.RefreshTokenResp{},
|
||||||
|
@ -474,9 +475,9 @@ func (use *TokenUseCase) wrapTokenError(ctx context.Context, param wrapTokenErro
|
||||||
{Key: "func", Value: param.funcName},
|
{Key: "func", Value: param.funcName},
|
||||||
{Key: "err", Value: param.err.Error()},
|
{Key: "err", Value: param.err.Error()},
|
||||||
}
|
}
|
||||||
|
|
||||||
logx.WithContext(ctx).Errorw(param.message, logFields...)
|
logx.WithContext(ctx).Errorw(param.message, logFields...)
|
||||||
|
|
||||||
wrappedErr := errs.NewError(
|
wrappedErr := errs.NewError(
|
||||||
code.CatToken,
|
code.CatToken,
|
||||||
code.CatToken,
|
code.CatToken,
|
||||||
|
@ -595,7 +596,7 @@ func (use *TokenUseCase) BlacklistToken(ctx context.Context, token string, reaso
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
logx.WithContext(ctx).Infow("token blacklisted",
|
logx.WithContext(ctx).Infow("token blacklisted",
|
||||||
logx.Field("jti", jtiStr),
|
logx.Field("jti", jtiStr),
|
||||||
logx.Field("uid", uid),
|
logx.Field("uid", uid),
|
||||||
logx.Field("reason", reason))
|
logx.Field("reason", reason))
|
||||||
|
|
|
@ -57,3 +57,21 @@ func (tc tokenClaims) UID() string {
|
||||||
|
|
||||||
return uid
|
return uid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tc tokenClaims) Scope() string {
|
||||||
|
scope, ok := tc["scope"]
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return scope
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tc tokenClaims) Account() string {
|
||||||
|
scope, ok := tc["account"]
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return scope
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue