How to ignore Self Signed Certificate issue in client validation - openiddict

I've been trying to look into how I can disable SSL certificate validation by the HttpClient used to send request to the authorization metadata endpoint. I am running the authoriation server locally using hostname idp.local.test.com with haproxy as a reverse proxy using self signed certificate.
When I test locally the client token validation (no introspection) the HttpClient used to send GET request to metadata endpoint throws SSL validation error because I'm using self-signed certificate.
Here is the output of the log:
info: System.Net.Http.HttpClient.OpenIddict.Validation.SystemNetHttp.ClientHandler[100]
Sending HTTP request GET https://idp.local.test.com/.well-known/openid-configuration
System.Net.Http.HttpClient.OpenIddict.Validation.SystemNetHttp.ClientHandler: Information: Sending HTTP request GET https://idp.local.test.com/.well-known/openid-configuration
Loaded '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/3.1.5/System.Diagnostics.StackTrace.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Loaded '/usr/local/share/dotnet/shared/Microsoft.NETCore.App/3.1.5/System.Reflection.Metadata.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
dbug: OpenIddict.Validation.OpenIddictValidationDispatcher[0]
An exception was thrown by OpenIddict.Validation.SystemNetHttp.OpenIddictValidationSystemNetHttpHandlers+SendHttpRequest`1[[OpenIddict.Validation.OpenIddictValidationEvents+ApplyConfigurationRequestContext, OpenIddict.Validation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=35a561290d20de2f]] while handling the OpenIddict.Validation.OpenIddictValidationEvents+ApplyConfigurationRequestContext event.
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Security.SslStream.ThrowIfExceptional()
at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)
at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__65_1(IAsyncResult iar)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
This is the Startup class in the client application:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
});
services.AddOpenIddict()
.AddValidation(options =>
{
// options.Configure(config =>
// {
// config.MetadataAddress = new Uri("/.well-known/openid-configuration");
// });
var section = Configuration.GetSection("OAuth");
var tokenEncryptionKey = section.GetValue<string>("TokenEncryptionKey");
var issuer = section.GetValue<string>("Issuer");
options.SetIssuer(issuer);
options.AddEncryptionKey(new SymmetricSecurityKey(
Convert.FromBase64String(tokenEncryptionKey)
));
options.UseSystemNetHttp();
options.UseAspNetCore();
});
services.AddControllers(options =>
{
options.Filters.Add(typeof(GlobalExceptionFilter));
var requireAuthPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(requireAuthPolicy));
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
And this is the authorization server code:
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders()
.AddPasswordlessLoginTokenProvider()
.AddEmailConfirmationTokenProvider()
.AddPasswordResetTokenProvider();
services.AddOpenIddict()
.AddCore(coreBuilder =>
{
coreBuilder.SetDefaultApplicationEntity<OIDCApplication>()
.UseEntityFrameworkCore()
.UseDbContext<ApplicationDbContext>();
})
.AddServer(serverBuilder =>
{
serverBuilder.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles, Scopes.OfflineAccess);
serverBuilder.SetAuthorizationEndpointUris("/connect/authorize")
.SetTokenEndpointUris("/connect/token")
.SetConfigurationEndpointUris("/.well-known/openid-configuration")
.SetUserinfoEndpointUris("/connect/userinfo")
.SetIntrospectionEndpointUris("/connect/introspect");
serverBuilder.SetAuthorizationCodeLifetime(TimeSpan.FromMinutes(5));
string issuerHostname = Configuration["IssuerHost"];
serverBuilder.SetIssuer(new Uri($"https://{issuerHostname}"));
serverBuilder.Configure(options =>
{
options.UseSlidingExpiration = true;
});
serverBuilder.AllowAuthorizationCodeFlow()
.AllowRefreshTokenFlow();
serverBuilder.UseAspNetCore()
.EnableAuthorizationEndpointPassthrough()
.EnableTokenEndpointPassthrough()
.EnableUserinfoEndpointPassthrough()
.DisableTransportSecurityRequirement(); // Remove on prod
var tokenEncryptionKey = Configuration.GetValue<string>("TokenEncryptionKey");
serverBuilder.AddEncryptionKey(new SymmetricSecurityKey(
Convert.FromBase64String(tokenEncryptionKey)
));
serverBuilder.AddDevelopmentSigningCertificate();
})
.AddValidation(options =>
{
options.UseLocalServer();
options.UseAspNetCore();
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseHsts();
app.UseMiddleware<Middlewares.LoggingMiddleware>();
app.UseExceptionHandler("/Home/Error");
app.UseStatusCodePagesWithReExecute("/Home/Status", "?code={0}");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
Cheers

Adding your self-signed certificate to the trusted certificates list would be the right thing to do (it mostly depends on your OS).
Alternatively, you can use the HttpClientFactory APIs to force the HttpClientHandler used by OpenIddict's System.Net.Http integration to ignore server certificate validation errors:
services.AddHttpClient(typeof(OpenIddictValidationSystemNetHttpOptions).Assembly.GetName().Name)
.ConfigurePrimaryHttpMessageHandler(_ => new HttpClientHandler
{
ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
});

Related

Authentication and Authorization in .Net Core 5 and Angular 10 using JWT problem

Hello I'm trying make authorization using JWT token so when not authorized user request api or request service it decline,
I've used JWT token with claim Role and made Job column in my database as role so that It will get the role from it
the problem is I can't decode the token or tbh I tried my best with the help of identity to decode it but I sure can't
that's my startup.cs
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.AddAuthentication();
services.AddCors(options =>
{
options.AddPolicy("EnableCORS", Builder =>
{
Builder.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddDbContext<media_cloudContext>(option => option.UseSqlServer(Configuration.GetConnectionString("MediaCloudCS")));
services.AddScoped<ILoginService, LoginService>();
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "MediaCloudApi", Version = "v1" });
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "MediaCloudApi v1"));
}
app.UseHttpsRedirection();
app.UseCors("EnableCORS");
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
I added JWT package and tried to add default scheme but it can't define it and the only thing avilable JWTBearerExtension
that's my token creation service
public class TokenHelper
{
public const string Issuer = "http://MediaCloud.com";
public const string Audience = "http://MediaCloud.com";
public const string Secret = "OFRC1j9aaR2BvADxNWlG2pmuD392UfQBZZLM1fuzDEzDlEpSsn+btrpJKd3FfY855OMA9oK4Mc8y48eYUrVUSw==";
public static string GenerateSecureSecret()
{
var hmac = new HMACSHA256();
return Convert.ToBase64String(hmac.Key);
}
public static string GenerateToken(UserInfo user)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Convert.FromBase64String(Secret);
var claimsIdentity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.Name, user.Id.ToString()),
new Claim(ClaimTypes.Role, user.Job),
});
var signingCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = claimsIdentity,
Issuer = Issuer,
Audience = Audience,
Expires = DateTime.Now.AddMinutes(15),
SigningCredentials = signingCredentials,
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}
and that's the get request from the controller
[HttpGet,Authorize]
public async Task<ActionResult<IEnumerable<UserInfo>>> GetUserInfos()
{
return await _context.UserInfos.ToListAsync();
}
and the error code from postman
STATUS 500 INTERNAL SERVER ERROR
System.InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).
at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
HEADERS
=======
Accept: */*
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 69
Content-Type: application/json
Host: localhost:44371
User-Agent: PostmanRuntime/7.28.4
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IjciLCJyb2xlIjoiYWRtaW4iLCJuYmYiOjE2MzU5NzMyMDYsImV4cCI6MTYzNTk3NDEwNiwiaWF0IjoxNjM1OTczMjA2LCJpc3MiOiJodHRwOi8vTWVkaWFDbG91ZC5jb20iLCJhdWQiOiJodHRwOi8vTWVkaWFDbG91ZC5jb20ifQ.QjOC2ixirm9zmMmFDRO28JPd1Q97mq_M8bxlmmgT8EU
Postman-Token: 3911736a-ea2b-4273-ba35-d0315a560e71
I think the problem is the default schema but I can't add it and I'm new to .net core
you have to add to ConfigureServices(IServiceCollection services) of your startup file the code similar this one
var key = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration["Tokens:Key"]));
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
IssuerSigningKey = key,
ValidateIssuerSigningKey = true,
ValidateLifetime = true,
ValidateIssuer = false,
ValidAudience =Configuration["Tokens:Audience"] ,
ValidateAudience = true
};
});
and it is better to use appsettings to keep token parameters then to hard code them. Add somethig like this to to appsettings.json
"Tokens": {
"Key": "xxxxxx"
"Audience": "xxxxx",
"Issuer": "xxxx"
}

Error with Google Login and ASP.NET Core Web API

I have a Blazor client with a Asp.net Core Web API using a custom implementation of JWT for authentication and I'm trying to implement an external identity provider (Google OAuth).
From Blazor when a user clicks the link to auth with google, is calling the following API endpoint:
public async Task<IActionResult> ExternalLogin([FromBody] string provider)
{
var redirectUrl = "/ExternalLoginCallback";
AuthenticationProperties properties = _repository.Account.ExternalLogin(provider, redirectUrl);
return Challenge(properties, provider);
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.Configure<AppSettings>(Configuration.GetSection(AppSettings.JWTSettings));
services.Configure<AppSettings>(Configuration.GetSection(AppSettings.EmailConfiguration));
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
});
services.ConfigureSqliteContext(Configuration);
services.ConfigureLoggerService();
services.ConfigureDependencyInjection(Configuration);
services.AddControllers();
services.AddAutoMapper();
services.AddIdentity<User, IdentityRole>(opt =>
{
opt.Password.RequiredLength = 0;
opt.Password.RequireDigit = false;
opt.Password.RequireUppercase = false;
opt.Password.RequiredUniqueChars = 0;
opt.Password.RequireNonAlphanumeric = false;
opt.User.RequireUniqueEmail = true;
opt.SignIn.RequireConfirmedEmail = true;
})
.AddEntityFrameworkStores<RepositoryContext>()
.AddDefaultTokenProviders();
services.AddAuthentication()
.AddGoogle(GoogleDefaults.AuthenticationScheme, conf =>
{
var googleAuth = Configuration.GetSection("Google");
conf.ClientId = googleAuth["ClientId"];
conf.ClientSecret = googleAuth["ClientSecret"];
conf.SignInScheme = IdentityConstants.ExternalScheme;
});
if (Environment.IsDevelopment())
{
services.ConfigureAuthDevelopment(Configuration);
}
else
{
}
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebAssemblyDebugging();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors("CorsPolicy");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapFallbackToFile("index.html");
});
}
Edge Dev Console error:
Access to fetch at 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=******-o1gn4lob5hcknjggl10837m3ea5om5b4.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Flocalhost%3A44313%2Fsignin-google&scope=openid%20profile%20email&state=CfDJ8Ok9DyPEKDNCp3gn7utujrjiLfNm4KnoB6RC-cf3g01gBFzNSAqo54K-GaMudVevgRKaJZbcT5_O9S-jCGixs0i5SPY_CUxvM-l_DDsckOP0iHQMgyncA_-Ce_8vgCuxeozNkRWOHDJWar174-TkOgulJpYTr7b82MtOkUs3FOmiqpJ42YU2Q74y9imEFsgk8lynBRzb8Qqvh7P5kMuIg85QNnpjeO6lFbvefLDXPIzzE2r0n5sYlo1vzUG2sRbtRNgfThR6TvF-LPuMGygVCRI' (redirected from 'https://localhost:44313/api/account/ExternalLogin?provider=Google') from origin 'https://localhost:44313' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
dotnet.5.0.2.js:1 GET https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=*******-o1gn4lob5hcknjggl10837m3ea5om5b4.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Flocalhost%3A44313%2Fsignin-google&scope=openid%20profile%20email&state=CfDJ8Ok9DyPEKDNCp3gn7utujrjiLfNm4KnoB6RC-cf3g01gBFzNSAqo54K-GaMudVevgRKaJZbcT5_O9S-jCGixs0i5SPY_CUxvM-l_DDsckOP0iHQMgyncA_-Ce_8vgCuxeozNkRWOHDJWar174-TkOgulJpYTr7b82MtOkUs3FOmiqpJ42YU2Q74y9imEFsgk8lynBRzb8Qqvh7P5kMuIg85QNnpjeO6lFbvefLDXPIzzE2r0n5sYlo1vzUG2sRbtRNgfThR6TvF-LPuMGygVCRI net::ERR_FAILED
[]
Edge Dev Console network header
Request URL: https://localhost:44313/api/account/ExternalLogin?provider=Google
Request Method: GET
Status Code: 302
Remote Address: [::1]:44313
Referrer Policy: strict-origin-when-cross-origin
My assumption is that Challenge() produces a redirect which is then "blocked by CORS policy" from Blazor.
What would be the simplest yet more efficient way to implement it?

Microsoft.AspNetCore.Authentication.WsFederation.WsFederationHandler - .AspNetCore.Correlation.WsFederation cookie not found

I have a .NET Core 3.1 MVC app running as Azure app service. It is a WS-Federation client of ADFS 4.0
The app is running fine as far as I can tell, but logs are showing this error several times every hour.
WARN Microsoft.AspNetCore.Authentication.WsFederation.WsFederationHandler - '.AspNetCore.Correlation.WsFederation.7uN5rakM-M-9CQtd4R-mS_Z0Srw2yDfCEXZCLTGdJoU' cookie not found.
2020-09-01 20:49:15,961 [25] ERROR Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware - An unhandled exception has occurred while executing the request.
System.Exception: An error was encountered while handling the remote login.
---> System.Exception: Correlation failed.
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler`1.HandleRequestAsync()
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
})
.AddWsFederation(options =>
{
options.Wtrealm = Configuration["Federation:idaWtrealm"];
options.MetadataAddress = Configuration["Federation:idaADFSMetadata"];
})
.AddCookie();
Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
services.AddRazorPages();
services.AddRouting(options => options.LowercaseUrls = true);
services.AddHttpContextAccessor();
// Add functionality to inject IOptions<T>
services.AddOptions();
// Add our Config object so it can be injected
services.Configure<EndpointOptions>(Configuration.GetSection("Endpoints"));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/home/error");
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}");
endpoints.MapRazorPages();
});
}

