通过下面的 C# 代码请求 token 时只返回了 access token,没有返回 refresh token
var httpClient = _httpClientFactory.CreateClient();
var parameters = new FormUrlEncodedContent(new Dictionary<string, string>
{
["client_id"] = _apiOptions.ClientId,
["client_secret"] = _apiOptions.ClientSecret,
["grant_type"] = "authorization_code",
["code"] = _memoryCache.Get<string>("code"),
["redirect_uri"] = _apiOptions.RedirectUri
});
var response = await httpClient.PostAsync($"{_apiOptions.OauthUrl}/connect/token", parameters);
以前是正常的,请问如何解决这个问题?
是请求 /connect/authoriz
时的 scope
参数中少了 offline_access
引起的
排查过程:
scope
参数中是否包含 offline_access
createRefreshToken = request.AuthorizationCode.RequestedScopes.Contains(IdentityServerConstants.StandardScopes.OfflineAccess);
/connect/token
的请求参数中加上 scope=offline_access
,问题依旧/connect/authorize
的 scope
请求参数中增加 offline_access
public IActionResult Authorize()
{
var url = QueryHelpers.AddQueryString(
$"{_apiOptions.OauthUrl}/connect/authorize",
new Dictionary<string, string>
{
["client_id"] = _apiOptions.ClientId,
["scope"] = "openid profile CnBlogsApi offline_access",
["response_type"] = "code id_token",
["redirect_uri"] = _apiOptions.RedirectUri,
["state"] = "cnblogs open api",
["nonce"] = Guid.NewGuid().ToString(),
["response_mode"] = "form_post"
});
return Redirect(url);
}
以下是一个示例代码,包括调用 PostAsync
方法并处理返回的响应的代码:
var httpClient = _httpClientFactory.CreateClient();
var parameters = new FormUrlEncodedContent(new Dictionary<string, string>
{
["client_id"] = _apiOptions.ClientId,
["client_secret"] = _apiOptions.ClientSecret,
["grant_type"] = "authorization_code",
["code"] = _memoryCache.Get<string>("code"),
["redirect_uri"] = _apiOptions.RedirectUri
});
var response = await httpClient.PostAsync($"{_apiOptions.OauthUrl}/connect/token", parameters);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
var tokenResponse = JsonConvert.DeserializeObject<TokenResponse>(responseContent);
// 处理返回的令牌响应
var accessToken = tokenResponse.AccessToken;
var refreshToken = tokenResponse.RefreshToken;
// 其他处理逻辑
}
else
{
// 处理请求失败的情况
var errorResponse = await response.Content.ReadAsStringAsync();
// 其他错误处理逻辑
}
确保你检查了 response 对象的内容,看看是否包含 refresh_token。通常,返回的令牌响应是一个 JSON 对象,你可以通过 response.Content.ReadAsStringAsync() 将其转换为字符串或使用相应的 JSON 解析方法转换为对象,并查看其中的 refresh_token 字段。
如果 refresh_token 字段确实不存在,则可能是以下原因之一:
你的 Identity Server 4 配置不包括 refresh_token 预定义的授权类型。你需要确保在 Identity Server 4 配置中包含 refresh_token 的授权类型。
当你的授权码 code 被使用一次之后,它将会失效。这意味着你只能使用它一次来请求令牌。确保你并没有多次使用同一个 code 值来请求令牌。