In my Startup.cs class I have the following
services.AddAuthentication(options =>
{
options.DefaultScheme = "cookie";
options.DefaultChallengeScheme = "oidc";
options.DefaultSignOutScheme = "oidc";
})
.AddCookie("cookie", options =>
{
options.Cookie.Name = "cookie name";
options.Cookie.SameSite = SameSiteMode.Strict;
})
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "the authority URL";
options.ClientId = "the client identifier";
options.ClientSecret = "super secret";
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("api");
});
And contrary to having hardcoded values, I would like to call an API to get them. The API will return a model named FooAuthenticationConfiguration.
I don't know if I undestood correctly what you want to do, but tell me if this works for you:
In Startup.cs, create a method like:
private async Task GetConfiguration()
{
HttpClient client = new HttpClient();
var Response = await client.GetAsync("https://reqres.in/api/users/2");
}
Convert the ConfigureServices into an Async Method and calls in the beggining the GetConfiguration() like this:
public async void ConfigureServices(IServiceCollection services)
{
await GetConfiguration();
//....
}
You could do something like this.
This is the Program.cs from a Blazor WASM but should work similarly
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.AddApiAuthorization(c =>
{
c.ProviderOptions.ConfigurationEndpoint = $"{builder.Configuration["ApiBaseUri"]}/_configuration/auth";
});
And then the Controller in your Api would look like this..
[ApiController]
[Route("_configuration")]
public class ConfigurationController
: ControllerBase
{
readonly IConfiguration configuration;
public ConfigurationController(
IConfiguration configuration)
{
this.configuration = configuration;
}
[HttpGet, Route("auth")]
public IActionResult GetAuthConfiguration()
{
var settings = new Dictionary<string, object?>()
{
{ "authority", configuration.GetValue<string>("oAuth:Authority") },
{ "scope", "openid profile" },
{ "response_type", "code" },
{ "redirect_uri", "myUrl" }
};
return new JsonResult(settings);
}
}
Related
Authorize signalR Hub not getting connect to hub with front end angular, unable to invoke jwt access token to hub connection. How to connect Authurized signalr hub in asp core with angular project
i have the following code in my project,
Here my Code
public class Startup
{
readonly string CorsPolicy = "CorsPolicy";
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddCors(options =>
{
options.AddPolicy(name: CorsPolicy,
builder =>
{
builder
.AllowAnyHeader()
.AllowAnyMethod()
.WithOrigins("http://localhost:3000", "http://localhost:4200", "http://localhost:1234")
.AllowCredentials();
});
});
services.AddControllers();
services.AddSignalR()
.AddJsonProtocol(options =>
{
options.PayloadSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
//jwt token
services.AddAuthentication(opt =>
{
opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
opt.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = false;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])),
ClockSkew = TimeSpan.Zero
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = "Bearer " + context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/connecthub")))
{
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ApplicationDatabaseContext context)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors(CorsPolicy);
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<signalR_Hub>("/connecthub");
});
}
}
}
This my Hub connection
[Authorize]
public class sample_Hub :Hub
{
}
This my controller
[Authorize]
[HttpPut("{id}")]
public async Task<IActionResult> Putfilecreations(string id, filecreations filecreations)
{
var entity = _context.file_creations.Where(x => x.file_creation_id == id).FirstOrDefault();
entity.client_type_id = filecreations.client_type_id;
_context.file_creations.Update(entity);
await _context.SaveChangesAsync();
await _hubContext.Clients.All.SendAsync("FileUpdated", entity);
return Ok(entity);
}
This my Angular code for connect Hub
this.hubConnection = new HubConnectionBuilder()
.withUrl(environment.baseUrls.server + 'connecthub')
.configureLogging(LogLevel.Information)
.build();
Try to add CORS this way, the order is important:
services.AddCors(options =>
{
options.AddPolicy(CorsPolicy, builder => builder.WithOrigins("http://localhost:3000", "http://localhost:4200", "http://localhost:1234"")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
.SetIsOriginAllowed((host) => true));
});
I'm trying to use ASP.Net Core 2.2 with OAuth authentication. To use OAuth I use the AddOAuth method in the public void ConfigureServices(IServiceCollection services)in Startup.cs:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "Provider";
})
.AddCookie()
.AddOAuth("Provider", options =>
{
options.ClientId = Configuration["Provider:ClientId"];
options.ClientSecret = Configuration["Provider:ClientSecret"];
options.CallbackPath = new PathString("/callback");
options.AuthorizationEndpoint = "https://api.provider.net/auth/code";
options.TokenEndpoint = "https://api.provider.net/auth/token";
});
The problem is, that when the middleware tries to get an authorization code by using the TokenEndpoint, I receive a HTTP 401 because the provider expects a basic authentication header at this endpoint.
My question is, how can I tell the middleware to add a basic auth header to the TokenEndpoint request?
#Kirk Larkin Thanks for posting the link, this helped me alot to came up with a solution!
I created a DelegateHandler which adds a basic authentication header if the request is send to the TokenEndpoint:
public class AuthorizingHandler : DelegatingHandler
{
private readonly OAuthOptions _options;
public AuthorizingHandler(HttpMessageHandler inner, OAuthOptions options)
: base(inner)
{
_options = options;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if(request.RequestUri == new Uri(_options.TokenEndpoint))
{
string credentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(_options.ClientId + ":" + _options.ClientSecret));
request.Headers.Add("Authorization", $"Basic {credentials}");
}
return base.SendAsync(request, cancellationToken);
}
}
This DelegateHandler is used in the ConfigureService method:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "Provider";
})
.AddCookie()
.AddOAuth("Provider", options =>
{
options.ClientId = Configuration["Provider:ClientId"];
options.ClientSecret = Configuration["Provider:ClientSecret"];
options.CallbackPath = new PathString("/callback");
options.AuthorizationEndpoint = "https://api.provider.net/auth/code";
options.TokenEndpoint = "https://api.provider.net/auth/token";
var innerHandler = new HttpClientHandler();
options.BackchannelHttpHandler = new AuthorizingHandler(innerHandler, options);
//...
});
// ...
}
I managed to set up an Identity Server 4 using is4aspid from their templates and it seems to be working fine. Now I'm trying to protect a Web Api using Asp.net Core 2.0. The Authorize seems to be working, but when I try to use [Authorize(Roles ="Admin")] in my controller method it won't work.
I watched this video and tried to do what they did, but I can't find a good chunk of the code they use, like AuthorizationProviderClient or app.UseAuthorizationProvider()
This is the Startup.cs ConfigureServices method of my Identity Server:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer (Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
services.Configure<IISOptions>(iis =>
{
iis.AuthenticationDisplayName = "Windows";
iis.AutomaticAuthentication = false;
});
var builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
})
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApis())
.AddInMemoryClients(Config.GetClients())
.AddAspNetIdentity<ApplicationUser>();
if (Environment.IsDevelopment())
{
builder.AddDeveloperSigningCredential();
}
else
{
throw new Exception("need to configure key material");
}
services.AddAuthentication()
.AddGoogle(options =>
{
options.ClientId = "xxxx-xxxx.apps.googleusercontent.com";
options.ClientSecret = "xxxxx";
});
}
And this is the config class:
public static class Config
{
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile()
};
}
public static IEnumerable<ApiResource> GetApis()
{
return new ApiResource[]
{
//new ApiResource("api1", "My API #1")
new ApiResource("api1", "My API #1") { UserClaims = { "role" } }
};
}
public static IEnumerable<Client> GetClients()
{
return new[]
{
// https://www.scottbrady91.com/Angular/SPA-Authentiction-using-OpenID-Connect-Angular-CLI-and-oidc-client
new Client {
ClientId = "angular_spa",
ClientName = "Intranet Web App",
AllowedGrantTypes = GrantTypes.Implicit,
AllowedScopes = new List<string> { "openid", "profile", "api1" },
RedirectUris = new List<string> { "http://localhost:4200/auth-callback", "http://localhost:4200/silent-refresh.html" },
PostLogoutRedirectUris = new List<string> { "http://localhost:4200/" },
AllowedCorsOrigins = new List<string> { "http://localhost:4200" },
AllowAccessTokensViaBrowser = true
}
};
}
}
And this is the Startup.cs ConfigureServices of my WebApi:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore()
.AddAuthorization()
.AddJsonFormatters();
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ApiName = "api1";
options.EnableCaching = false;
options.RoleClaimType = System.Security.Claims.ClaimTypes.Role;
});
}
And then the configure:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAuthentication();
app.UseMvc();
}
This is how the roles are in the database:
I got this API from their samples. When I send the Bearer token using Postman the Authorize attribute works fine, now I want to get the Roles to work as well. Am I missing a nuget package or something?
Thanks in advance for any help
start up cs file .net core: (This is also get called while creating test server)
public class Startup
{
private IHostingEnvironment env;
private Dictionary<string, string> secretlist = new Dictionary<string, string>();
public Startup(IConfiguration configuration, IHostingEnvironment env)
{
this.Configuration = configuration;
this.CurrentEnvironment = env;
}
public Startup(IHostingEnvironment env)
{
this.env = env;
}
public IConfiguration Configuration { get; }
private IHostingEnvironment CurrentEnvironment { get; set; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<FormOptions>(x =>
{
x.ValueLengthLimit = int.MaxValue;
x.MultipartBodyLengthLimit = int.MaxValue;
x.MultipartHeadersLengthLimit = int.MaxValue;
});
services.AddApplicationInsightsTelemetry(this.Configuration);
services.AddSingleton<ITelemetryInitializer, AppInsightsInitializer>();
// Adds services required for using options.
services.AddOptions();
services.Configure<AppSettingsConfig>(this.Configuration.GetSection("AppSettings"));
if (this.CurrentEnvironment.IsDevelopment())
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(Environment.ExpandEnvironmentVariables(this.Configuration.GetValue<string>("AppSettings:KeyStorage_UNCPath"))))
.ProtectKeysWithDpapiNG();
}
else
{
CloudStorageAccount storageAccount = new CloudStorageAccount(
new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(
this.Configuration.GetValue<string>("AppSettings:StorageAccountName"),
this.Configuration.GetValue<string>("AppSettings:StorageAccessValue")), true);
//Create blob client
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Get a reference to a container named "keycontainer."
CloudBlobContainer container = blobClient.GetContainerReference("keycontainer");
services.AddDataProtection().PersistKeysToAzureBlobStorage(container, "keys.xml");
}
services.Configure<AppSettingsConfig>(options =>
{
if (!this.CurrentEnvironment.IsDevelopment())
{
}
});
var azureAdConfig = new AzureAdConfig();
this.Configuration.GetSection("Authentication:AzureAd").Bind(azureAdConfig);
services.Configure<AzureAdConfig>(this.Configuration.GetSection("Authentication:AzureAd"));
var connectionStringsConfig = new ConnectionStringsConfig();
connectionStringsConfig.oneConnection = this.secretlist["ConnectionStrings"];
//this.Configuration.GetSection("ConnectionStrings").Bind(connectionStringsConfig);
//services.Configure<ConnectionStringsConfig>(this.Configuration.GetSection("ConnectionStrings"));
if (this.RequireAAD())
{
// Add framework services.
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new RequireHttpsAttribute());
});
}
else
{
services.Configure<MvcOptions>(options =>
{
});
}
// Add Authentication services.
if (this.RequireAAD())
{
// Configure the OWIN pipeline to use cookie auth.
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
// Configure the OWIN pipeline to use OpenID Connect auth.
// https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-openid-connect-code
.AddOpenIdConnect(options =>
{
options.ClientId = azureAdConfig.ClientId;
options.ClientSecret = azureAdConfig.ClientSecret;
options.Authority = string.Format(azureAdConfig.AADInstance, azureAdConfig.Tenant);
options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
options.Resource = azureAdConfig.ResourceURI_Graph;
// PostLogoutRedirectUri = Configuration["AzureAd:PostLogoutRedirectUri"],
options.Events = new AuthEvents(azureAdConfig, connectionStringsConfig);
});
if (this.RequireAAD())
{
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter(policy));
config.Filters.Add(typeof(ExceptionFilter));
});
}
else
{
services.AddMvc();
}
if (this.Configuration.GetValue<bool>("API: SWITCH_ENABLE_API", true))
{
//services.AddScoped<IDBOperation, Operations>();
services.AddScoped<ILookupSearch, Operations>();
services.AddScoped<IFullSearch, Operations>();
}
services.AddSingleton<Common.Data.RepositoryFactories>(new Common.Data.RepositoryFactories(new Dictionary<Type, Func<DbContext, object>>
{
{ typeof(IQueryRepository), dbcontext => new QueryRepository(dbcontext) },
{ typeof(IDomainValuesRepository), dbcontext => new DomainValuesRepository(dbcontext) },
{ typeof(IRequestsRepository), dbcontext => new RequestsRepository(dbcontext) },
// { typeof(IoneDomainValuesRepository), dbcontext => new oneDomainValuesRepository(dbcontext) }
}));
services.AddTransient<Common.Contracts.IRepositoryProvider, Common.Data.RepositoryProvider>();
services.AddScoped<one.Data.Contracts.IoneUow, one.Data.oneUow>();
services.AddTransient<IUow,Uow>();
// For accessing appinsights for dependency injection?
services.AddApplicationInsightsTelemetry();
// For Storing Tokens in DB
services.AddDistributedSqlServerCache(o =>
{
o.ConnectionString = this.secretlist["ConnectionStrings"];
// o.ConnectionString = this.Configuration.GetConnectionString("oneConnection");
// o.ConnectionString = this.Configuration[this.Configuration.GetSection("KeyVaultSeetings")["oneConnectionString"]];
o.SchemaName = "dbo";
o.TableName = "CacheTable";
});
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<IEntityExtractor, EntityExtractor>();
services.AddScoped<ITokenCacheService, DistributedTokenCacheService>();
services.AddScoped<ITokenService, TokenService>();
services.AddTransient<IAPIClient,APIClient>();
}
/// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
/// </summary>
/// <param name="app"></param>
/// <param name="env"></param>
/// <param name="loggerFactory"></param>
/// <param name="tc"></param>
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, TelemetryClient tc)
{
var azureAdConfig = new AzureAdConfig();
this.Configuration.GetSection("Authentication:AzureAd").Bind(azureAdConfig);
loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
loggerFactory.AddProvider(new MyFilteredLoggerProvider(tc));
loggerFactory.AddApplicationInsights(app.ApplicationServices, this.Configuration.GetValue<string>("Logging:LogLevel:Default") == "Information" ? Microsoft.Extensions.Logging.LogLevel.Information : Microsoft.Extensions.Logging.LogLevel.Warning);
this.SetupStore(app);
app.UseRewriter(new RewriteOptions().AddRedirectToHttps());
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true
});
}
else
{
app.UseExceptionHandler("/Home/Error");
}
// TODO . Switch
app.UseStaticFiles();
if (this.RequireAAD())
{
app.UseAuthentication();
}
app.UseMiddleware(typeof(ErrorHandlingMiddleware));
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
}
}
Controller is decorated as :
[Route("api/[controller]")]
public class SearchController : BaseController
Controller Action is decorated as :
[Route("TestMethod")]
[ActionName("TestMethod")]
[HttpGet]
public async Task<EmptyResult> Test()
Configuration of TestServer Test CS file :
public DemoTest()
{
// Set up server configuration
var configuration = new ConfigurationBuilder()
.AddJsonFile(#"appsettings.json")
.Build();
// Create builder
var builder = new WebHostBuilder()
.UseStartup<Startup>()
.UseConfiguration(configuration);
// Create test server
var server = new TestServer(builder);
// Create database context
this._context = server.Host.Services.GetService(typeof(DBContext)) as DBContext;
// Create client to query server endpoints
this._client = server.CreateClient();
_client.BaseAddress = new Uri("https://localhost:44316/");
}
Test as a Fact :
[Fact]
public async Task Test()
{
try
{
var response = await this._client.GetAsync("/api/Search/TestMethod");
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
//Assert.False(result != null);
}
catch (Exception ex)
{
throw;
}
}
Getting Status as 302 and SearchController action is not getting
called. All the dependencies are resolved using start up configuration
file
Any idea ???
You could check the content for var responseString = await response.Content.ReadAsStringAsync(); to see what the content is.
I assume it is the login page which is due to that you required Authorize.
First, try to remove the code below for a try.
services.AddMvc(config =>
{
//var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
//config.Filters.Add(new Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter(policy));
config.Filters.Add(typeof(ExceptionFilter));
});
For Authentication, you will need to imitate the login process, here is a link for Identity, you could try implement your own login for AAD.
Razor Pages .NET Core 2.1 Integration Testing post authentication
I am getting an error in net core 2.1:
Bearer was not authenticated.
Failure message: No SecurityTokenValidator available for token: null
The asp net output window is:
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[7]
Bearer was not authenticated. Failure message: No SecurityTokenValidator available for token: null
info: Microsoft.AspNetCore.Cors.Infrastructure.CorsService[4]
Policy execution successful.
The accounts controller code is here:
namespace quiz_backend.Controllers
{
public class Credentials
{
public string Email { get; set; }
public string Password { get; set; }
}
[Produces("application/json")]
[Route("api/Account")]
public class AccountController : Controller
{
readonly UserManager<IdentityUser> userManager;
readonly SignInManager<IdentityUser> signInManager;
public AccountController(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager)
{
this.userManager = userManager;
this.signInManager = signInManager;
}
[HttpPost]
public async Task<IActionResult> Register([FromBody] Credentials credentials)
{
var user = new IdentityUser {
UserName = credentials.Email,
Email = credentials.Email
};
var result = await userManager.CreateAsync(user, credentials.Password);
if (!result.Succeeded)
return BadRequest(result.Errors);
await signInManager.SignInAsync(user, isPersistent: false);
// create a token
var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("this is the secret phrase"));
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);
var jwt = new JwtSecurityToken(signingCredentials: signingCredentials);
return Ok(new JwtSecurityTokenHandler().WriteToken(jwt));
}
}
}
Here is the startup.cs
namespace quiz_backend
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options => options.AddPolicy("Cors", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
services.AddDbContext<QuizContext>(opt =>opt.UseInMemoryDatabase("quiz"));
services.AddDbContext<UserDbContext>(opt => opt.UseInMemoryDatabase("user"));
services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<UserDbContext>();
var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("this is the secret phrase"));
services.AddAuthentication(options =>{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(cfg => {
cfg.RequireHttpsMetadata = false;
cfg.SaveToken = true;
cfg.TokenValidationParameters = new TokenValidationParameters()
{
IssuerSigningKey = signingKey,
ValidateAudience = false,
ValidateLifetime = false,
ValidateIssuerSigningKey = true
};
});
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors("Cors");
app.UseMvc();
}
}
}
This is the front end auth code to attach the token to the header in ts:
export class AuthInterceptor implements HttpInterceptor {
constructor() {}
intercept(req, next) {
var token = localStorage.getItem('token')
var authRequest = req.clone({
headers: req.headers.set('Authorization', `Bearer ${token}`)
})
return next.handle(authRequest)
}
}
Based on your code, it seems that the issue is that the token received is not valid (NULL).
Failure message: No SecurityTokenValidator available for token: null
First of all, you should make sure the token arrives as expected.