Reputation:
I'm trying to use ASP.NET middleware to authenticate using Google OAuth. I understand the problem I am getting is due to CORS issues but I cannot seem to resolve them.
My Startup class config is as follows:
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder
.AllowAnyHeader()
.AllowAnyMethod()
.AllowAnyOrigin()
.AllowCredentials()
);
......
services.AddGoogle(o =>
{
o.ClientId = Configuration["Authentication:Google:ClientId"];
o.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
o.AuthorizationEndpoint += "?prompt=consent"; // Hack so we always get a refresh token, it only comes on the first authorization response
o.AccessType = "offline";
o.SaveTokens = true;
o.Events = new OAuthEvents()
{
OnRemoteFailure = ctx =>
{
ctx.Response.Redirect("/error?FailureMessage=" + UrlEncoder.Default.Encode(ctx.Failure.Message));
ctx.HandleResponse();
return Task.FromResult(0);
}
};
o.ClaimActions.MapJsonSubKey("urn:google:image", "image", "url");
o.ClaimActions.Remove(ClaimTypes.GivenName);
});
...........
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
//if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors("CorsPolicy");
app.Use(async (context, next) =>
{
await next();
// Serve index file and allow Angular to take over routing if (NotFound)
if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value))
{
context.Request.Path = "/index.html";
await next();
}
});
app.UseAuthentication();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseMvc();
}
In my Auth Controller:
// POST: api/auth/ExternalLogin
[HttpPost("loginexternal")]
[AllowAnonymous]
public async Task<IActionResult> LoginExternal([FromBody]string provider)
{
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
// Request a redirect to the external login provider to link a login for the current user
var redirectUrl = Url.Action(nameof(ExternalLoginCallback));
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User));
return new ChallengeResult(provider, properties);
}
My typescript angular code which calls this function:
loginExternal() {
const headers = new HttpHeaders({ 'Content-Type': 'application/json', 'Accept': 'application/json' });
return this.http.post(this.baseUrl + '/auth/loginexternal', '"Google"', { headers: headers })
.map((res: any) => {
localStorage.setItem('auth_token', res.auth_token);
this.loggedIn = true;
this._authNavStatusSource.next(true);
return true;
})
.catch(this.handleError);
}
And this is the response
The above response occures after the ChallengeResult is executed in my LoginExternal action.
Upvotes: 4
Views: 1186
Reputation: 31
Try to use this.document.location.href or even window.location.href to redirect to your google authentication page instead of making http request to your .net core controller action.
@Injectable()
export class LoginService {
//...
constructor(@Inject(DOCUMENT) private document: Document,...)
login() {
this.document.location.href = 'https://www.mywebsite.com/account/signInWithGoogle';
}
}
Here’s how it looks like in a controller action:
public class AccountController : Controller
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly UserManager<IdentityUser> _userManager;
public AccountController(SignInManager<IdentityUser> signInManager, UserManager<IdentityUser> userManager)
{
_signInManager = signInManager;
_userManager = userManager;
}
public IActionResult SignInWithGoogle()
{
var authenticationProperties = _signInManager.ConfigureExternalAuthenticationProperties("Google", Url.Action(nameof(HandleExternalLogin)));
return Challenge(authenticationProperties, "Google");
}
...
Upvotes: 2