Authorize signalr core hub using identiyserver4 - c#

I am using visual studio 2019 preview Angular / .net core API backend template with individual authorization.
I believe within this template, identityserver4 is being used.
Within the API there is a signalr core hub which I am trying to authorize. I have the Authorize attribute on the hub. I am also specifying the token in the angular signalr client URL query string.
Despite the above, the authorize attribute has no effect, I am able to access the hub with or without the token.
JS / angular client
ngOnInit() {
console.log(this.authService.getAccessToken().toPromise())
this._hubConnection = new signalR.HubConnectionBuilder()
//.withUrl('/handoverhub', {accessTokenFactory: () => this.token})
.withUrl('/handoverhub', { accessTokenFactory: () => {
return this.authService.getAccessToken().toPromise();
} })
.configureLogging(signalR.LogLevel.Information)
.build();
ASPNETCore code
Hub using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using HomecareShared.Models;
using HomecareShared.Models.DTOs;
using HomecareShared.Models.Handover;
using HomecareShared.Models.Notify;
using HomecareShared.Models.SharedResources;
using HomecareHandover.Repo;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.VisualBasic.ApplicationServices;
namespace HomecareHandover.Hubs {
[Authorize]
public class HandoverHub : Hub
Some snippets of startup
app.UseAuthentication();
app.UseAuthorization();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<HandoverHub>("/handoverhub"); //For handover
endpoints.MapHub<TaskHub>("/taskhub"); //For task
});
app.UseIdentityServer();
services.AddAuthentication()
.AddIdentityServerJwt();
services.AddSignalR();
No error messages. I am able to get straight into the hub no problem.

I have had a similar problem but with AzureSignalR. I overcome the issue by implementing the code below. You also should call UseIdentityServer before UseEndpoints;
app.UseAuthentication();
app.UseAuthorization();
app.UseAzureSignalR(routes =>
{
routes.MapHub<ChatHub>("/hubs/chat");
routes.MapHub<NotificationHub>("/hubs/notifications");
});
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapHealthChecks("/healthz", new HealthCheckOptions() { });
});
By the way, another example about Hub authorization yet again in AzureSignalR and pure JWT but I put here so you may take a peek
https://github.com/ilkerkaran/MySignalRPlayGround/blob/master/SignalRServer.API/Startup.cs

FIXED!!!!
Turns out it was ordering in Startup.cs file.
I first implemented ilkerkaran's suggestion about calling identityserver before UseEndpoints. Then after 4 more hours, I moved app.UseAuthorization() below app.UseIdentityServer and that fixed it.
Hopefully, this helps someone else.

Related

asp.net core: IApplicationLifetime.ApplicationStopping isn't triggered

I saw a few articles about IApplicationLifetime and the way I can trigger execution when application starts and stops but I probably miss something because it is just not triggered.
Here is my workaround:
I opened a project template Container Application for kubernetes, asp.net core 2.2
Program.cs looks as it was created:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace Kubernetes1
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}
Startup.cs looks as following:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Internal;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
namespace Kubernetes1
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//var appLifetime = app.ApplicationServices.GetRequiredService<IApplicationLifetime>();
appLifetime.ApplicationStopping.Register(() => Console.WriteLine("ApplicationStopping called"));
appLifetime.ApplicationStopped.Register(() => Console.WriteLine("ApplicationStopped called"));
app.Run(async (context) =>
{
Console.WriteLine("AAA");
});
}
}
}
All I wanted to do here is running the app in cmd, then stop it and see 2 lines printed in console:
ApplicationStopping called
ApplicationStopped called
I didn't manage to make it happen.
Any ideas?
in a different cmd window I type: Get-Process -Name *dotnet* | Stop-Process
Stop-Process will kill the process, skipping any graceful shutdown behavior an application might have.
When the IApplicationLifetime talks about the application stopping, then it refers to the application being gracefully shut down. There are a few ways to trigger this, depending on how the application is starting:
When the application is running in the console: CTRL + C. For example when running through dotnet run or running the compiled executable directly.
When the application is running in IIS: Stopping the website or the application pool.
When the application is running as a Windows Service: Stopping the service.

How to sign out user from Blazor server-side app that uses Negotiate

I have a Blazor server-side application that uses .NET core 3.1. It uses Microsoft.AspNetCore.Authentication.Negotiate to authenticate user through Windows Credentials/Active Directory.
The issue I have is how to sign out user. After various research I found out that certain external authentication methods do not support sign out. For example Windows/AD does not need to be explicitly signed out. The only thing you need to do is clean identity and Claims principles locally in application. That is what I am having trouble with. The user also signs out automatically when you close browser.
I am using this middle ware to authenticate using Negotiate and am trying to clean claims of user during sign out. But it doesn't work.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Authentication;
namespace Test.Middleware
{
internal class ValidateAuthentication : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
try
{
if (context.User.Identity.IsAuthenticated)
{
await next(context);
}
else
{
await context.ChallengeAsync("Negotiate");
}
}
catch(InvalidOperationException) // this is for Windows/Negotiate sign out
{
context.User = new System.Security.Claims.ClaimsPrincipal();
}
}
}
}
Here is my configuration of services
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddElasticsearch(Configuration);
services.AddHttpContextAccessor();
services.AddScoped<ValidateAuthentication>();
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();
}
Expected result is for user to be signed out. But the actual result is user remains signed in.