SignalR client doesn't connect to server with http protocol

I've made .NET Core API with signalR, when I load app with https protocol, I can connect with signalR javascript client, but when I load app with http protocol - signalR js client can't connect to hub. CORS works fine.
My Code: Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.WithOrigins("http://localhost:3000")
.AllowAnyMethod()
.AllowCredentials()
.AllowAnyHeader());
});
services.AddSignalR(options =>
{
options.EnableDetailedErrors = true;
});
services.AddControllers(options =>
{
options.EnableEndpointRouting = true;
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
logger.LogInformation($"Started Configure with is Production mode:{env.IsProduction()}");
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseCors("CorsPolicy");
app.UseAuthorization();
app.UseAuthentication();
app.UseEndpoints(route =>
{
route.MapHub<ConnectionHub>("/chat");
route.MapControllers();
});
}
On my JS app:
var connection = new signalR.HubConnectionBuilder()
.withUrl("http://localhost:5066/chat") // WHEN I'M CHANGING TO HTTPS host - everything works fine
.build();
// Create a function that the hub can call to broadcast messages.
connection.on("broadcastMessage", function (name, message) { });
connection.start()
.then(function () {
connection.invoke("Send", name, messageInput.value);
})
.catch((error) => {
console.error(error.message);
});
Well , I resolved this problem adding options object to signalR client (add skipNegotiations: true) . To be honestly I hdont know what does it mean yet (tomorrow I'll read meaning and I'll write description of this property).
// Start the connection.
var connection = new signalR.HubConnectionBuilder()
.withUrl("http://localhost:5066/chat", {
skipNegotiation: false,
transport: signalR.HttpTransportType.WebSockets|
signalR.HttpTransportType.LongPolling |
signalR.HttpTransportType.serverSentEvents,
})
.build();
UPD: Well, It became works thanks to adding options object after url string.
About this object. At first signalR make negotiation (it's like some handshake between back and front) and if transport type is only websockets - you should skip it.

Dotnet Core 2.0 Authorization failed for user: (null)

My code was working perfectly with .net core 2.0. I'm not sure what went wrong. Application is throwing error during authorization. Error message and startup class code below.
> Microsoft.AspNetCore.Cors.Infrastructure.CorsService:Information:
Policy execution successful.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed for user: (null).
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information:
Authorization failed for user: (null).
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed for user: (null).
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information:
Authorization failed for user: (null).
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information:
Authorization failed for the request at filter
'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information:
Authorization failed for the request at filter
'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
namespace API
{
public class Startup
{
public IConfigurationRoot Configuration { get; }
public void ConfigureScopeServices(IServiceCollection services)
{
services.AddDbContext<AppDbContext>(options => options.UseMySql(Configuration.GetConnectionString("Default")));
}
public void ConfigureCompressionService(IServiceCollection services)
{
services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.Fastest);
services.AddResponseCompression(options => { options.Providers.Add<GzipCompressionProvider>(); });
}
public void ConfigureJWTService(IServiceCollection services)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetSection("ApplicationConfiguration:TokenOptions:SigningKey").Value)),
ValidateIssuer = true,
ValidIssuer = Configuration.GetSection("ApplicationConfiguration:TokenOptions:Issuer").Value,
ValidateAudience = true,
ValidAudience = Configuration.GetSection("ApplicationConfiguration:TokenOptions:Audience").Value,
ValidateLifetime = true,
NameClaimType = JwtRegisteredClaimNames.Sub,
RoleClaimType = "Roles"
};
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(o =>
{
o.TokenValidationParameters = tokenValidationParameters;
});
}
public void ConfigureServices(IServiceCollection services)
{
this.ConfigureScopeServices(services);
this.ConfigureCompressionService(services);
this.ConfigureJWTService(services);
services.Configure<ApplicationConfiguration>(Configuration.GetSection("ApplicationConfiguration"));
//Customized Response Object to Map MiddleWare Response Object
var formatterSettings = JsonSerializerSettingsProvider.CreateSerializerSettings();
formatterSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
ResponseFormatter formatter = new ResponseFormatter(formatterSettings, ArrayPool<Char>.Create());
services.AddMvcCore()
.AddApiExplorer()
.AddAuthorization()
.AddFormatterMappings()
.AddDataAnnotations()
.AddJsonFormatters()
.AddCors()
.AddMvcOptions(
options =>
{
options.OutputFormatters.RemoveType<JsonOutputFormatter>();
options.OutputFormatters.Insert(0, formatter);
}
);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseCors(
builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
);
app.UseMvc();
app.UseResponseCompression();
}
}
}
I think you missed authentication middleware: app.UseAuthentication().
Please try this:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseCors(
builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
);
app.UseAuthentication();
app.UseMvc();
app.UseResponseCompression();
}