解析POST请求响应获取OAuth访问密钥的技术疑问
我发送了一个看似成功的POST HttpWebRequest,收到了15个包含数据的响应头(result.Headers.Count - 1)。其中result.Headers(13)的内容为:
fpc=Arg8nm0VqblMnu3rWck9GCw; expires=Wed, 05-Jun-2024 15:59:45 GMT; path=/; secure; HttpOnly; SameSite=None,esctx=PAQABBwEAAADnfolhJpSnRYB1SVj-Hgd8jINyVhrdWcuTdgm378vqo8Qo9ZgPGeuBNHyLhH1nZC8AfCBrfkJjbWVgfmt1yGtOCMmbLDUwDm4pPKp2qiUmCJHs5cnVcv--Oc4Q9LsQLS9m0znPAPGdAojpzBNGZ6tQPQTnroP24HSg4I53tNhF4j-u2orVUJBod72dh620NqggAA; domain=.login.microsoftonline.com; path=/; secure; HttpOnly; SameSite=None,x-ms-gateway-slice=estsfd; path=/; secure; httponly,stsservicecookie=estsfd; path=/; secure; httponly
在该响应头中我看到了esctx=PAQABBwEAAADnfolhJpSnRYB1SVj-Hgd8jINyVhrdWcuTdgm378vqo8Qo9ZgPGeuBNHyLhH1nZC8AfCBrfkJjbWVgfmt1yGtOCMmbLDUwDm4pPKp2qiUmCJHs5cnVcv--Oc4Q9LsQLS9m0znPAPGdAojpzBNGZ6tQPQTnroP24HSg4I53tNhF4j-u2orVUJBod72dh620NqggAA;。请问这是不是我需要的OAuth响应访问密钥?如果是的话,我该如何将其解析出来?
以下是实际的POST请求代码:
Private Sub RunRequest() Dim s As HttpWebRequest Dim enc As UTF8Encoding Dim postdata As String Dim postdatabytes As Byte() Dim url As String = ("https://login.microsoftonline.com/ca4f5969-c10f-40d4-8127-e74b691f95de/v2.0/.well-known/openid-configuration") 'Dim url As String = ("https://login.microsoftonline.com/ca4f5969-c10f-40d4-8127-e74b691f95de/oauth2/v2.0/token") s = HttpWebRequest.Create(url) enc = New System.Text.UTF8Encoding() postdata = "client_id=4e502cbc-a55f-4341-a498-69cfbe19ee7b&client_secret=0Ag8Q~QgsWJ55mz9SWG6hf22b_7mZ2m~.nInpagc&grant_type=client_credentials&scope=https://tffproduction.onmicrosoft.com/04cc9749-dbe5-4914-b262-d866b907756b/.default" postdatabytes = enc.GetBytes(postdata) s.Method = "POST" s.ContentType = "application/x-www-form-urlencoded" s.ContentLength = postdatabytes.Length Using stream = s.GetRequestStream() stream.Write(postdatabytes, 0, postdatabytes.Length) End Using Dim result As WebResponse Try result = s.GetResponse() Dim breakpoint As String = Nothing Catch ex As Exception Dim errmsg As String = ex.Message End Try Dim sb As New StringBuilder Dim hdkey As String For I As Int32 = 0 To result.Headers.Count - 1 hdkey = result.Headers(I) sb.Append(result.Headers(I)) sb.AppendLine() Next Dim Hdrs As String = sb.ToString End Sub
1. esctx不是OAuth访问密钥
esctx是Azure AD生成的会话上下文Cookie,用于跟踪应用的认证会话状态,和OAuth 2.0的access_token(访问密钥)完全不是一回事。真正的访问令牌会在请求token端点的响应体中返回,格式为JSON。
2. 请求的核心错误修正
你当前请求的URL是OpenID配置发现端点(/.well-known/openid-configuration),这个端点仅接受GET请求,用于获取Azure AD的认证元数据,不会处理POST类型的token请求。你需要改用代码中被注释掉的token端点URL:https://login.microsoftonline.com/ca4f5969-c10f-40d4-8127-e74b691f95de/oauth2/v2.0/token。
3. 获取并解析真正的访问令牌
修改URL后,请求的响应体是JSON格式,包含access_token、token_type、expires_in等核心字段。你需要读取响应体并解析JSON,示例代码如下:
Private Sub RunRequest() Dim s As HttpWebRequest Dim enc As UTF8Encoding Dim postdata As String Dim postdatabytes As Byte() ' 使用正确的token端点 Dim url As String = ("https://login.microsoftonline.com/ca4f5969-c10f-40d4-8127-e74b691f95de/oauth2/v2.0/token") s = HttpWebRequest.Create(url) enc = New System.Text.UTF8Encoding() postdata = "client_id=4e502cbc-a55f-4341-a498-69cfbe19ee7b&client_secret=0Ag8Q~QgsWJ55mz9SWG6hf22b_7mZ2m~.nInpagc&grant_type=client_credentials&scope=https://tffproduction.onmicrosoft.com/04cc9749-dbe5-4914-b262-d866b907756b/.default" postdatabytes = enc.GetBytes(postdata) s.Method = "POST" s.ContentType = "application/x-www-form-urlencoded" s.ContentLength = postdatabytes.Length Using stream = s.GetRequestStream() stream.Write(postdatabytes, 0, postdatabytes.Length) End Using Dim result As WebResponse Try result = s.GetResponse() ' 读取响应体 Using reader As New StreamReader(result.GetResponseStream()) Dim responseJson As String = reader.ReadToEnd() ' 解析JSON(示例使用System.Text.Json) Dim tokenObj = JsonSerializer.Deserialize(Of Dictionary(Of String, Object))(responseJson) If tokenObj.ContainsKey("access_token") Then Dim accessToken As String = tokenObj("access_token").ToString() ' 此处获取到真正的访问令牌 End If End Using Catch ex As Exception Dim errmsg As String = ex.Message End Try End Sub
4. 若需解析esctx的值
虽然它不是访问密钥,但如果需要提取该字段的值,可以通过字符串拆分实现:
' 假设headers13是拿到的result.Headers(13)内容 Dim headers13 As String = "fpc=Arg8nm0VqblMnu3rWck9GCw; expires=Wed, 05-Jun-2024 15:59:45 GMT; path=/; secure; HttpOnly; SameSite=None,esctx=PAQABBwEAAADnfolhJpSnRYB1SVj-Hgd8jINyVhrdWcuTdgm378vqo8Qo9ZgPGeuBNHyLhH1nZC8AfCBrfkJjbWVgfmt1yGtOCMmbLDUwDm4pPKp2qiUmCJHs5cnVcv--Oc4Q9LsQLS9m0znPAPGdAojpzBNGZ6tQPQTnroP24HSg4I53tNhF4j-u2orVUJBod72dh620NqggAA; domain=.login.microsoftonline.com; path=/; secure; HttpOnly; SameSite=None,x-ms-gateway-slice=estsfd; path=/; secure; httponly,stsservicecookie=estsfd; path=/; secure; httponly" ' 按逗号拆分多个Cookie项 Dim cookies = headers13.Split(","c) For Each cookie In cookies If cookie.Trim().StartsWith("esctx=") Then ' 拆分键值对,提取等号后内容并去除末尾分号 Dim esctxValue = cookie.Trim().Split("="c)(1).TrimEnd(";"c) ' esctxValue即为目标内容 Exit For End If Next
内容的提问来源于stack exchange,提问作者dashley