Cannot convert lambda expression to type 'ServiceLifetime' because it is not a delegate type on Asp.net core 2.2

Why do I get this error:
Cannot convert lambda expression to type 'ServiceLifetime' because it is not a delegate type [TokenAuthWebApiCore.Server]
on this line of code:
public virtual void SetUpDataBase(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<SecurityContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("SecurityConnection"), sqlOptions => sqlOptions.MigrationsAssembly("TokenAuthWebApiCore.Server")));
}
This is how I use it:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(Configuration);
services.AddMvc();
SetUpDataBase(services);
// services.AddDbContext<SecurityContext>(options =>
// options.UseSqlServer(Configuration.GetConnectionString("SecurityConnection"), sqlOptions => sqlOptions.MigrationsAssembly("TokenAuthWebApiCore.Server")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
public virtual void SetUpDataBase(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<SecurityContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("SecurityConnection"), sqlOptions => sqlOptions.MigrationsAssembly("TokenAuthWebApiCore.Server")));
}
This are all my using statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.IdentityModel.Tokens;
using System.Text;
I am thinking probably this is because the tutorial I am following a tutorial for a different version of .net core and I am using .net core version 2.2. Can you please show me how to fix this? Thank you.
I had the same error in my project. The problem was that my context class was not derived from DbContext.
public class SecurityContext : DbContext
{
}
SecurityContext is not a DbContext. If you have a DbContext called SecurityContext in your project, remove using System.Security; from your usings in your Startups.csclass or rename the DbContext to something like SecurityDbContext.
The generic type you are using when calling AddDbContext is from the System.Security namespace, but it should be your Database context.
I´ve had the same issue. I use an interface, which is implemented by my DbContext. This solved the problem for me:
services.AddDbContext<IMyDbContext, MyDbContext>(options => options.UseLazyLoadingProxies()
.UseNpgsql("MyConnectionString", opt => opt.UseNodaTime()));
Not about version compatibility error.You need to implement DbContext in your project. When you make context class, you need to inherit context class from DbContext class.
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services
.AddEntityFrameworkSqlServer()
.AddDbContext<EmployeeContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("EmployeeContext"));
});
I received this when I accidentally installed EntityFramework instead of Microsoft.EntityFrameworkCore in my data project.
I just had the same problem, when migrating a project to EF core. What happened is that the DB context was still defined for EF. To fix it, I changed the DbContext to include EF core, and added the DbContextOptions constructor.
Full explenation over at the aspnetcore site.
I had EntityFramework & EntityFrameworkCore installed, removed EntityFramework & it was sorted

ASP.NET 5 MVC6 - How to include the standard HTTP error views (404, 502, etc..)

I created a new empty Project in Visual Studio 2015 - Update 1 with ASP.NET 5, MVC6 and AngularJS. I want to see the standard error pages when there are errors like 404, 502 etc like shown in the example below.
How can I include those error messages?
At this time I can only look in my browser console and see the 404 errors.
The routing will be client side with the angular ui-router module (if this information is needed here).
Here you can see my startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Diagnostics;
using Microsoft.AspNet.Diagnostics.Entity;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.Http;
using Microsoft.Extensions.DependencyInjection;
namespace Chronicus
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app)
{
/*
// auto generated code
app.UseIISPlatformHandler();
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
*/
app.UseIISPlatformHandler();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
app.UseMvc();
}
// Entry point for the application.
public static void Main(string[] args) => WebApplication.Run<Startup>(args);
}
}

Microsoft Azure AD authentication giving 'System.Net.Http.HttpRequestException'

I am facing a strange imtermittent issue with Azure AD authentication.
We are using CORS enabled web api in our project (origins are specified in web.config which are fetched by custom attribute, and this attribute is used for controllers).
Athorization part is done using adal.js
code is as follows:
startup.cs
using Microsoft.Owin;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
[assembly: OwinStartup(typeof(test.testapi.WebApi.Startup))]
namespace Test.testapi.WebApi
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
}
Startup.auth.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Claims;
using Microsoft.Owin.Security.ActiveDirectory;
using System.Configuration;
using Owin;
using System.Net;
namespace test.testapi.WebApi
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
//Following line is not required if you are using HTTPS calls to APIs
//ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["ida:Audience"],
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
});
}
}
}
When the control goes to startup.auth.cs it gives System.Net.Http.HttpRequestException
Error
Now thing is while i was working on my local dev environment i never got this issue(always authenticated fine ) but QA was facing this issue on QA server, so we started hosting web api from my machine, After which i also started getting this issue and that too quite frequently now.
what is this issue if anyone has faced this same issue.

Categories