Вход в Google в Angular 7 с .NET Core API - PullRequest
0 голосов
/ 14 февраля 2019

Я пытаюсь ввести логин Google в своем приложении Angular.Если я пытаюсь вызвать конечную точку API для внешнего сервера входа, верните код ошибки 405, например:

Доступ к XMLHttpRequest по адресу 'https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=...' (перенаправлен с 'http://localhost:5000/api/authentication/externalLogin?provider=Google') из источника 'null' заблокированПолитика CORS: Ответ на предварительный запрос не проходит проверку контроля доступа: в запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin».

Если я вызываю api/authentication/externalLogin?provider=Google в новомна вкладке браузера все работает корректно.Мне кажется, что проблема в угловом коде.

Мой API работает на localhost:5000.Угловое приложение работает на localhost:4200.Я использую .net core 2.1 и Angular 7

C # код

Startup.cs

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(x =>
{
    x.RequireHttpsMetadata = false;
    x.SaveToken = true;
    x.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(key),
        ValidateIssuer = false,
        ValidateAudience = false
    };
})
.AddCookie()
.AddGoogle(options => {
    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.ClientId = "xxx";
    options.ClientSecret = "xxx";
    options.Scope.Add("profile");
    options.Events.OnCreatingTicket = (context) =>
    {
        context.Identity.AddClaim(new Claim("image", context.User.GetValue("image").SelectToken("url").ToString()));

        return Task.CompletedTask;
    };
});

AuthenticationController.cs

[HttpGet]
public IActionResult ExternalLogin(string provider)
{
    var callbackUrl = Url.Action("ExternalLoginCallback");
    var authenticationProperties = new AuthenticationProperties { RedirectUri = callbackUrl };
    return this.Challenge(authenticationProperties, provider);
}

[HttpGet]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
    var result = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme);

    return this.Ok(new
    {
        NameIdentifier = result.Principal.FindFirstValue(ClaimTypes.NameIdentifier),
        Email = result.Principal.FindFirstValue(ClaimTypes.Email),
        Picture = result.Principal.FindFirstValue("image")
    });
}

Угловой код

login.component.html

<button (click)="googleLogIn()">Log in with Google</button>

login.component.ts

googleLogIn() {
  this.authenticationService.loginWithGoogle()
  .pipe(first())
  .subscribe(
    data => console.log(data)
  );
}

authentication.service.ts

public loginWithGoogle() {
  return this.http.get<any>(`${environment.api.apiUrl}${environment.api.authentication}externalLogin`,
  {
    params: new HttpParams().set('provider', 'Google'),
    headers: new HttpHeaders()
      .set('Access-Control-Allow-Headers', 'Content-Type')
      .set('Access-Control-Allow-Methods', 'GET')
      .set('Access-Control-Allow-Origin', '*')
  })
  .pipe(map(data => {
    return data;
  }));
}

Я представляю следующую схему: Angular -> My API -> перенаправление в Google -> Google возвращениепользовательские данные на моем API -> Мой API возвращает токен JWT -> Токен углового использования

Не могли бы вы помочь мне с этой проблемой.

Ответы [ 2 ]

0 голосов
/ 29 июля 2019

Мне нужно добавить несколько вещей:

  1. Я проверил ответ @Nehuen Antiman, и он частично работает на меня.

  2. Хорошей практикой является создание такого intereptor, как он предложил, но было бы неплохо, если бы вы просто добавили флаг «withCredentials» к своему сервису .ts:

    public loginWithGoogle() {
      return this.http.get<any>(`${environment.api.apiUrl}${environment.api.authentication}externalLogin`,
      {
        params: new HttpParams().set('provider', 'Google'),
        headers: new HttpHeaders()
          .set('Access-Control-Allow-Headers', 'Content-Type')
          .set('Access-Control-Allow-Methods', 'GET')
          .set('Access-Control-Allow-Origin', '*'),
        withCredentials: true
      })
      .pipe(map(data => {
        return data;
      }));
    }
    
  3. Пожалуйста, такжене забудьте добавить AllowCredentials() метод к вашему CorsOptions.Вот пример из моего кода:

    services.AddCors(options =>
    {
        options.AddPolicy(AllowedOriginsPolicy,
        builder =>
        {
            builder.WithOrigins("http://localhost:4200")
                .AllowAnyHeader()
                .AllowAnyMethod()
                .AllowCredentials();
        });
    });
    
0 голосов
/ 17 мая 2019

У меня была похожая проблема, и, поскольку вы сказали, что CORS уже настроен на серверной части, проблема может заключаться в том, что Angular не добавляет учетные данные в запросы API.Что-то делает браузер, когда вы набираете конечную точку API в строке URL.Вы можете использовать угловые перехватчики для добавления учетных данных в каждом запросе.Проверьте это: https://angular.io/guide/http#intercepting-requests-and-responses

И для вашего конкретного случая это может работать:

export class CookieInterceptor implements HttpInterceptor {

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    request = request.clone({
      withCredentials: true
    });
    return next.handle(request);
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...