From 2c7704774deff21af5a2817299cce2e530da9f9a Mon Sep 17 00:00:00 2001 From: Tung Wu Date: Thu, 25 Apr 2024 16:52:58 +0800 Subject: [PATCH 1/2] Throw error in case of account linking in promote flow --- .../declarative/intent_promote_flow.go | 16 ++++++++++ .../node_promote_identity_login_id.go | 27 +++++++++++++++- .../node_promote_identity_oauth.go | 31 ++++++++++++++++++- 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/pkg/lib/authenticationflow/declarative/intent_promote_flow.go b/pkg/lib/authenticationflow/declarative/intent_promote_flow.go index 14c6977e846..829bfb3c8be 100644 --- a/pkg/lib/authenticationflow/declarative/intent_promote_flow.go +++ b/pkg/lib/authenticationflow/declarative/intent_promote_flow.go @@ -25,6 +25,8 @@ type IntentPromoteFlow struct { var _ authflow.PublicFlow = &IntentPromoteFlow{} var _ authflow.EffectGetter = &IntentPromoteFlow{} +var _ authflow.Milestone = &IntentPromoteFlow{} +var _ MilestoneAccountLinkingConfigGetter = &IntentPromoteFlow{} func (*IntentPromoteFlow) Kind() string { return "IntentPromoteFlow" @@ -146,6 +148,20 @@ func (i *IntentPromoteFlow) GetEffects(ctx context.Context, deps *authflow.Depen }, nil } +func (i *IntentPromoteFlow) Milestone() {} +func (i *IntentPromoteFlow) MilestoneAccountLinkingConfigGetter(deps *authflow.Dependencies) (*config.AuthenticationFlowAccountLinking, error) { + flowRootObject, err := i.FlowRootObject(deps) + if err != nil { + return nil, err + } + // Promote flow is using AuthenticationFlowSignupFlow + signupFlow, ok := flowRootObject.(*config.AuthenticationFlowSignupFlow) + if !ok { + panic("flow root object is not signup flow in promote flow intent") + } + return signupFlow.AccountLinking, nil +} + func (i *IntentPromoteFlow) anonymousIdentity(f *authflow.Flow) *identity.Info { m, ok := authflow.FindMilestone[MilestoneDoUseAnonymousUser](f) if !ok { diff --git a/pkg/lib/authenticationflow/declarative/node_promote_identity_login_id.go b/pkg/lib/authenticationflow/declarative/node_promote_identity_login_id.go index 1bc99891030..165b9ae64be 100644 --- a/pkg/lib/authenticationflow/declarative/node_promote_identity_login_id.go +++ b/pkg/lib/authenticationflow/declarative/node_promote_identity_login_id.go @@ -12,6 +12,7 @@ import ( authflow "github.com/authgear/authgear-server/pkg/lib/authenticationflow" "github.com/authgear/authgear-server/pkg/lib/authn/identity" "github.com/authgear/authgear-server/pkg/lib/config" + "github.com/authgear/authgear-server/pkg/util/slice" ) func init() { @@ -71,12 +72,22 @@ func (n *NodePromoteIdentityLoginID) ReactTo(ctx context.Context, deps *authflow // promote if apierrors.IsKind(err, api.UserNotFound) { spec := n.makeLoginIDSpec(loginID) + + _, conflicts, err := n.checkConflictByAccountLinkings(ctx, deps, flows, spec) + if len(conflicts) > 0 { + // In promote flow, always error if any conflicts occurs + conflictSpecs := slice.Map(conflicts, func(i *identity.Info) *identity.Spec { + s := i.ToSpec() + return &s + }) + return nil, identityFillDetailsMany(api.ErrDuplicatedIdentity, spec, conflictSpecs) + } + info, err := newIdentityInfo(deps, n.UserID, spec) if err != nil { return nil, err } - // TODO(tung): Check for account linking return authflow.NewNodeSimple(&NodeDoCreateIdentity{ Identity: info, }), nil @@ -124,3 +135,17 @@ func (n *NodePromoteIdentityLoginID) makeLoginIDSpec(loginID string) *identity.S return spec } + +func (n *NodePromoteIdentityLoginID) checkConflictByAccountLinkings( + ctx context.Context, + deps *authflow.Dependencies, + flows authflow.Flows, + spec *identity.Spec) (config config.AccountLinkingConfigObject, conflicts []*identity.Info, err error) { + switch spec.Type { + case model.IdentityTypeLoginID: + // account linking of login id is not implemented at the moment + return nil, []*identity.Info{}, nil + default: + panic("unexpected spec type") + } +} diff --git a/pkg/lib/authenticationflow/declarative/node_promote_identity_oauth.go b/pkg/lib/authenticationflow/declarative/node_promote_identity_oauth.go index 1d440ce23b8..5abdd04196a 100644 --- a/pkg/lib/authenticationflow/declarative/node_promote_identity_oauth.go +++ b/pkg/lib/authenticationflow/declarative/node_promote_identity_oauth.go @@ -7,8 +7,12 @@ import ( "github.com/authgear/authgear-server/pkg/api" "github.com/authgear/authgear-server/pkg/api/apierrors" + "github.com/authgear/authgear-server/pkg/api/model" authflow "github.com/authgear/authgear-server/pkg/lib/authenticationflow" + "github.com/authgear/authgear-server/pkg/lib/authn/identity" "github.com/authgear/authgear-server/pkg/lib/authn/sso" + "github.com/authgear/authgear-server/pkg/lib/config" + "github.com/authgear/authgear-server/pkg/util/slice" ) func init() { @@ -65,13 +69,22 @@ func (n *NodePromoteIdentityOAuth) ReactTo(ctx context.Context, deps *authflow.D _, err = findExactOneIdentityInfo(deps, spec) if err != nil { if apierrors.IsKind(err, api.UserNotFound) { + _, conflicts, err := n.checkConflictByAccountLinkings(ctx, deps, flows, spec) + if len(conflicts) > 0 { + // In promote flow, always error if any conflicts occurs + conflictSpecs := slice.Map(conflicts, func(i *identity.Info) *identity.Spec { + s := i.ToSpec() + return &s + }) + return nil, identityFillDetailsMany(api.ErrDuplicatedIdentity, spec, conflictSpecs) + } + // promote info, err := newIdentityInfo(deps, n.UserID, spec) if err != nil { return nil, err } - // TODO(tung): Check for account linking return authflow.NewNodeSimple(&NodeDoCreateIdentity{ Identity: info, }), nil @@ -107,3 +120,19 @@ func (n *NodePromoteIdentityOAuth) OutputData(ctx context.Context, deps *authflo return data, nil } + +func (n *NodePromoteIdentityOAuth) checkConflictByAccountLinkings( + ctx context.Context, + deps *authflow.Dependencies, + flows authflow.Flows, + spec *identity.Spec) (config config.AccountLinkingConfigObject, conflicts []*identity.Info, err error) { + switch spec.Type { + case model.IdentityTypeOAuth: + return linkByOAuthIncomingOAuthSpec(ctx, deps, flows, &CreateIdentityRequestOAuth{ + Alias: n.Alias, + Spec: spec, + }) + default: + panic("unexpected spec type") + } +} From 479f8fa349ab6c047e9950907c7713abba306e03 Mon Sep 17 00:00:00 2001 From: Tung Wu Date: Thu, 25 Apr 2024 18:21:54 +0800 Subject: [PATCH 2/2] Fix error is not checked --- .../declarative/node_promote_identity_login_id.go | 3 +++ .../declarative/node_promote_identity_oauth.go | 3 +++ 2 files changed, 6 insertions(+) diff --git a/pkg/lib/authenticationflow/declarative/node_promote_identity_login_id.go b/pkg/lib/authenticationflow/declarative/node_promote_identity_login_id.go index 165b9ae64be..92e8e4e68ab 100644 --- a/pkg/lib/authenticationflow/declarative/node_promote_identity_login_id.go +++ b/pkg/lib/authenticationflow/declarative/node_promote_identity_login_id.go @@ -74,6 +74,9 @@ func (n *NodePromoteIdentityLoginID) ReactTo(ctx context.Context, deps *authflow spec := n.makeLoginIDSpec(loginID) _, conflicts, err := n.checkConflictByAccountLinkings(ctx, deps, flows, spec) + if err != nil { + return nil, err + } if len(conflicts) > 0 { // In promote flow, always error if any conflicts occurs conflictSpecs := slice.Map(conflicts, func(i *identity.Info) *identity.Spec { diff --git a/pkg/lib/authenticationflow/declarative/node_promote_identity_oauth.go b/pkg/lib/authenticationflow/declarative/node_promote_identity_oauth.go index 5abdd04196a..badd8328cbb 100644 --- a/pkg/lib/authenticationflow/declarative/node_promote_identity_oauth.go +++ b/pkg/lib/authenticationflow/declarative/node_promote_identity_oauth.go @@ -70,6 +70,9 @@ func (n *NodePromoteIdentityOAuth) ReactTo(ctx context.Context, deps *authflow.D if err != nil { if apierrors.IsKind(err, api.UserNotFound) { _, conflicts, err := n.checkConflictByAccountLinkings(ctx, deps, flows, spec) + if err != nil { + return nil, err + } if len(conflicts) > 0 { // In promote flow, always error if any conflicts occurs conflictSpecs := slice.Map(conflicts, func(i *identity.Info) *identity.Spec {