Skip to content

Commit

Permalink
Throw error if account linking occurs in promote flow
Browse files Browse the repository at this point in the history
DEV-1234
  • Loading branch information
louischan-oursky committed May 3, 2024
2 parents 5fd66aa + 479f8fa commit a04e8a5
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 2 deletions.
16 changes: 16 additions & 0 deletions pkg/lib/authenticationflow/declarative/intent_promote_flow.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -71,12 +72,25 @@ 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 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 {
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
Expand Down Expand Up @@ -124,3 +138,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")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -65,13 +69,25 @@ 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 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 {
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
Expand Down Expand Up @@ -107,3 +123,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")
}
}

0 comments on commit a04e8a5

Please sign in to comment.