在 Azure Active Directory B2C 中使用 OpenID Connect 进行 Web 登录会得到 id_token 而不是 access_token

Web sign-in with OpenID Connect in Azure Active Directory B2C gives id_token instead of access_token

我正在遵循 Microsoft 的指南:

https://docs.microsoft.com/en-us/azure/active-directory-b2c/openid-connect

发送第一个身份验证请求会得到预期的 codeid_token 响应。

GET https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/authorize?
client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6
&response_type=code+id_token
&redirect_uri=https%3A%2F%2Faadb2cplayground.azurewebsites.net%2F
&response_mode=form_post
&scope=openid%20offline_access
&state=arbitrary_data_you_can_receive_in_the_response
&nonce=12345

.ts 文件,Microsoft 示例值,但为清楚起见添加。

export const login = async () => {
    // window.location.origin is safe due to specified Redirect URIs for ADB2C
    window.location.href = "https://{tenant}.b2clogin.com/tfp/{tenant}.onmicrosoft.com/B2C_1_signupsignin/oauth2/v2.0/authorize?"
        + "client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6"
        + "&nonce=anyRandomValue"
        + "&redirect_uri=" + window.location.origin + "/signin-oidc"
        + "&scope=openid%20offline_access"
        + "&response_type=code+id_token";
}

但是获取令牌请求:

POST {tenant}.onmicrosoft.com/{policy}/oauth2/v2.0/token HTTP/1.1
Host: {tenant}.b2clogin.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&client_id=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6&scope=90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 offline_access&code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...&redirect_uri=urn:ietf:wg:oauth:2.0:oob

根据例子应该return这样:

{
    "not_before": "1442340812",
    "token_type": "Bearer",
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
    "scope": "90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 offline_access",
    "expires_in": "3600",
    "refresh_token": "AAQfQmvuDy8WtUv-sd0TBwWVQs1rC-Lfxa_NDkLqpg50Cxp5Dxj0VPF1mx2Z...",
}

我得到的是一个新的 id_token:

{
    "id_token": "eyJ0eXAiOiJKV...",
    "token_type": "Bearer",
    "not_before": 1602766192,
    "id_token_expires_in": 3600,
    "profile_info": "eyJ2ZXIiOiIxL...",
    "scope": "offline_access openid",
    "refresh_token": "eyJraWQiOiJjc...",
    "refresh_token_expires_in": 1209600
}

C#:

var client = _clientFactory.CreateClient();

var kvpList = new List<KeyValuePair<string, string>>();
kvpList.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
kvpList.Add(new KeyValuePair<string, string>("client_id", "90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6"));
kvpList.Add(new KeyValuePair<string, string>("scope", "90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6 offline_access"));
kvpList.Add(new KeyValuePair<string, string>("code", {code}));
kvpList.Add(new KeyValuePair<string, string>("redirect_uri", HttpContext.Request.Scheme + "://" + HttpContext.Request.Host + "/signin-oidc"));
kvpList.Add(new KeyValuePair<string, string>("client_secret", "{mySecret}"));

var req = new HttpRequestMessage(HttpMethod.Post, "https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/B2C_1_signupsignin/oauth2/v2.0/token")
{ Content = new FormUrlEncodedContent(kvpList) };

using var httpResponse = await client.SendAsync(req);

var response = await httpResponse.Content.ReadAsStringAsync();

我错过了什么?

当您请求“openid offline_access”时,您只需要 id-token 和一个刷新令牌。要获取访问令牌,您需要请求与您要访问的 resource/API 关联的范围。

确实是范围错误。从您的 Azure AD B2C 应用程序注册或应用程序(旧版)中获取它。

我的例子被阅读了

https://{tenant}.onmicrosoft.com/90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6/read

TS:

"&scope=openid%20offline_access%20https://{tenant}.onmicrosoft.com/90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6/read"

C#:

kvpList.Add(new KeyValuePair<string, string>("scope", "openid offline_access https://{tenant}.onmicrosoft.com/90c0fe63-bcf2-44d5-8fb7-b8bbc0b29dc6/read"));

在此之后一切正常。