127 lines
3.7 KiB
Go
127 lines
3.7 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
errs "gateway/internal/library/errors"
|
|
"gateway/internal/library/errors/code"
|
|
"gateway/internal/library/zitadel"
|
|
domauth "gateway/internal/model/auth/domain/usecase"
|
|
memberdom "gateway/internal/model/member/domain"
|
|
memberenum "gateway/internal/model/member/domain/enum"
|
|
dommember "gateway/internal/model/member/domain/usecase"
|
|
"gateway/internal/svc"
|
|
"gateway/internal/types"
|
|
)
|
|
|
|
func issueAuthToken(ctx context.Context, sc *svc.ServiceContext, tenantID, uid string) (*types.AuthTokenData, error) {
|
|
if sc.AuthToken == nil {
|
|
return nil, errb.SysNotImplemented("auth token not configured")
|
|
}
|
|
pair, err := sc.AuthToken.IssuePair(ctx, &domauth.IssuePairRequest{
|
|
TenantID: tenantID,
|
|
UID: uid,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &types.AuthTokenData{
|
|
AccessToken: pair.AccessToken,
|
|
RefreshToken: pair.RefreshToken,
|
|
ExpiresIn: pair.ExpiresIn,
|
|
UID: uid,
|
|
TokenType: pair.TokenType,
|
|
}, nil
|
|
}
|
|
|
|
func tokenDataFromRefresh(ctx context.Context, sc *svc.ServiceContext, refreshToken string) (*types.AuthTokenData, error) {
|
|
if sc.AuthToken == nil {
|
|
return nil, errb.SysNotImplemented("auth token not configured")
|
|
}
|
|
pair, err := sc.AuthToken.Refresh(ctx, refreshToken)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
claims, err := sc.AuthToken.ParseAccessToken(ctx, pair.AccessToken)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &types.AuthTokenData{
|
|
AccessToken: pair.AccessToken,
|
|
RefreshToken: pair.RefreshToken,
|
|
ExpiresIn: pair.ExpiresIn,
|
|
UID: claims.UID,
|
|
TokenType: pair.TokenType,
|
|
}, nil
|
|
}
|
|
|
|
func zitadelIdentityFromToken(ctx context.Context, client *zitadel.Client, tok *zitadel.TokenResult) (*zitadel.IDTokenClaims, error) {
|
|
if tok == nil {
|
|
return nil, errb.SvcThirdParty("empty token result")
|
|
}
|
|
if tok.IDToken != "" {
|
|
claims, err := zitadel.ParseIDTokenClaims(tok.IDToken)
|
|
if err != nil {
|
|
return nil, errb.SvcThirdParty("parse id_token failed").WithCause(err)
|
|
}
|
|
return claims, nil
|
|
}
|
|
claims, err := client.FetchUserInfo(ctx, tok.AccessToken)
|
|
if err != nil {
|
|
return nil, wrapZitadelErr(err)
|
|
}
|
|
return claims, nil
|
|
}
|
|
|
|
func memberForLogin(ctx context.Context, sc *svc.ServiceContext, tenantID, zitadelSub string) (*dommember.MemberDTO, error) {
|
|
if sc.MemberProfile == nil {
|
|
return nil, errb.SysNotImplemented("member profile not configured")
|
|
}
|
|
dto, err := sc.MemberProfile.GetByZitadelUserID(ctx, tenantID, zitadelSub)
|
|
if err != nil {
|
|
if e := errs.FromError(err); e != nil && e.Category() == code.ResNotFound {
|
|
return nil, errb.AuthUnauthorized("invalid credentials").WithCause(memberdom.ErrNotFound)
|
|
}
|
|
return nil, err
|
|
}
|
|
if err := ensureLoginEligible(dto.Status); err != nil {
|
|
return nil, err
|
|
}
|
|
return dto, nil
|
|
}
|
|
|
|
func ensureLoginEligible(status memberenum.MemberStatus) error {
|
|
switch status {
|
|
case memberenum.MemberStatusActive:
|
|
return nil
|
|
case memberenum.MemberStatusUnverified:
|
|
return errb.AuthForbidden("account is not verified")
|
|
case memberenum.MemberStatusSuspended:
|
|
return errb.AuthForbidden("account is suspended")
|
|
case memberenum.MemberStatusDeleted:
|
|
return errb.AuthUnauthorized("invalid credentials")
|
|
default:
|
|
return errb.AuthForbidden("account is not allowed to login")
|
|
}
|
|
}
|
|
|
|
func normalizeLoginEmail(email string) string {
|
|
return strings.TrimSpace(strings.ToLower(email))
|
|
}
|
|
|
|
func requireLoginDeps(sc *svc.ServiceContext) error {
|
|
if sc.Zitadel == nil {
|
|
return errb.SysNotImplemented("zitadel not configured")
|
|
}
|
|
if sc.MemberProfile == nil {
|
|
return errb.SysNotImplemented("member profile not configured")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func isMemberNotFound(err error) bool {
|
|
e := errs.FromError(err)
|
|
return e != nil && e.Category() == code.ResNotFound
|
|
}
|