Skip to content

Commit 1c8f14a

Browse files
authored
Exclude identity conflicts of the same account #4497
ref DEV-1632
2 parents a3509f4 + 3933488 commit 1c8f14a

5 files changed

Lines changed: 118 additions & 4 deletions

File tree

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# https://linear.app/authgear/issue/DEV-1632/incorrectly-enter-account-linking-when-creating-two-identity-in-a-row
2+
name: Account linking - Incoming OAuth - DEV-1632
3+
authgear.yaml:
4+
override: |
5+
authentication:
6+
identities:
7+
- login_id
8+
- oauth
9+
identity:
10+
oauth:
11+
providers:
12+
- alias: google
13+
client_id: "google"
14+
type: google
15+
account_linking:
16+
oauth:
17+
- alias: google
18+
action: login_and_link
19+
oauth_claim:
20+
pointer: "/email"
21+
user_profile:
22+
pointer: "/email"
23+
authentication_flow:
24+
signup_flows:
25+
- name: f1
26+
steps:
27+
- type: identify
28+
one_of:
29+
- identification: oauth
30+
steps:
31+
- type: identify
32+
one_of:
33+
- identification: email
34+
steps:
35+
- action: "create"
36+
input: |
37+
{
38+
"type": "signup",
39+
"name": "f1"
40+
}
41+
output:
42+
result: |
43+
{
44+
"action": {
45+
"type": "identify"
46+
}
47+
}
48+
49+
- action: input
50+
input: |
51+
{
52+
"identification": "oauth",
53+
"alias": "google",
54+
"redirect_uri": "http://mock"
55+
}
56+
output:
57+
result: |
58+
{
59+
"action": {
60+
"type": "identify",
61+
"data": {
62+
"oauth_authorization_url": "[[string]]"
63+
}
64+
}
65+
}
66+
- action: oauth_redirect
67+
to: "{{ .prev.result.action.data.oauth_authorization_url }}"
68+
redirect_uri: http://mock
69+
output:
70+
result: |
71+
{
72+
"query": "[[string]]"
73+
}
74+
75+
- action: input
76+
input: |
77+
{
78+
"query": "{{ .prev.result.query }}"
79+
}
80+
output:
81+
result: |
82+
{
83+
"action": {
84+
"type": "identify"
85+
}
86+
}
87+
88+
- action: input
89+
input: |
90+
{
91+
"identification": "email",
92+
"login_id": "mock@example.com"
93+
}
94+
output:
95+
result: |
96+
{
97+
"action": {
98+
"type": "finished"
99+
}
100+
}

pkg/lib/authenticationflow/declarative/intent_check_conflict_and_create_identity.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,9 @@ func (i *IntentCheckConflictAndCreateIdenity) checkConflictByAccountLinkings(
8888
flows authflow.Flows) (conflicts []*AccountLinkingConflict, err error) {
8989
switch i.Request.Type {
9090
case model.IdentityTypeOAuth:
91-
return linkByIncomingOAuthSpec(ctx, deps, flows, i.Request.OAuth, i.JSONPointer)
91+
return linkByIncomingOAuthSpec(ctx, deps, flows, i.UserID, i.Request.OAuth, i.JSONPointer)
9292
case model.IdentityTypeLoginID:
93-
return linkByIncomingLoginIDSpec(ctx, deps, flows, i.Request.LoginID, i.JSONPointer)
93+
return linkByIncomingLoginIDSpec(ctx, deps, flows, i.UserID, i.Request.LoginID, i.JSONPointer)
9494
default:
9595
// Linking of other types are not supported at the moment
9696
return nil, nil

pkg/lib/authenticationflow/declarative/intent_promote_identity_login_id.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ func (n *IntentPromoteIdentityLoginID) checkConflictByAccountLinkings(
166166
spec *identity.Spec) (conflicts []*AccountLinkingConflict, err error) {
167167
switch spec.Type {
168168
case model.IdentityTypeLoginID:
169-
return linkByIncomingLoginIDSpec(ctx, deps, flows, NewCreateLoginIDIdentityRequest(spec).LoginID, n.JSONPointer)
169+
return linkByIncomingLoginIDSpec(ctx, deps, flows, n.UserID, NewCreateLoginIDIdentityRequest(spec).LoginID, n.JSONPointer)
170170
default:
171171
panic("unexpected spec type")
172172
}

pkg/lib/authenticationflow/declarative/node_promote_identity_oauth.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func (n *NodePromoteIdentityOAuth) checkConflictByAccountLinkings(
129129
spec *identity.Spec) (conflicts []*AccountLinkingConflict, err error) {
130130
switch spec.Type {
131131
case model.IdentityTypeOAuth:
132-
return linkByIncomingOAuthSpec(ctx, deps, flows, NewCreateOAuthIdentityRequest(n.Alias, spec).OAuth, n.JSONPointer)
132+
return linkByIncomingOAuthSpec(ctx, deps, flows, n.UserID, NewCreateOAuthIdentityRequest(n.Alias, spec).OAuth, n.JSONPointer)
133133
default:
134134
panic("unexpected spec type")
135135
}

pkg/lib/authenticationflow/declarative/utils_account_linking.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ func linkByIncomingOAuthSpec(
139139
ctx context.Context,
140140
deps *authflow.Dependencies,
141141
flows authflow.Flows,
142+
userID string,
142143
request *CreateIdentityRequestOAuth,
143144
identificationJSONPointer jsonpointer.T,
144145
) (conflicts []*AccountLinkingConflict, err error) {
@@ -191,6 +192,12 @@ func linkByIncomingOAuthSpec(
191192

192193
for _, iden := range idenConflicts {
193194
iden := iden
195+
196+
// Exclude identities that actually belong to this user.
197+
if iden.UserID == userID {
198+
continue
199+
}
200+
194201
// Exclude duplicates
195202
if _, exist := conflictedIdentityIDs[iden.ID]; exist {
196203
continue
@@ -227,6 +234,7 @@ func linkByIncomingLoginIDSpec(
227234
ctx context.Context,
228235
deps *authflow.Dependencies,
229236
flows authflow.Flows,
237+
userID string,
230238
request *CreateIdentityRequestLoginID,
231239
identificationJSONPointer jsonpointer.T,
232240
) (conflicts []*AccountLinkingConflict, err error) {
@@ -271,6 +279,12 @@ func linkByIncomingLoginIDSpec(
271279

272280
for _, iden := range idenConflicts {
273281
iden := iden
282+
283+
// Exclude identities that actually belong to this user.
284+
if iden.UserID == userID {
285+
continue
286+
}
287+
274288
// Exclude duplicates
275289
if _, exist := conflictedIdentityIDs[iden.ID]; exist {
276290
continue

0 commit comments

Comments
 (0)