Respond with unauthenticated on compliance page missing membership
Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -673,6 +673,15 @@ func (s AuthService) SendMagicLink(ctx context.Context, req *SendMagicLinkReques
|
||||
)
|
||||
}
|
||||
|
||||
func (s AuthService) GetMagincLinkEmail(ctx context.Context, tokenString string) (mail.Addr, error) {
|
||||
payload, err := statelesstoken.ValidateToken[MagicLinkData](s.tokenSecret, TokenTypeMagicLink, tokenString)
|
||||
if err != nil {
|
||||
return mail.Nil, NewInvalidTokenError()
|
||||
}
|
||||
|
||||
return payload.Data.Email, nil
|
||||
}
|
||||
|
||||
func (s AuthService) OpenSessionWithMagicLink(ctx context.Context, tokenString string) (*coredata.Identity, *coredata.Session, *string, error) {
|
||||
var (
|
||||
now = time.Now()
|
||||
|
||||
@@ -40,7 +40,7 @@ func NewGraphQLHandler(iamSvc *iam.Service, trustSvc *trust.Service, esignSvc *e
|
||||
sessionCookie: authn.NewCookie(&cookieConfig),
|
||||
},
|
||||
Directives: schema.DirectiveRoot{
|
||||
Nda: newNDADirectiveFunc(logger, trustSvc, esignSvc),
|
||||
Nda: newNDADirective(logger, esignSvc),
|
||||
Session: session.Directive,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ package trust_v1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql"
|
||||
"go.gearno.de/kit/log"
|
||||
@@ -25,12 +24,10 @@ import (
|
||||
"go.probo.inc/probo/pkg/server/api/authn"
|
||||
"go.probo.inc/probo/pkg/server/api/compliancepage"
|
||||
"go.probo.inc/probo/pkg/server/gqlutils"
|
||||
"go.probo.inc/probo/pkg/trust"
|
||||
)
|
||||
|
||||
func newNDADirectiveFunc(
|
||||
func newNDADirective(
|
||||
logger *log.Logger,
|
||||
trustSvc *trust.Service,
|
||||
esignSvc *esign.Service,
|
||||
) func(ctx context.Context, obj any, next graphql.Resolver) (any, error) {
|
||||
return func(ctx context.Context, obj any, next graphql.Resolver) (any, error) {
|
||||
@@ -41,24 +38,7 @@ func newNDADirectiveFunc(
|
||||
|
||||
membership := compliancepage.ComplianceMembershipFromContext(ctx)
|
||||
if membership == nil {
|
||||
// Connected user should always have a membership
|
||||
logger.ErrorCtx(ctx, "cannot get membership from context")
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
compliancePage := compliancepage.CompliancePageFromContext(ctx)
|
||||
if compliancePage == nil {
|
||||
logger.ErrorCtx(ctx, "cannot get compliance page from context")
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
if _, err := trustSvc.GetNDAFile(ctx, compliancePage.ID); err != nil {
|
||||
if errors.Is(err, trust.ErrNDAFileNotFound) {
|
||||
return next(ctx)
|
||||
}
|
||||
|
||||
logger.ErrorCtx(ctx, "cannot get NDA file", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
return nil, gqlutils.Unauthenticatedf(ctx, "authentication needed")
|
||||
}
|
||||
|
||||
if membership.ElectronicSignatureID == nil {
|
||||
|
||||
@@ -824,9 +824,9 @@ type Query {
|
||||
|
||||
type Mutation {
|
||||
sendMagicLink(input: SendMagicLinkInput!): SendMagicLinkPayload
|
||||
@session(required: NONE)
|
||||
@session(required: OPTIONAL)
|
||||
verifyMagicLink(input: VerifyMagicLinkInput!): VerifyMagicLinkPayload
|
||||
@session(required: NONE)
|
||||
@session(required: OPTIONAL)
|
||||
|
||||
requestAllAccesses: RequestAccessesPayload! @session(required: PRESENT) @nda
|
||||
|
||||
|
||||
@@ -2246,9 +2246,9 @@ type Query {
|
||||
|
||||
type Mutation {
|
||||
sendMagicLink(input: SendMagicLinkInput!): SendMagicLinkPayload
|
||||
@session(required: NONE)
|
||||
@session(required: OPTIONAL)
|
||||
verifyMagicLink(input: VerifyMagicLinkInput!): VerifyMagicLinkPayload
|
||||
@session(required: NONE)
|
||||
@session(required: OPTIONAL)
|
||||
|
||||
requestAllAccesses: RequestAccessesPayload! @session(required: PRESENT) @nda
|
||||
|
||||
@@ -4278,7 +4278,7 @@ func (ec *executionContext) _Mutation_sendMagicLink(ctx context.Context, field g
|
||||
directive0 := next
|
||||
|
||||
directive1 := func(ctx context.Context) (any, error) {
|
||||
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "NONE")
|
||||
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "OPTIONAL")
|
||||
if err != nil {
|
||||
var zeroVal *types.SendMagicLinkPayload
|
||||
return zeroVal, err
|
||||
@@ -4341,7 +4341,7 @@ func (ec *executionContext) _Mutation_verifyMagicLink(ctx context.Context, field
|
||||
directive0 := next
|
||||
|
||||
directive1 := func(ctx context.Context) (any, error) {
|
||||
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "NONE")
|
||||
required, err := ec.unmarshalNSessionRequirement2goᚗproboᚗincᚋproboᚋpkgᚋserverᚋgqlutilsᚋdirectivesᚋsessionᚐSessionRequirement(ctx, "OPTIONAL")
|
||||
if err != nil {
|
||||
var zeroVal *types.VerifyMagicLinkPayload
|
||||
return zeroVal, err
|
||||
|
||||
@@ -210,17 +210,54 @@ func (r *mutationResolver) SendMagicLink(ctx context.Context, input types.SendMa
|
||||
|
||||
// VerifyMagicLink is the resolver for the verifyMagicLink field.
|
||||
func (r *mutationResolver) VerifyMagicLink(ctx context.Context, input types.VerifyMagicLinkInput) (*types.VerifyMagicLinkPayload, error) {
|
||||
identity, session, continueURL, err := r.iam.AuthService.OpenSessionWithMagicLink(ctx, input.Token)
|
||||
session := authn.SessionFromContext(ctx)
|
||||
identity := authn.IdentityFromContext(ctx)
|
||||
|
||||
email, err := r.iam.AuthService.GetMagincLinkEmail(ctx, input.Token)
|
||||
if err != nil {
|
||||
var errInvalidToken *iam.ErrInvalidToken
|
||||
if errors.As(err, &errInvalidToken) {
|
||||
return nil, gqlutils.Invalid(ctx, err)
|
||||
}
|
||||
|
||||
r.logger.ErrorCtx(ctx, "cannot open session with magic link", log.Error(err))
|
||||
r.logger.ErrorCtx(ctx, "cannot get magic link email", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
var continueURL *string
|
||||
|
||||
switch {
|
||||
case session == nil:
|
||||
var err error
|
||||
identity, session, continueURL, err = r.iam.AuthService.OpenSessionWithMagicLink(ctx, input.Token)
|
||||
if err != nil {
|
||||
var errInvalidToken *iam.ErrInvalidToken
|
||||
if errors.As(err, &errInvalidToken) {
|
||||
return nil, gqlutils.Invalid(ctx, err)
|
||||
}
|
||||
|
||||
r.logger.ErrorCtx(ctx, "cannot open session with magic link", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
case identity.EmailAddress != email:
|
||||
if err := r.iam.SessionService.CloseSession(ctx, session.ID); err != nil {
|
||||
r.logger.ErrorCtx(ctx, "cannot close session", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
|
||||
var err error
|
||||
identity, session, continueURL, err = r.iam.AuthService.OpenSessionWithMagicLink(ctx, input.Token)
|
||||
if err != nil {
|
||||
var errInvalidToken *iam.ErrInvalidToken
|
||||
if errors.As(err, &errInvalidToken) {
|
||||
return nil, gqlutils.Invalid(ctx, err)
|
||||
}
|
||||
|
||||
r.logger.ErrorCtx(ctx, "cannot open session with magic link", log.Error(err))
|
||||
return nil, gqlutils.Internal(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
trustCenter := compliancepage.CompliancePageFromContext(ctx)
|
||||
trustService := r.TrustService(ctx, trustCenter.ID.TenantID())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user