How to resolve Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' ... in ASP.NET 5 - asp.net-core

I am trying to add Google authentication to my website which is been developed using ASP.NET 5 with web API controller along with react and axios. The request call from axios is throwing Network error. As shown below
Error: Network Error
at createError (https://localhost:44331/static/js/bundle.js:48536:15)
at XMLHttpRequest.handleError (https://localhost:44331/static/js/bundle.js:47921:14)
message: "Network Error"
isAxiosError: true
When I check the browser console it throws error stating --> Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=610964943445-9jinqs228qqa64kt9fqdsmo1mtkbg9ni.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Flocalhost%3A44331%2Fsignin-google&scope=openid%20profile%20email&state=CfDJ8If3moGK8nFOrHvENOPET4upw6kmRMdILweas1dhbMn4xPQuR1iRNG_YyZmLF5U-1BGJAYpW2XDf_38k7Glu2UGC2MGe4lEP3G1kUm4FhQ39A4Cw3Mq9G3W4E9t7xJltqSWiDuNdu-MyJr39ykiFRYMziYWVcIhf9J-Ju6R4LlqQKpw5WL2BV2s84_vl8l1z1TCH2QX0Ifz6XPlEdpqK3G6MqI8OFsjMd96RimTzZIL00Q3Bkeb6JOpMl5TWoP3lRYPsR0sf2vEVnX1xYxoGFU0'
(redirected from 'https://localhost:44331/signin/ExternalLogin?provider=Google') from origin 'https://localhost:44331' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Below are my code details-->
Startup.cs-->
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication().AddGoogle(googleOptions =>
{
googleOptions.ClientId = configuration.Google.ClientId;
googleOptions.ClientSecret = configuration.Google.ClientSecret;
});
services.AddCors(options => options.AddPolicy("MyPolicy",
builder =>
{
builder
.WithOrigins("https://localhost:44331")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
}));
services.AddAuthentication(IISDefaults.AuthenticationScheme);
services.AddControllers();
services.AddMvc();
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
..
app.UseRouting();
app.UseAuthentication();
app.UseCors("MyPolicy");
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
}
SignInController.cs-->
[ApiController]
[Route("[controller]/[action]")]
public class SignInController : ControllerBase
{
...
[EnableCors("MyPolicy")]
[AllowAnonymous]
[HttpPost]
public IActionResult ExternalLogin(string provider, string returnUrl=null)
{
var redirectUrl = Url.Action("ExternalLoginCallback", "SignIn",
new { ReturnUrl = returnUrl });
var properties = _signInManager
.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return new ChallengeResult(provider, properties);
}
}
reactapicall.jsx-->
import axios from "axios";
const baseUrl = "/signin/"
export default {
login(url = baseUrl) {
return {
gmail: providerName => axios.post(url + "ExternalLogin?provider=" + providerName, null, { headers: { 'content-type': 'application/json', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': '*'} })
}
}
}
launchSettings.json-->
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://localhost:44331",
"sslPort": 44331
}
package.json-->
{
"name": "best_ui_react_app",
"version": "0.1.0",
"private": true,
"proxy": "https://localhost:44331",
"dependencies": {
"#emotion/react": "^11.4.1"
}
..
}
I have tried all the approaches but none of them worked. Please give me some suggestions so that I can fix this issue.

Related

ASP .NET Core CORS issue with Google authentication on redirect

Been following this tutorial in order to implement Google authentication in my web API but on the client side (using React and axios to do the request) the authentication process gets interrupted with this CORS issue and I'm struggling to sort it out:
Access to XMLHttpRequest at 'https://accounts.google.com/o/oauth2/v2/auth?(etc)' (redirected from 'https://localhost:44320/Photo/b997d788-3812-41d0-a09d-1a597eee9bad') from origin 'https://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
This is the Startup.cs file:
namespace rvc
{
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.AddDefaultPolicy(builder =>
{
builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
});
});
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(options =>
{
options.LoginPath = "/account/google-login";
}).AddGoogle(options =>
{
options.ClientId = "clientId";
options.ClientSecret = "secret";
});
services.AddScoped<PhotoService>();
services.AddScoped<TagService>();
services.AddScoped(_ => new BlobServiceClient(Configuration.GetConnectionString("AzureBlobStorage")));
services.AddDbContext<Data.DataContext>(x => x.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "rvc", 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", "rvc v1"));
}
app.UseHttpsRedirection();
if (env.IsProduction())
{
app.UseSpa(spa => { });
app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.ContentRootPath, "client")),
EnableDefaultFiles = true
});
}
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}
}
}
The Route("google-login") gets called but the Url.Action("GoogleResponse") is not reached. These are the Google Authentication methods:
namespace rvc.Controllers;
[AllowAnonymous, Route("account")]
public class AccountController : Controller
{
[Route("google-login")]
public IActionResult GoogleLogin()
{
var properties = new AuthenticationProperties {RedirectUri = Url.Action("GoogleResponse")};
return Challenge(properties, GoogleDefaults.AuthenticationScheme);
}
[Route("google-response")]
public async Task<IActionResult> GoogleResponse()
{
var result = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);
var claims = result.Principal?.Identities.FirstOrDefault()
?.Claims.Select(claim => new
{
claim.Issuer,
claim.OriginalIssuer,
claim.Type,
claim.Value
});
return Json(claims);
}
}
This is probably because from the server you use redirect, which triggers CORS (even if from your server you allow it).
you have to return the redirect URL to your front-end in some other way, capture it from the front-end app and then call the URL you need to invoke.

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?

