IdentityServer4 and SignarR authentication (Net Core 2.2) with custom token key

  1. Custom Token Retriever class:
public class CustomTokenRetriever
    {
        internal const string TokenItemsKey = "idsrv4:tokenvalidation:token";
        // custom token key change it to the one you use for sending the access_token to the server
        // during websocket handshake
        internal const string SignalRTokenKey = "token";

        static Func<HttpRequest, string> AuthHeaderTokenRetriever { get; set; }
        static Func<HttpRequest, string> QueryStringTokenRetriever { get; set; }

        static CustomTokenRetriever()
        {
            AuthHeaderTokenRetriever = TokenRetrieval.FromAuthorizationHeader();
            QueryStringTokenRetriever = TokenRetrieval.FromQueryString();
        }

        public static string FromHeaderAndQueryString(HttpRequest request)
        {
            var token = AuthHeaderTokenRetriever(request);

            if (string.IsNullOrEmpty(token))
            {
                token = QueryStringTokenRetriever(request);
            }

            if (string.IsNullOrEmpty(token))
            {
                token = request.HttpContext.Items[TokenItemsKey] as string;
            }

            if (string.IsNullOrEmpty(token) && request.Query.TryGetValue(SignalRTokenKey, out StringValues extract))
            {
                token = extract.ToString();
            }

            return token;
        }
    }

2. Startup configuration

   public class Startup
    {
        public static IHostingEnvironment _hostingEnv;
        public Startup(IHostingEnvironment env, IConfiguration configuration)
        {
            _hostingEnv = env;
            Configuration = configuration;
        }

        public static IConfiguration Configuration { get; set; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //CORS
            services.AddCors();
            //Authentication
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
            })
                .AddIdentityServerAuthentication(options =>
                {
                    options.Authority = "https://localhost:44326/"; // Auth Server
                 
                    options.ApiName = "APIName";     // API Resource Id
                    options.TokenRetriever = CustomTokenRetriever.FromHeaderAndQueryString;
                    

            services.AddMvc();
            services.AddSignalR()
                .AddHubOptions<MyHub>(options =>
                {
                    options.EnableDetailedErrors = false;
                });
            services.AddDistributedMemoryCache(); // Adds a default in-memory implementation of IDistributedCache


            services.AddSingleton<ISingletonDeviceModels, SingletonDeviceModels>();
            services.AddSingleton<IUserIdProvider, NameUserIdProvider>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            //CORS
            var cors = Configuration.GetSection("CorsOrigins").Get<List<string>>().ToArray();
            app.UseCors(builder =>
                        builder.WithOrigins(cors)
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .WithExposedHeaders("Content-Range", "Link")
                        .AllowCredentials()
                );

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            // Add middleware after Identity but before Mvc
            app.UseAuthentication();
            app.UseSignalR(routes =>
            {
                routes.MapHub<MyHub>("/api/v1/myhub");

            }
            );
            app.UseMvc();
        }
    }

Leave a Reply

Your email address will not be published. Required fields are marked *