You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Authy迁移至Twilio Verify后用户未验证问题求助

Authy 迁移至 Twilio Verify API 后验证失败问题排查

我们此前参考相关步骤将Authy迁移至Verify API,但迁移完成后用户仍无法完成验证。以下是使用的代码:

迁移主逻辑代码

Dim oAuthy = New clsAuthy(apiKey, False)

'Fetch details from authy to migrate to verify
Dim authyDetails As clsAuthySecret = oAuthy.GetAuthyDetails(item("TwilioAuthyId"))

oAuthy = Nothing

'Migrate data to verify API
With oVerify
    .GenerateQRCode(item("UserName"), item("UserId").ToString(), authyDetails.Secret)

    .VerifyToken(.FactorID, authyDetails.OTP, item("UserId").ToString())

    FactorId = .FactorID
    VerifyUrl = .QrUrl
End With

Authy 信息导出方法

Public Function GetAuthyDetails(ByRef AuthyID As String) As clsAuthySecret

    Dim apiResponse As clsAuthySecret
    Dim url = String.Format("{0}/protected/json/users/{1}/secret/export", Me.baseUrl, AuthyID, Me.apikey)

    Try
        client.Headers.Set("X-Authy-API-Key", Me.apikey)

        Dim response = client.DownloadString(url)
        apiResponse = JsonConvert.DeserializeObject(Of clsAuthySecret)(response)
        apiResponse.RawResponse = response
    Catch ex As WebException
        apiResponse = New clsAuthySecret()
        apiResponse.Status = AuthyStatus.BadRequest 'bad request
        apiResponse.Message = ex.Message
        'apiResponse.RawResponse = ex.Response.ToString()
    End Try

    If (apiResponse.Success) Then
        apiResponse.Status = AuthyStatus.Success
    End If

    Return apiResponse
End Function

Verify API 相关方法

Public Function GenerateQRCode(ByVal Email As String, 
                               ByVal UserID As String,
                               ByVal Secret As String
                               ) As Task(Of Boolean)
    Try
        TwilioClient.Init(_accountSID, _authToken)
        Dim newFactor = NewFactorResource.Create(friendlyName:=Email,
                                                 factorType:=NewFactorResource.FactorTypesEnum.Totp,
                                                 pathServiceSid:=_serviceSID,
                                                 pathIdentity:=UserID.ToLower(),
                                                 bindingSecret:=Secret)

        _factorID = newFactor.Sid
        _qrUrl = JObject.Parse(newFactor.Binding.ToString())("uri")
    Catch ex As Exception
        _responseMessage = ex.Message
        Return False
    End Try

    Return True
End Function


Public Function VerifyToken(ByVal FactorID As String,
                            ByVal Token As String,
                            ByVal UserID As String
                            ) As Task(Of Boolean)
    Try
        TwilioClient.Init(_accountSID, _authToken)
        Dim factor = FactorResource.Update(authPayload:=Token,
                                           pathServiceSid:=_serviceSID,
                                           pathIdentity:=UserID.ToLower(),
                                           pathSid:=FactorID)

        If factor.Status.ToString = "verified" Then
            Return True
        Else
            Return False
        End If
    Catch ex As Exception
        _responseMessage = ex.Message
        Return False
    End Try
End Function

关键问题与遗漏步骤分析

  • 异步方法未正确等待:GenerateQRCode和VerifyToken均为异步方法(返回Task(Of Boolean)),但调用时未使用Await关键字,会导致代码执行顺序混乱——比如还未成功创建Factor就发起验证请求,或FactorID未正确赋值就传入验证方法。
  • 验证Token的API调用错误:当前VerifyToken方法使用FactorResource.Update验证Token,这是错误的。Twilio Verify API中验证TOTP Token应使用VerifyFactorResource.Create方法,FactorResource.Update仅用于更新Factor属性(如友好名称),不负责验证操作。
  • Secret编码格式检查:确认从Authy导出的authyDetails.Secret是否为Base32编码格式。Twilio Verify的bindingSecret要求必须是Base32编码字符串,若Authy返回的是其他编码(如Hex),需先转换为Base32格式。
  • 错误信息不完整:Catch块仅记录Exception.Message,建议捕获WebException时读取响应流内容,获取Twilio返回的具体错误信息,便于精准定位问题。

修正后的核心代码示例

异步调用修正

Dim oAuthy = New clsAuthy(apiKey, False)

'Fetch details from authy to migrate to verify
Dim authyDetails As clsAuthySecret = oAuthy.GetAuthyDetails(item("TwilioAuthyId"))

oAuthy = Nothing

'Migrate data to verify API - 使用Await等待异步方法完成
With oVerify
    Await .GenerateQRCode(item("UserName"), item("UserId").ToString(), authyDetails.Secret)

    Dim verifySuccess = Await .VerifyToken(.FactorID, authyDetails.OTP, item("UserId").ToString())

    FactorId = .FactorID
    VerifyUrl = .QrUrl
End With

验证方法修正

Public Async Function VerifyToken(ByVal FactorID As String,
                            ByVal Token As String,
                            ByVal UserID As String
                            ) As Task(Of Boolean)
    Try
        TwilioClient.Init(_accountSID, _authToken)
        ' 使用VerifyFactorResource.Create验证Token
        Dim verifyResult = VerifyFactorResource.Create(
            authPayload:=Token,
            pathServiceSid:=_serviceSID,
            pathIdentity:=UserID.ToLower(),
            pathSid:=FactorID
        )

        Return verifyResult.Status = "verified"
    Catch ex As Exception
        ' 记录完整错误信息
        If TypeOf ex Is WebException Then
            Using reader = New StreamReader(CType(ex, WebException).Response.GetResponseStream())
                _responseMessage = reader.ReadToEnd()
            End Using
        Else
            _responseMessage = ex.Message
        End If
        Return False
    End Try
End Function

内容的提问来源于stack exchange,提问作者Shivam Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 04:15:33