@@ -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
5866var _ 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 ,
0 commit comments