Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not able to enable CORS for identity server 4 in asp.net core

Ok, I have added CORS policy for my dot net core APIs but somehow these CORS policies are not working for identity server 4 endpoints. I have following api where I try to register a user:

    [EnableCors("AllowAllCorsPolicy")]
    [Route("api/User")]
    public class UserController : Controller
    {
        private readonly UserManager<ApplicationUser> _userManager;
        private IUserServices _userService;
        public UserController(UserManager<ApplicationUser> userManager, IUserServices userService)
        {
            _userManager = userManager;
            _userService = userService;
        }

        [HttpPost]
        public async Task<int> Post([FromBody]User userInfo)
        {
            var user = new ApplicationUser{  UserName = userInfo.Name, Email = userInfo.Email,
                UserTypeId = Constant.User, CustomerId = userInfo.CustomerId };

            //Follwing 3 lines give CORS issue.
            await _userManager.AddToRoleAsync(user, Constant.User);
            var userClaim = new Claim(Constant.User, user.Email.ToString(), ClaimValueTypes.Integer);
            await _userManager.AddClaimAsync(user, userClaim);

            // var userObj = _userService.AddNewUser(userInfo);
        }

Now if I use above identity server methods (AddToRoleAsync() and AddClaimAsync()) I get CORS error in my client (angular app running on different server)

However if I use my custom method to register the user, I don't get CORS error:

            //Don't get CORS error when commented below
            //await _userManager.AddToRoleAsync(user, Constant.User);
            //var userClaim = new Claim(Constant.User, user.Email.ToString(), ClaimValueTypes.Integer);
            //await _userManager.AddClaimAsync(user, userClaim);

            //use custom method
            var userObj = _userService.AddNewUser(userInfo);

To enable CORS for asp.net, startup.cs I am doing:

    public void ConfigureServices(IServiceCollection services)
            {
              services.AddCors(options =>
             {
                options.AddPolicy("AllowAllCorsPolicy",
                    builder => builder.AllowAnyOrigin()
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials());
            });
            services.AddMvc();
          }


public void Configure(IApplicationBuilder app, IHostingEnvironment env,  IServiceProvider serviceProvider)
        {
            app.UseCors("AllowAllCorsPolicy");
        }

I even tried to add the CORS headers manually in startup.cs, but no luck:

public void Configure(IApplicationBuilder app, IHostingEnvironment env,  IServiceProvider serviceProvider)
        {
            app.Use(async (context, next) =>
        {
            if (context.Request.Method == "OPTIONS")
                context.Response.StatusCode = (int)HttpStatusCode.OK;

            var headers = context.Response.Headers;
            if (headers.ContainsKey("Access-Control-Allow-Origin"))
            {
                headers["Access-Control-Allow-Origin"] = string.Join(",", context.Request.Headers["Referer"].Select(x => x.Substring(0, x.Length - 1)));
            }
            else
            {
                context.Response.Headers.Append("Access-Control-Allow-Origin", string.Join(",", context.Request.Headers["Referer"].Select(x => x.Substring(0, x.Length - 1))));
            }
            if (headers.ContainsKey("Access-Control-Allow-Headers"))
            {
                headers["Access-Control-Allow-Headers"] = "Origin, Content-Type, Accept, Client, Authorization, X-Auth-Token, X-Requested-With";
            }
            else
            {
                context.Response.Headers.Append("Access-Control-Allow-Headers", "Origin, Content-Type, Accept, Client, Authorization, X-Auth-Token, X-Requested-With");
            }
            if (headers.ContainsKey("Access-Control-Allow-Methods"))
            {
                headers["Access-Control-Allow-Credentials"] = "GET, POST, PATCH, PUT, DELETE, OPTIONS";
            }
            else
            {
                context.Response.Headers.Append("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS");
            }
            if (headers.ContainsKey("Access-Control-Allow-Credentials"))
            {
                headers["Access-Control-Allow-Credentials"] = "true";
            }
            else
            {
                context.Response.Headers.Append("Access-Control-Allow-Credentials", "true");
            }
            context.Response.Headers.Append("Access-Control-Expose-Headers", "X-Auth-Token");
            context.Response.Headers.Append("Vary", "Origin");
            await next();
        });
        }

I saw this documentation for identityserver Options for CORS and also this CORS documentation but not much helpful.

like image 883
Saurabh Palatkar Avatar asked Apr 11 '17 10:04

Saurabh Palatkar


People also ask

How do you fix the CORS error in Ruby?

Fixing the “CORS” error In a nutshell, the browser is preventing the request because the frontend app is at a different origin than our backend app. Thankfully, this is easy to fix. Add the rack-cors gem to Gemfile and bundle install . Then open the file at config/initializers/cors.

How do I enable CORS in asp net CORS?

You can enable CORS per action, per controller, or globally for all Web API controllers in your application. To enable CORS for a single action, set the [EnableCors] attribute on the action method.

Why is CORS not working?

Cross-Origin Resource Sharing (CORS) errors occur when a server doesn't return the HTTP headers required by the CORS standard. To resolve a CORS error from an API Gateway REST API or HTTP API, you must reconfigure the API to meet the CORS standard.


2 Answers

This works for the newer version of the server.

    services.AddSingleton<ICorsPolicyService>((container) => {
        var logger = container.GetRequiredService<ILogger<DefaultCorsPolicyService>>();
        return new DefaultCorsPolicyService(logger)
        {
            AllowAll = true
        };
    });

more details here at this discussion, with credit to the original author

https://github.com/IdentityServer/IdentityServer4/issues/4685

like image 89
Jay Avatar answered Nov 03 '22 01:11

Jay


If you are using IdentityServer 4 with clients for authentication you must configure CORS with IdentityServer 4 see : IdentityServer4CORS

IdentityServer4 CORS is for the token endpoint only. What you did is configure the CORS for all the controller/methods which is probably correct in your case. However, you won't be able to retrieve the token if you don't enable CORS on identityserver4.

You can either add a list of allowed CORS to your clients that will be added to the identityserver database OR add a global default one like this :

var cors = new DefaultCorsPolicyService(_loggerFactory.CreateLogger<DefaultCorsPolicyService>())
{
    AllowedOrigins = { "https://foo", "https://bar" }
};
services.AddSingleton<ICorsPolicyService>(cors);

Note that you can manually add it to the database too.

like image 31
Pilouk Avatar answered Nov 03 '22 02:11

Pilouk