Communicating between React-native and ASP.Net core RestfulAPI

I am having an issue getting my react-native app to communicate with my restful api backend.
This is backend controller
[ApiController]
[Route("[controller]")]
public class AuditController : ControllerBase
{
[HttpGet]
public IActionResult Audits()
{
var audit = new List<AuditRequest>
{
new AuditRequest
{
Date = "23/04/2019 16:49:37",
User ="Fiona",
Message="Logon"
},
new AuditRequest
{
Date = "23/04/2019 16:49:37",
User ="Fiona",
Message="Logon"
},
new AuditRequest
{
Date = "23/04/2019 16:49:37",
User ="Fiona",
Message="Logon"
}
};
return Ok(audit);
}
}
Startup file
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddCors(opt =>
{
opt.AddPolicy("CorsPolicy", policy =>
{
policy.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
//.WithOrigins("http://localhost:3000");
});
});
}
// 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.UseHttpsRedirection();
app.UseRouting();
app.UseCors("CorsPolicy");
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
and my react file.
useEffect(() => {
axios
.get("https://localhost:44354/audit")
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
console.log("error");
});
//auditsActions.fetchAudits();
}, []);
I am able to test the end-point using Postman.
The error i get is Network Error
node_modules\axios\lib\core\createError.js:15:0 in
node_modules\axios\lib\adapters\xhr.js:88:12 in dispatchXhrRequest
... 9 more stack frames from framework internals.
I am using expo and an emulator
Can someone tell me how to solve this issue?
In the end I used this application - coveyor by keyoti.

ionic httpclient doesnt work on emulator with net core 0 Unknown Error"

I'm getting this error, with ionic serve is working fine in the browser, but when i ran ionic cordova emulate android or ios is not working as expected, i tried to fetch another url and with another url is working(public api) but no with my server, i searched on the web and its look like it is a cors issue, but i cant find the solution.
headers:HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, headers: Map(0)}
message:"Http failure response for (unknown url): 0 Unknown Error"
name:"HttpErrorResponse"
ok:false
status:0
statusText:"Unknown Error"
url:null
__proto__:HttpResponseBase {constructor: }
This is my service in ionic with httpclient from angular:
return this.http.post<Response>(`${this.url}/api/account/login`, credentials, {
headers: {
'Content-Type': 'application/json; charset=utf-8',
'Access-Control-Allow-Origin': '*'
}
})
.pipe(
tap(res => {
this.spinner.dismiss();
if (res.ResponseCode == 0) {
this.storage.set(TOKEN_KEY, res.Data[0]);
localStorage.setItem(TOKEN_KEY, res.Data[0]);
this.user = this.helper.decodeToken(res.Data[0]);
this.state.state = true;
this.state.user = this.user;
this.authenticationState.next(this.state);
} else {
this.showAlert(res.ResponseMessage);
}
}),
catchError(e => {
this.showAlert(e.error.msg);
throw new Error(e);
})
);
and this is my net core 2.1 startup for configuring the cors option;
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ApplicationDbContext dbContext)
{
app.UseCors(options => options.WithOrigins("http://localhost:8100").AllowAnyMethod().AllowAnyHeader());
}
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddDefaultPolicy(
builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
}

