Skip to content

Commit 43cb3fd

Browse files
authored
Put only the send-code operation in delayed one time function #5336
ref DEV-2964
2 parents 10ba2bd + 8f58319 commit 43cb3fd

4 files changed

Lines changed: 89 additions & 49 deletions

File tree

pkg/lib/authenticationflow/declarative/intent_authn_oob.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func (i *IntentAuthenticationOOB) ReactTo(ctx context.Context, deps *authflow.De
7777
return nil, authflow.ErrIncompatibleInput
7878
}
7979

80-
node := NewNodeAuthenticationOOB(&NodeAuthenticationOOB{
80+
node, err := NewNodeAuthenticationOOB(ctx, deps, &NodeAuthenticationOOB{
8181
JSONPointer: i.JSONPointer,
8282
UserID: i.UserID,
8383
Purpose: i.Purpose,
@@ -86,6 +86,9 @@ func (i *IntentAuthenticationOOB) ReactTo(ctx context.Context, deps *authflow.De
8686
Channel: channel,
8787
Authentication: i.Authentication,
8888
})
89+
if err != nil {
90+
return nil, err
91+
}
8992

9093
return node, nil
9194
}

pkg/lib/authenticationflow/declarative/intent_verify_claim.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func (i *IntentVerifyClaim) ReactTo(ctx context.Context, deps *authflow.Dependen
8585
return nil, authflow.ErrIncompatibleInput
8686
}
8787

88-
node := NewNodeVerifyClaim(&NodeVerifyClaim{
88+
node, err := NewNodeVerifyClaim(ctx, deps, &NodeVerifyClaim{
8989
JSONPointer: i.JSONPointer,
9090
UserID: i.UserID,
9191
Purpose: i.Purpose,
@@ -95,6 +95,9 @@ func (i *IntentVerifyClaim) ReactTo(ctx context.Context, deps *authflow.Dependen
9595
ClaimValue: i.ClaimValue,
9696
Channel: channel,
9797
})
98+
if err != nil {
99+
return nil, err
100+
}
98101

99102
return node, nil
100103
}

pkg/lib/authenticationflow/declarative/node_authn_oob.go

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,32 @@ type NodeAuthenticationOOB struct {
3535
Authentication model.AuthenticationFlowAuthentication `json:"authentication,omitempty"`
3636
}
3737

38-
func NewNodeAuthenticationOOB(n *NodeAuthenticationOOB) *authflow.NodeWithDelayedOneTimeFunction {
38+
func NewNodeAuthenticationOOB(ctx context.Context, deps *authflow.Dependencies, n *NodeAuthenticationOOB) (*authflow.NodeWithDelayedOneTimeFunction, error) {
3939
n.WebsocketChannelName = authflow.NewWebsocketChannelName()
40+
41+
kind := n.otpKind(deps)
42+
_, claimValue := n.Info.OOBOTP.ToClaimPair()
4043
simpleNode := authflow.NewNodeSimple(n)
44+
code, err := n.GenerateCode(ctx, deps)
45+
if ratelimit.IsRateLimitErrorWithBucketName(err, kind.RateLimitTriggerCooldown(claimValue).Name) {
46+
// Ignore trigger cooldown rate limit error; continue the flow
47+
code = ""
48+
} else if err != nil {
49+
return nil, err
50+
}
4151

4252
return &authflow.NodeWithDelayedOneTimeFunction{
4353
Node: simpleNode,
4454
DelayedOneTimeFunction: func(ctx context.Context, deps *authflow.Dependencies) error {
45-
kind := n.otpKind(deps)
46-
err := n.SendCode(ctx, deps)
47-
_, claimValue := n.Info.OOBOTP.ToClaimPair()
48-
if ratelimit.IsRateLimitErrorWithBucketName(err, kind.RateLimitTriggerCooldown(claimValue).Name) {
49-
// Ignore trigger cooldown rate limit error; continue the flow
50-
} else if err != nil {
51-
return err
55+
if code != "" {
56+
err := n.SendCode(ctx, deps, code)
57+
if err != nil {
58+
return err
59+
}
5260
}
5361
return nil
5462
},
55-
}
63+
}, nil
5664
}
5765

5866
var _ authflow.NodeSimple = &NodeAuthenticationOOB{}
@@ -155,11 +163,16 @@ func (n *NodeAuthenticationOOB) ReactTo(ctx context.Context, deps *authflow.Depe
155163
Claim: verifiedClaim,
156164
}), nil
157165
case inputNodeAuthenticationOOB.IsResend():
166+
code, err := n.GenerateCode(ctx, deps)
167+
if err != nil {
168+
return nil, err
169+
}
170+
158171
newSimpleNode := authflow.NewNodeSimple(n)
159172
return &authflow.NodeWithDelayedOneTimeFunction{
160173
Node: newSimpleNode,
161174
DelayedOneTimeFunction: func(ctx context.Context, deps *authflow.Dependencies) error {
162-
return n.SendCode(ctx, deps)
175+
return n.SendCode(ctx, deps, code)
163176
},
164177
}, authflow.ErrReplaceNode
165178
default:
@@ -242,19 +255,8 @@ func (n *NodeAuthenticationOOB) invalidOTPCodeError() error {
242255
}
243256
}
244257

245-
func (n *NodeAuthenticationOOB) SendCode(ctx context.Context, deps *authflow.Dependencies) error {
246-
// Here is a bit tricky.
247-
// Normally we should use the given message type to send a message.
248-
// However, if the channel is whatsapp, we use the specialized otp.MessageTypeWhatsappCode.
249-
// It is because otp.MessageTypeWhatsappCode will send a Whatsapp authentication message.
250-
// which is optimized for delivering a authentication code to the end-user.
251-
// See https://developers.facebook.com/docs/whatsapp/business-management-api/authentication-templates/
252-
typ := n.otpMessageType(n.Info)
253-
if n.Channel == model.AuthenticatorOOBChannelWhatsapp {
254-
typ = translation.MessageTypeWhatsappCode
255-
}
258+
func (n *NodeAuthenticationOOB) GenerateCode(ctx context.Context, deps *authflow.Dependencies) (string, error) {
256259
_, claimValue := n.Info.OOBOTP.ToClaimPair()
257-
258260
code, err := deps.OTPCodes.GenerateOTP(ctx,
259261
n.otpKind(deps),
260262
claimValue,
@@ -265,10 +267,25 @@ func (n *NodeAuthenticationOOB) SendCode(ctx context.Context, deps *authflow.Dep
265267
},
266268
)
267269
if err != nil {
268-
return err
270+
return "", err
269271
}
270272

271-
err = deps.OTPSender.Send(
273+
return code, nil
274+
}
275+
276+
func (n *NodeAuthenticationOOB) SendCode(ctx context.Context, deps *authflow.Dependencies, code string) error {
277+
// Here is a bit tricky.
278+
// Normally we should use the given message type to send a message.
279+
// However, if the channel is whatsapp, we use the specialized otp.MessageTypeWhatsappCode.
280+
// It is because otp.MessageTypeWhatsappCode will send a Whatsapp authentication message.
281+
// which is optimized for delivering a authentication code to the end-user.
282+
// See https://developers.facebook.com/docs/whatsapp/business-management-api/authentication-templates/
283+
typ := n.otpMessageType(n.Info)
284+
if n.Channel == model.AuthenticatorOOBChannelWhatsapp {
285+
typ = translation.MessageTypeWhatsappCode
286+
}
287+
_, claimValue := n.Info.OOBOTP.ToClaimPair()
288+
err := deps.OTPSender.Send(
272289
ctx,
273290
otp.SendOptions{
274291
Channel: n.Channel,

pkg/lib/authenticationflow/declarative/node_verify_claim.go

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,32 @@ type NodeVerifyClaim struct {
3434
WebsocketChannelName string `json:"websocket_channel_name,omitempty"`
3535
}
3636

37-
func NewNodeVerifyClaim(n *NodeVerifyClaim) *authflow.NodeWithDelayedOneTimeFunction {
37+
func NewNodeVerifyClaim(ctx context.Context, deps *authflow.Dependencies, n *NodeVerifyClaim) (*authflow.NodeWithDelayedOneTimeFunction, error) {
3838
n.WebsocketChannelName = authflow.NewWebsocketChannelName()
39+
40+
kind := n.otpKind(deps)
3941
simpleNode := authflow.NewNodeSimple(n)
42+
code, err := n.GenerateCode(ctx, deps)
43+
if ratelimit.IsRateLimitErrorWithBucketName(err, kind.RateLimitTriggerCooldown(n.ClaimValue).Name) {
44+
// Ignore trigger cooldown rate limit error; continue the flow
45+
code = ""
46+
} else if err != nil {
47+
return nil, err
48+
}
4049

4150
return &authflow.NodeWithDelayedOneTimeFunction{
4251
Node: simpleNode,
4352
DelayedOneTimeFunction: func(ctx context.Context, deps *authflow.Dependencies) error {
44-
kind := n.otpKind(deps)
45-
err := n.SendCode(ctx, deps)
46-
if ratelimit.IsRateLimitErrorWithBucketName(err, kind.RateLimitTriggerCooldown(n.ClaimValue).Name) {
47-
// Ignore trigger cooldown rate limit error; continue the flow
48-
} else if err != nil {
49-
return err
53+
if code != "" {
54+
err := n.SendCode(ctx, deps, code)
55+
if err != nil {
56+
return err
57+
}
5058
}
59+
5160
return nil
5261
},
53-
}
62+
}, nil
5463
}
5564

5665
var _ authflow.NodeSimple = &NodeVerifyClaim{}
@@ -133,11 +142,16 @@ func (n *NodeVerifyClaim) ReactTo(ctx context.Context, deps *authflow.Dependenci
133142
Claim: verifiedClaim,
134143
}), nil
135144
case inputNodeVerifyClaim.IsResend():
145+
code, err := n.GenerateCode(ctx, deps)
146+
if err != nil {
147+
return nil, err
148+
}
149+
136150
newSimpleNode := authflow.NewNodeSimple(n)
137151
return &authflow.NodeWithDelayedOneTimeFunction{
138152
Node: newSimpleNode,
139153
DelayedOneTimeFunction: func(ctx context.Context, deps *authflow.Dependencies) error {
140-
return n.SendCode(ctx, deps)
154+
return n.SendCode(ctx, deps, code)
141155
},
142156
}, authflow.ErrReplaceNode
143157
default:
@@ -208,18 +222,7 @@ func (n *NodeVerifyClaim) invalidOTPCodeError() error {
208222
}
209223
}
210224

211-
func (n *NodeVerifyClaim) SendCode(ctx context.Context, deps *authflow.Dependencies) error {
212-
// Here is a bit tricky.
213-
// Normally we should use the given message type to send a message.
214-
// However, if the channel is whatsapp, we use the specialized otp.MessageTypeWhatsappCode.
215-
// It is because otp.MessageTypeWhatsappCode will send a Whatsapp authentication message.
216-
// which is optimized for delivering a authentication code to the end-user.
217-
// See https://developers.facebook.com/docs/whatsapp/business-management-api/authentication-templates/
218-
typ := n.MessageType
219-
if n.Channel == model.AuthenticatorOOBChannelWhatsapp {
220-
typ = translation.MessageTypeWhatsappCode
221-
}
222-
225+
func (n *NodeVerifyClaim) GenerateCode(ctx context.Context, deps *authflow.Dependencies) (string, error) {
223226
code, err := deps.OTPCodes.GenerateOTP(ctx,
224227
n.otpKind(deps),
225228
n.ClaimValue,
@@ -230,10 +233,24 @@ func (n *NodeVerifyClaim) SendCode(ctx context.Context, deps *authflow.Dependenc
230233
},
231234
)
232235
if err != nil {
233-
return err
236+
return "", err
237+
}
238+
return code, nil
239+
}
240+
241+
func (n *NodeVerifyClaim) SendCode(ctx context.Context, deps *authflow.Dependencies, code string) error {
242+
// Here is a bit tricky.
243+
// Normally we should use the given message type to send a message.
244+
// However, if the channel is whatsapp, we use the specialized otp.MessageTypeWhatsappCode.
245+
// It is because otp.MessageTypeWhatsappCode will send a Whatsapp authentication message.
246+
// which is optimized for delivering a authentication code to the end-user.
247+
// See https://developers.facebook.com/docs/whatsapp/business-management-api/authentication-templates/
248+
typ := n.MessageType
249+
if n.Channel == model.AuthenticatorOOBChannelWhatsapp {
250+
typ = translation.MessageTypeWhatsappCode
234251
}
235252

236-
err = deps.OTPSender.Send(
253+
err := deps.OTPSender.Send(
237254
ctx,
238255
otp.SendOptions{
239256
Channel: n.Channel,

0 commit comments

Comments
 (0)