问题描述
我正在尝试使这个access_token东西起作用,以调用从BaseController用Autohorize属性声明的API。我认为我的配置有问题。 有人可以告诉我我在做什么错吗?
我已附上Startup.cs供参考。 我正在尝试使用以下代码中调用的API来获取访问令牌:
var httpClient = _httpClientFactory.CreateClient(BaseController.AUTHORIZATION_SERVICE_CLIENT_NAME);
httpClient.DefaultRequestHeaders.Clear();
httpClient.DefaultRequestHeaders.Add(HeaderNames.Accept,"application/json");
//AccessToken is always null
var accessToken = _httpContextAccessor.HttpContext.GetTokenAsync("access_token").Result;
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",accessToken);
var request = new HttpRequestMessage(HttpMethod.Get,"/api/auth/user/?id=" + id);
var response = httpClient.SendAsync(request,HttpCompletionOption.ResponseHeadersRead).Result;
if (response.IsSuccessStatusCode)
return response.Content.ReadAsStringAsync().Result as string;
return "-";
我的IS4启动: 确认
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddMvc().AddDataAnnotationsLocalization();
services.AddRazorPages()
.AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizeAreaFolder("Identity","/Account/Manage");
});
//START IS4
var builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
options.UserInteraction.LoginUrl = "/Identity/Account/Login";
options.UserInteraction.LogoutUrl = "/Identity/Account/Logout";
options.Authentication = new AuthenticationOptions()
{
CookieLifetime = TimeSpan.FromHours(10),// ID server cookie timeout set to 10 hours
CookieSlidingExpiration = true
};
})
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(connectionString,sql => sql.MigrationsAssembly(migrationsAssembly));
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(connectionString,sql => sql.MigrationsAssembly(migrationsAssembly));
options.EnableTokenCleanup = true;
})
.AddAspNetIdentity<User>();
if (env.IsDevelopment())
builder.AddDeveloperSigningCredential();
else
builder.AddSigningCredential(LoadCertificateFromStore());
//END IS4
//START IDENTITY
services.AddIdentity<User,Role>(options =>
{
options.SignIn.RequireConfirmedEmail = true;
})
.AddEntityFrameworkStores<IdentityContext>()
.AddUserStore<CustomUserStore>()
.AddRoleStore<CustomRoleStore>()
.AddDefaultTokenProviders()
.AddClaimsPrincipalFactory<CustomUserClaimsPrincipalFactory>();
services.ConfigureApplicationCookie(options => {
options.LoginPath = Startup.LoginPath;
options.LogoutPath = Startup.LogoutPath;
options.AccessDeniedPath = Startup.AccessDeniedPath;
});
services.AddAuthentication(o =>{})
.AddGoogle("Google","Google",options =>
{
options.SignInScheme = IdentityConstants.ExternalScheme;
options.ClientId = configuration.GetValue<string>("Google:ClientId");
options.ClientSecret = configuration.GetValue<string>("Google:ClientSecret");
})
.AddOpenIdConnect("azuread","Azure AD",options => configuration.Bind("AzureAd",options));
services.Configure<OpenIdConnectOptions>("azuread",options =>
{
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Events = new OpenIdConnectEvents()
{
OnRedirectToIdentityProviderForSignOut = context =>
{
context.HandleResponse();
context.Response.Redirect("/Identity/Account/Logout");
return Task.FromResult(0);
}
};
});
services.AddTransient<IClaimsTransformation,ClaimsTransformer>();
//END IDENTITY
//Set named HttpClient settings for API to get roles of user
services.AddHttpContextAccessor();
services.AddTransient<BearerTokenHandler>();
services.AddHttpClient(BaseController.AUTHORIZATION_SERVICE_CLIENT_NAME,client =>
{
client.BaseAddress = new Uri("https://localhost:44318/");
}).AddHttpMessageHandler<BearerTokenHandler>();
}
public void Configure(IApplicationBuilder app)
{
if (Environment.IsDevelopment())
{
Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(ErrorPath);
}
app.UseStaticFiles();
app.UseRouting();
app.UseIdentityServer();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(name: "defaultArea",pattern: "{area=Identity}/{controller=Account}/{action=Login}/{id?}");
endpoints.MapControllerRoute(name: "default",pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
Bearer令牌处理程序,当我向客户端添加'AddHttpMessageHandler
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)
{
var accessToken = await GetAccessTokenAsync();
if (!string.IsNullOrWhiteSpace(accessToken))
request.SetBearerToken(accessToken);
return await base.SendAsync(request,cancellationToken);
}
public async Task<string> GetAccessTokenAsync()
{
// get the expires_at value & parse it
var expiresAt = await _httpContextAccessor.HttpContext.GetTokenAsync("expires_at");
var expiresAtAsDateTimeOffset = DateTimeOffset.Parse(expiresAt,CultureInfo.InvariantCulture);
if ((expiresAtAsDateTimeOffset.AddSeconds(-60)).ToUniversalTime() > DateTime.UtcNow)
return await _httpContextAccessor.HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken); // no need to refresh,return the access token
var idpClient = _httpClientFactory.CreateClient("IDPClient");
// get the discovery document
var discoveryReponse = await idpClient.GetDiscoveryDocumentAsync();
// refresh the tokens
var refreshToken = await _httpContextAccessor.HttpContext.GetTokenAsync(OpenIdConnectParameterNames.RefreshToken);
var refreshResponse = await idpClient.RequestRefreshTokenAsync(new RefreshTokenRequest {
Address = discoveryReponse.TokenEndpoint,ClientId = "mvc",ClientSecret = "secret",RefreshToken = refreshToken
});
// store the tokens
var updatedTokens = new List<AuthenticationToken>();
updatedTokens.Add(new AuthenticationToken {
Name = OpenIdConnectParameterNames.IdToken,Value = refreshResponse.IdentityToken
});
updatedTokens.Add(new AuthenticationToken {
Name = OpenIdConnectParameterNames.AccessToken,Value = refreshResponse.AccessToken
});
updatedTokens.Add(new AuthenticationToken {
Name = OpenIdConnectParameterNames.RefreshToken,Value = refreshResponse.RefreshToken
});
updatedTokens.Add(new AuthenticationToken {
Name = "expires_at",Value = (DateTime.UtcNow + TimeSpan.FromSeconds(refreshResponse.ExpiresIn)).
ToString("o",CultureInfo.InvariantCulture)
});
// get authenticate result,containing the current principal & properties
var currentAuthenticateResult = await _httpContextAccessor.HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
// store the updated tokens
currentAuthenticateResult.Properties.StoreTokens(updatedTokens);
// sign in
await _httpContextAccessor.HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,currentAuthenticateResult.Principal,currentAuthenticateResult.Properties);
return refreshResponse.AccessToken;
}
解决方法
一个想法可能是尝试在您的配置中设置SaveTokens = true。
请参阅此article或想法。