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

使用Basic4Android通过Refresh Token获取新Token时遇503错误排查

问题:使用Refresh Token获取MS Graph新访问令牌时返回Error 503(AADSTS40008)

我在Basic4Android中编写了通过Refresh Token获取新访问令牌的代码,但始终返回Error 503,错误代码为AADSTS40008。已尝试更换不同端点和重定向URL,问题依旧。请求检查POST数据格式和请求端点是否正确。

返回的错误信息

{"error":"server_error","error_description":"AADSTS40008: There was an unexpected error from the external identity provider.\r\nTrace ID: 866cab93-5042-43d1-9331-fe5f9b005100\r\nCorrelation ID: 06250287-46ed-4511-9610-fea73d2ea737\r\nTimestamp: 2023-10-20 17:19:41Z","error_codes":[40008],"timestamp":"2023-10-20 17:19:41Z","trace_id":"866cab93-5042-43d1-9331-fe5f9b005100","correlation_id":"06250287-46ed-4511-9610-fea73d2ea737","error_uri":"https://login.microsoftonline.com/error?code=40008"}

现有代码

Sub RefreshAccessToken(refToken As String) As ResumableSub
    Log("RefreshAccessToken Called with refToken: " & refToken)

    If CheckConnection = False Then
        Log("No network connection. Aborted.")
        Return Null
    End If

    Dim params As Map
    params.Initialize
    params.Put("client_id", ConfigData.clientID)
    params.Put("client_secret", ConfigData.clientSecret)
    params.Put("refresh_token", refToken)
    params.Put("grant_type", "refresh_token")
    'params.Put("scope", ConfigData.clientID & "/.default openid profile offline_access")
    params.Put("scope", "openid profile offline_access https://graph.microsoft.com/.default")
    params.Put("tenant", ConfigData.clientTenant)
    params.Put("redirect_uri", ConfigData.redirectURI)
    Log("Parameters set up.")

    Dim SB As StringBuilder
    SB.Initialize
    For Each key As String In params.Keys
        SB.Append(key).Append("=").Append(params.Get(key)).Append("&")
    Next
    SB.Remove(SB.Length - 1, SB.Length)
    Log("POST data prepared.")

    Try
        'hc.Initialize("hc")
        Log("POST Data: " & SB.ToString)
        req.InitializePost2("https://login.microsoftonline.com/" & ConfigData.clientTenant & "/oauth2/v2.0/token", SB.ToString.GetBytes("UTF8"))
        req.SetContentType("application/x-www-form-urlencoded")
        hc.Execute(req, 1)
        Log("HTTP request executed.")
        'Log("Full URL: " & "https://login.microsoftonline.com/" & ConfigData.clientTenant & "/oauth2/v2.0/token" & SB.ToString.GetBytes("UTF8"))
        Wait For hc_ResponseSuccess (Response As OkHttpResponse, TaskId As Int)
        Wait For hc_ResponseError (Response As OkHttpResponse, Reason As String, StatusCode As Int, TaskId As Int)
        Log("HTTP Response Status: " & Response & " Status Code =" & StatusCode & "Task ID = " & TaskId)
        Log("hc_ResponseSuccess triggered.")
        
        If TaskId = 1 Then
            Response.GetAsynchronously("response", File.OpenOutput(File.DirInternalCache, "response.txt", False), True, TaskId)
            Log("Response being gotten asynchronously.")
            Wait For response_StreamFinish (Success As Boolean, TaskId As Int)
            Log("response_StreamFinish triggered.")
            
            If Success Then
                Try
                    Dim parser As JSONParser
                    parser.Initialize(File.ReadString(File.DirInternalCache, "response.txt"))
                    Dim root As Map = parser.NextObject
                    Log("JSON parsed successfully.")
                    
                    Dim newAccessToken As String = root.Get("access_token")
                    Dim newRefreshToken As String = root.Get("refresh_token")
                    Dim newExpiresIn As Long = root.Get("expires_in")
                    
                    SaveTokens(newAccessToken, newRefreshToken, newExpiresIn, SubFolderID, MainFolderID)
                    Log("Tokens saved successfully.")
                    
                    Return Success  ' Successfully refreshed the token
                Catch
                    Log("JSON Parsing failed: " & LastException.Message)
                    Return Null  ' Failed due to JSON parsing
                End Try
            Else
                Log("Error in response_StreamFinish: " & LastException.Message)
                Return False  ' Failed due to stream finish
            End If
        Else
            Log("Unexpected TaskId: " & TaskId)
            Return Null  ' TaskId doesn't match, ignore
        End If
    Catch
        Log("HTTP Request failed: " & LastException.Message)
        Return Null  ' Failed due to HTTP request
    End Try
