Nad tym problemem przesiedziałem kilka ładnych godzin dzisiaj. A mianowicie, w komponencie autentykacji użytkownika przez zewnętrzny serwis OAuth moja aplikacja Angular robi uwierzytelnienie użytkownika przez Web API endpoint:
private externalProviderWindow: Window; //definicja okna
(...)
var url = 'http://localhost:50962/' + "api/token/external-login/" + providerName; //url Web API
var params = "toolbar=yes,scrollbars=yes,resizable=yes,width=" + w + ", height=" + h; //parametry okna
this.externalProviderWindow = window.open(url, "ExternalProvider", params, false); //otwarcie okna z url
this.externalProviderWindow.addEventListener("message", this.handleMessage.bind(this), false); //dodanie event listenera
W powyższym kodzie komponent Angulara otwiera nowe okno z adresem prowadzącym do Web API, gdzie ono robi autentykację przez facebooka. Jeśli wynik jest pozytywny, to Web API zwraca odpowiedź JSON. Jednak żeby addEventListener
został odpalony, web API zwraca JSON do widoku HTML w oknie externalProviderWindow
, następnie jest wysyłana wiadomość do tego okna.
Wynik z kontrolera API przekazany do otwartego okna externalProviderWindow
(nic szczególnego, tutaj działa wszystko dobrze):
TokenResponseViewModel response = GenerateResponse(user);
return View(response);
A poniżej widok HTML który odbiera wynik, parsuje z message
i wysyła do otwartego okna:
@model TokenResponseViewModel
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>External Login</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
<script>
var accessToken = "@Model.Token";
var message = {};
if (accessToken) {
message.status = true;
message.token = '@Model.Token';
message.email = '@Model.Email';
message.refreshToken = '@Model.RefreshToken';
message.user = '@Model.User';
} else {
message.status = false;
}
console.log('posting message');
this.window.postMessage(JSON.stringify(message), "http://localhost:4200");
console.log('posted message');
</script>
</body>
</html>
I tu pojawia się problem, ponieważ, Web API jest pod domeną http://localhost:50962/
a ClientApp http://localhost:4200/
. Więc okno otwarte przez klienta 4200
ładuje adres dla 50962
. Po wysłaniu wiadomości this.window.postMessage(JSON.stringify(message), "http://localhost:4200");
otrzymuję w konsoli błąd:
Nie udało się wykonać „postMessage” dla „DOMWindow”: dostarczony cel („http://localhost:4200”) jest różny od domeny okna odbiorcy („http://localhost:50962”).
Do tej pory próbowałem już tego podejścia w różnych kombinacjach.
Próbowałem też odpalić Web API i SPA na jednym porcie, ale wtedy żądania do Web API end pointów nie były ogarniane przez ruter Angulara i wyrzucało mi błąd w konsoli, że routing nie istnieje. Ostatecznie zostałem przy osobnych domenach (portach).