I try to send request from my bff server to my protected api.
The API needs an access token for authentication. I split the request using HttpClientFactory. I’m setting the access token in httpClient.DefaultRequestHeaders.Authorization. But when the API accepts the request, an error is displayed:
The response was successfully returned as a challenge response: {
"error": "missing_token",
"error_description": "The security token is missing.",
"error_uri": "https://documentation.openiddict.com/errors/ID2000"
}
Most likely I’m passing the token incorrectly or something like that. How can I correctly pass a token or how can I configure the API so that it accepts a token.
Code from my bff server that sends a request to the API:
[HttpGet]
public async Task Get()
{
var httpClient = _httpClientFactory.CreateClient();
var accessToken = await HttpContext.GetTokenAsync("access_token");
var request = new HttpRequestMessage(HttpMethod.Get, new Uri(_apiEndpoint, "api/request-transportation-rate"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
//response.EnsureSuccessStatusCode();
await response.Content.CopyToAsync(HttpContext.Response.Body);
}
Unswer from API in Get() method:
{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
Date: Fri, 31 May 2024 11:15:27 GMT
Server: Kestrel
Cache-Control: no-store
Pragma: no-cache
WWW-Authenticate: Bearer
Content-Length: 0
Expires: Thu, 01 Jan 1970 00:00:00 GMT
}}
Setting up a bff server:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = "/account/login";
})
.AddOpenIdConnect(options =>
{
configuration.GetSection("OpenIDConnectSettings").Bind(options);
options.Authority = configuration["OpenIDConnectSettings:Authority"];
options.ClientId = configuration["OpenIDConnectSettings:ClientId"];
options.ClientSecret = configuration["OpenIDConnectSettings:ClientSecret"];
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.ResponseType = OpenIdConnectResponseType.Code;
options.Scope.Add("profile");
options.Scope.Add("offline_access");
options.Scope.Add("roles");
options.Scope.Add("phone");
options.Scope.Add("email");
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
});
API settings:
services.AddOpenIddict()
.AddValidation(options =>
{
options.AddEncryptionKey(new SymmetricSecurityKey(
Convert.FromBase64String("DRjd/GnduI3Efzen9V9BvbNUfc/VKgXltV7Kbk9sMkY=")));
options.SetIssuer("https://localhost:8000/");
options.AddAudiences("Test");
options.UseIntrospection()
.SetClientId("Test")
.SetClientSecret("901564A5-G5F6-42CB-B10D-61EF6A8F3654");
options.UseSystemNetHttp();
options.UseAspNetCore();
});
services.AddAuthentication(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
services.AddAuthorization();
Bff server init settings from identity server:
if (await iddictManager.FindByClientIdAsync("bff-server", cancellationToken) is null)
{
await iddictManager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = "bff-server",
ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654",
DisplayName = "bff-server",
ConsentType = ConsentTypes.Explicit,
RedirectUris =
{
new Uri("http://localhost:7001/signin-oidc")
},
PostLogoutRedirectUris =
{
new Uri("http://localhost:7001/signout-callback-oidc")
},
Permissions =
{
Permissions.ResponseTypes.Code,
Permissions.GrantTypes.AuthorizationCode,
Permissions.GrantTypes.RefreshToken,
Permissions.Endpoints.Revocation,
Permissions.Endpoints.Authorization,
Permissions.Endpoints.Token,
Permissions.Endpoints.Logout,
Permissions.Scopes.Profile,
Permissions.Scopes.Roles,
Permissions.Scopes.Email,
Permissions.Scopes.Phone,
$"{Permissions.Prefixes.Scope}api"
},
Requirements =
{
Requirements.Features.ProofKeyForCodeExchange
}
}, cancellationToken);
}
API init settings from identity server:
if (await iddictManager.FindByClientIdAsync("Test") == null)
{
var descriptor = new OpenIddictApplicationDescriptor
{
ClientId = "Test",
ClientSecret = "901564A5-G5F6-42CB-B10D-61EF6A8F3654",
Permissions =
{
Permissions.Endpoints.Introspection
}
};
await iddictManager.CreateAsync(descriptor);
}
Identity server settings:
services.AddDistributedMemoryCache();
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = "/authentication/login";
});
//session
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(2);
options.Cookie.HttpOnly = true;
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
services.AddQuartz(options =>
{
options.UseMicrosoftDependencyInjectionJobFactory();
options.UseSimpleTypeLoader();
options.UseInMemoryStore();
});
services.AddQuartzHostedService(options => options.WaitForJobsToComplete = true);
services.AddOpenIddict()
.AddCore(options =>
{
options.UseEntityFrameworkCore()
.UseDbContext<AppDbContext>();
options.UseQuartz();
});
services.AddOpenIddict()
.AddServer(options =>
{
options.AllowAuthorizationCodeFlow()
.AllowClientCredentialsFlow()
.AllowRefreshTokenFlow()
.AllowHybridFlow()
.RequireProofKeyForCodeExchange();
options.SetAuthorizationEndpointUris("connect/authorize")
.SetLogoutEndpointUris("connect/logout")
.SetTokenEndpointUris("connect/token")
.SetIntrospectionEndpointUris("connect/introspect")
.SetUserinfoEndpointUris("connect/userinfo");
options.AddEncryptionKey(new SymmetricSecurityKey(
Convert.FromBase64String("DRjd/GnduI3Efzen9V9BvbNUfc/VKgXltV7Kbk9sMkY=")));
options.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
//DisableAccessTokenEncryption();
options.RegisterScopes("api",
OpenIddict.Abstractions.OpenIddictConstants.Scopes.Email,
OpenIddict.Abstractions.OpenIddictConstants.Scopes.Profile,
OpenIddict.Abstractions.OpenIddictConstants.Scopes.Roles,
OpenIddict.Abstractions.OpenIddictConstants.Scopes.Phone);
options.UseAspNetCore()
.EnableLogoutEndpointPassthrough()
.EnableTokenEndpointPassthrough()
.EnableAuthorizationEndpointPassthrough()
.EnableUserinfoEndpointPassthrough();
})
.AddValidation(options =>
{
options.AddEncryptionKey(new SymmetricSecurityKey(
Convert.FromBase64String("DRjd/GnduI3Efzen9V9BvbNUfc/VKgXltV7Kbk9sMkY=")));
options.UseLocalServer();
options.EnableAuthorizationEntryValidation();
options.UseAspNetCore();
});
services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.WithOrigins("https://localhost:7037")
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowAnyOrigin();
});
});
I tried to pass the token in a different way and tried to configure the api