End Sub

问题分析与修复建议

1. POST参数问题

  • 冗余的tenant参数:URL路径中已经包含租户ID,POST参数无需重复提交,直接删除params.Put("tenant", ConfigData.clientTenant)。
  • 参数未做URL编码:代码直接拼接参数值,若client_secret、refresh_token等包含&、=、%等特殊字符,会导致服务端解析参数错误,这是核心问题。需用B4A的StringUtils.EncodeUrl方法对每个参数值进行URL编码。
  • redirect_uri验证:若提交该参数,必须和获取refresh token时使用的redirect_uri完全一致;若是机密客户端(使用client_secret),可省略该参数。

2. HTTP请求逻辑问题

  • 同时监听Success和Error事件:当前逻辑会导致事件触发混乱,应使用Wait For (hc.Execute(req, 1)) Complete统一处理成功/失败情况,避免空指针异常。

修改后的代码片段

Sub RefreshAccessToken(refToken As String) As ResumableSub
    Log("RefreshAccessToken Called with refToken: " & refToken)

    If CheckConnection = False Then
        Log("No network connection. Aborted.")
        Return Null
    End If

    Dim params As Map
    params.Initialize
    params.Put("client_id", ConfigData.clientID)
    params.Put("client_secret", ConfigData.clientSecret)
    params.Put("refresh_token", refToken)
    params.Put("grant_type", "refresh_token")
    params.Put("scope", "openid profile offline_access https://graph.microsoft.com/.default")
    params.Put("redirect_uri", ConfigData.redirectURI) ' 确保和授权时的URI完全一致
    Log("Parameters set up.")

    Dim SB As StringBuilder
    SB.Initialize
    Dim su As StringUtils
    For Each key As String In params.Keys
        ' 对参数值进行URL编码
        Dim encodedValue As String = su.EncodeUrl(params.Get(key), "UTF8")
        SB.Append(key).Append("=").Append(encodedValue).Append("&")
    Next
    SB.Remove(SB.Length - 1, SB.Length)
    Log("POST Data: " & SB.ToString)

    Try
        req.InitializePost2("https://login.microsoftonline.com/" & ConfigData.clientTenant & "/oauth2/v2.0/token", SB.ToString.GetBytes("UTF8"))
        req.SetContentType("application/x-www-form-urlencoded")
        
        ' 统一处理请求结果
        Wait For (hc.Execute(req, 1)) Complete (Success As Boolean, Response As OkHttpResponse, Reason As String, StatusCode As Int)
        Log("HTTP Response Status Code: " & StatusCode)
        
        If Success Then
            Response.GetAsynchronously("response", File.OpenOutput(File.DirInternalCache, "response.txt", False), True, 1)
            Wait For response_StreamFinish (StreamSuccess As Boolean, TaskId As Int)
            
            If StreamSuccess Then
                Try
                    Dim parser As JSONParser
                    parser.Initialize(File.ReadString(File.DirInternalCache, "response.txt"))
                    Dim root As Map = parser.NextObject
                    
                    Dim newAccessToken As String = root.Get("access_token")
                    Dim newRefreshToken As String = root.Get("refresh_token")
                    Dim newExpiresIn As Long = root.Get("expires_in")
                    
                    SaveTokens(newAccessToken, newRefreshToken, newExpiresIn, SubFolderID, MainFolderID)
                    Log("Tokens saved successfully.")
                    Return True
                Catch
                    Log("JSON Parsing failed: " & LastException.Message)
                    Return Null
                End Try
            Else
                Log("Stream finish failed: " & LastException.Message)
                Return False
            End If
        Else
            Log("HTTP Request failed: " & Reason & ", Status Code: " & StatusCode)
            ' 输出完整错误响应便于排查
            If Response <> Null Then
                Dim errorText As String = su.InputStreamToString(Response.ErrorStream, "UTF8")
                Log("Error Response: " & errorText)
            End If
            Return Null
        End If
    Catch
        Log("Exception: " & LastException.Message)
        Return Null
    End Try
End Sub

额外检查项

  • 确认refresh_token未过期且有效,若令牌失效需重新引导用户授权。
  • 检查Azure AD应用注册的权限配置,确保offline_access权限已被授予。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 04:44:57