No 'Access-Control-Allow-Origin' in header error

I am working with an Angular 2 app with asp.net core back end. I am trying to print a pdf (client side code below). When I run on our dev server, everything is ok; however, running on production I get
Failed to load api_url: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin url is therefore not allowed access.
Everything I have seen mentions something about CORS policy, but I don't understand how this could be working fine on one server, but not on another. Also, it appears to be retrieving fine when hitting other API endpoints.
Client-side api call:
getPDF(pickupId: string): void {
this.printingSub.next(true);
this._http.get(this._dataUrl + 'pickupsheet?pickupid=' + pickupId + '&barcode=true', { responseType: ResponseContentType.Blob })
.catch(error => this.handleError(error))
.subscribe((response: Response) => {
this.pdfBlob = new Blob([response.blob()], { type: 'application/pdf' });
const blobUrl = URL.createObjectURL(this.pdfBlob);
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = blobUrl;
document.body.appendChild(iframe);
iframe.contentWindow.print();
this.printingSub.next(false);
});
}
Startup.cs
public class Startup
{
public IConfiguration Configuration { get; }
public IConfigurationSection AppSettings { get; }
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile(#"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
AppSettings = Configuration.GetSection("appSettings");
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
ConfigureDatabase();
ConfigurePolicies(services);
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddOptions();
services.Configure<AppAccessSettings>(s =>
{
s.Env = AppSettings.GetSection("env").Value;
s.EnableAuth = bool.Parse(AppSettings.GetSection("enableAuth").Value);
});
services.AddMvc().AddJsonOptions(options =>
options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver()
);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
// Configure JWT authentication
Authentication.SetVarFromFile(AppSettings.GetSection("authFile").Value);
Authentication.SetAuth(ref app, AppSettings.GetSection("audience").Value);
app.UseCors("CorsPolicy");
app.UseMvc();
}
private void ConfigureDatabase()
{
string dbSource = AppSettings.GetSection("env").Value;
OracleEnv.Connection = Configuration.GetSection("connectionStrings").GetSection(dbSource).Value;
}
private void ConfigurePolicies(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
services.AddAuthorization(options =>
{
options.AddPolicy("EnableAuth",
policy => policy.Requirements.Add(new AuthRequirement(Configuration)));
});
services.AddSingleton<IAuthorizationHandler, UserAuthHandler>();
}
}
private void ConfigurePolicies(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
services.AddAuthorization(options =>
{
options.AddPolicy("EnableAuth",
policy => policy.Requirements.Add(new AuthRequirement(Configuration)));
});
services.AddSingleton<IAuthorizationHandler, UserAuthHandler>();
}
Pickup Sheet API Method
[Route("PickupSheet")]
public IActionResult GetPickupSheet(string pickupId, bool barCode)
{
PbReportGenerator rpt = new PbReportGenerator();
byte[] report = rpt.RetrievePDFReport(232, new Dictionary<string, string>
{
{ pickupId, "string" },
{ (barCode ? 1 : 0).ToString(), "int" }
});
var stream = new MemoryStream(report);
var response = File(stream, "application/pdf", String.Format("Report232_{0}.pdf", pickupId));
return response;
}
You need to set withCredentials with each request:
this._http.get(URL, { responseType: ResponseContentType.Blob, withCredentials: true })