Ich folge diesem Artikel auf Social Logins mit AngularJS und ASP.Net WebAPI (das ist ziemlich gut):AngularJS und ASP.Net WebAPI Social Login auf einem mobilen Browser
ASP.NET Web API 2 external logins with Facebook and Google in AngularJS app
Ziemlich viel, die Der Code funktioniert einwandfrei, wenn Sie den sozialen Login über einen Desktop-Browser (z. B. Chrome, FF, IE, Edge) ausführen. Das soziale Login öffnet sich in einem neuen Fenster (nicht Tab) und Sie können entweder Ihr Google - oder Facebook - Konto verwenden und sobald Sie über eines von ihnen eingeloggt sind, werden Sie auf die Callback - Seite (authComplete.html) weitergeleitet Callback-Seite hat eine JS-Datei definiert (authComplete.js), die das Fenster schließen und einen Befehl im übergeordneten Fenster ausführen würde.
die AngularJS Steuerung, die die externe Login-URL aufruft und öffnet sich ein Popup-Fenster (nicht Reiter) auf Desktop-Browsern:
loginController.js
'use strict';
app.controller('loginController', ['$scope', '$location', 'authService', 'ngAuthSettings', function ($scope, $location, authService, ngAuthSettings) {
$scope.loginData = {
userName: "",
password: "",
useRefreshTokens: false
};
$scope.message = "";
$scope.login = function() {
authService.login($scope.loginData).then(function (response) {
$location.path('/orders');
},
function (err) {
$scope.message = err.error_description;
});
};
$scope.authExternalProvider = function (provider) {
var redirectUri = location.protocol + '//' + location.host + '/authcomplete.html';
var externalProviderUrl = ngAuthSettings.apiServiceBaseUri + "api/Account/ExternalLogin?provider=" + provider
+ "&response_type=token&client_id=" + ngAuthSettings.clientId
+ "&redirect_uri=" + redirectUri;
window.$windowScope = $scope;
var oauthWindow = window.open(externalProviderUrl, "Authenticate Account", "location=0,status=0,width=600,height=750");
};
$scope.authCompletedCB = function (fragment) {
$scope.$apply(function() {
if (fragment.haslocalaccount == 'False') {
authService.logOut();
authService.externalAuthData = {
provider: fragment.provider,
userName: fragment.external_user_name,
externalAccessToken: fragment.external_access_token
};
$location.path('/associate');
}
else {
//Obtain access token and redirect to orders
var externalData = { provider: fragment.provider, externalAccessToken: fragment.external_access_token };
authService.obtainAccessToken(externalData).then(function (response) {
$location.path('/orders');
},
function (err) {
$scope.message = err.error_description;
});
}
});
}
}]);
authComplete.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<script src="scripts/authComplete.js"></script>
</body>
</html>
authComplete.js
window.common = (function() {
var common = {};
common.getFragment = function getFragment() {
if (window.location.hash.indexOf("#") === 0) {
return parseQueryString(window.location.hash.substr(1));
} else {
return {};
}
};
function parseQueryString(queryString) {
var data = {},
pairs, pair, separatorIndex, escapedKey, escapedValue, key, value;
if (queryString === null) {
return data;
}
pairs = queryString.split("&");
for (var i = 0; i < pairs.length; i++) {
pair = pairs[i];
separatorIndex = pair.indexOf("=");
if (separatorIndex === -1) {
escapedKey = pair;
escapedValue = null;
} else {
escapedKey = pair.substr(0, separatorIndex);
escapedValue = pair.substr(separatorIndex + 1);
}
key = decodeURIComponent(escapedKey);
value = decodeURIComponent(escapedValue);
data[key] = value;
}
return data;
}
return common;
})();
var fragment = common.getFragment();
window.location.hash = fragment.state || '';
window.opener.$windowScope.authCompletedCB(fragment);
window.close();
Das Problem, das ich habe, ist, dass, wenn ich die Anwendung auf einem mobilen Gerät (Safari, Chrome for Mobile) laufen, die soziale Login-Fenster in einem neuen Tab öffnet und die JS-Funktion, die passieren sollte zu Zurück das Fragment zum Hauptanwendungsfenster wird nicht ausgeführt und die neue Registerkarte wird nicht geschlossen.
Sie eigentlich dieses Verhalten sowohl auf einem Desktop und mobilen Browser durch die Anwendung ausprobieren können:
http://ngauthenticationapi.azurewebsites.net/
Was ich in diesem Zusammenhang bisher versucht haben, ist in der Login-Controller, ich die Funktion so modifiziert, dass die externe uRL Login im selben Fenster öffnet sich:
$scope.authExternalProvider = function (provider) {
var redirectUri = location.protocol + '//' + location.host + '/authcomplete.html';
var externalProviderUrl = ngAuthSettings.apiServiceBaseUri + "api/Account/ExternalLogin?provider=" + provider
+ "&response_type=token&client_id=" + ngAuthSettings.clientId
+ "&redirect_uri=" + redirectUri;
window.location = externalProviderUrl;
};
und modifiziert, um die authComplete.js common.getFragment Funktion zur Anmeldeseite zurückzukehren, durch das Zugriffstoken durch die soziale bereitgestellt Anfügen melden Sie sich als Query-String:
common.getFragment = function getFragment() {
if (window.location.hash.indexOf("#") === 0) {
var hash = window.location.hash.substr(1);
var redirectUrl = location.protocol + '//' + location.host + '/#/login?ext=' + hash;
window.location = redirectUrl;
} else {
return {};
}
};
Und im Login-Controller, habe ich eine Funktion, um die Abfragezeichenfolgeflag zu analysieren und versuchen, die $ scope.authCompletedCB (Fragment) Funktion wie zu nennen:
var vm = this;
var fragment = null;
vm.testFn = function (fragment) {
$scope.$apply(function() {
if (fragment.haslocalaccount == 'False') {
authenticationService.logOut();
authenticationService.externalAuthData = {
provider: fragment.provider,
userName: fragment.external_user_name,
externalAccessToken: fragment.external_access_token
};
$location.path('/associate');
}
else {
//Obtain access token and redirect to orders
var externalData = { provider: fragment.provider, externalAccessToken: fragment.external_access_token };
authenticationService.obtainAccessToken(externalData).then(function (response) {
$location.path('/home');
},
function (err) {
$scope.message = err.error_description;
});
}
});
}
init();
function parseQueryString(queryString) {
var data = {},
pairs, pair, separatorIndex, escapedKey, escapedValue, key, value;
if (queryString === null) {
return data;
}
pairs = queryString.split("&");
for (var i = 0; i < pairs.length; i++) {
pair = pairs[i];
separatorIndex = pair.indexOf("=");
if (separatorIndex === -1) {
escapedKey = pair;
escapedValue = null;
} else {
escapedKey = pair.substr(0, separatorIndex);
escapedValue = pair.substr(separatorIndex + 1);
}
key = decodeURIComponent(escapedKey);
value = decodeURIComponent(escapedValue);
data[key] = value;
}
return data;
}
function init() {
var idx = window.location.hash.indexOf("ext=");
if (window.location.hash.indexOf("#") === 0) {
fragment = parseQueryString(window.location.hash.substr(idx));
vm.testFn(fragment);
}
}
Aber offensichtlich dies gibt mir einen Fehler Winkel Zusammenhang (die ich keine Ahnung im Moment haben):
https://docs.angularjs.org/error/$rootScope/inprog?p0=$digest
So ziemlich viel es eine Sackgasse ist für mich in diesem Stadium.
Alle Ideen oder Eingaben würden sehr geschätzt werden.
Gracias!
Update: Ich habe es geschafft, den Angular-Fehler über das rootscope zu lösen, aber leider löst das Auflösen das Hauptproblem nicht. Wenn ich versucht habe, das soziale Login auf derselben Browser-Registerkarte zu öffnen, auf der sich meine Anwendung befindet, kann Google sich anmelden und zur Anwendung zurückkehren und die erforderlichen Token übergeben. Anders ist es bei Facebook, wo in der Entwickler-Tool-Konsole eine Warnung erscheint, die Facebook davon abzuhalten scheint, die Login-Seite anzuzeigen.
Ziemlich viel, die ursprüngliche Methode, mit der ein neues Fenster (oder Registerkarte) geöffnet wird, ist der Weg nach vorne, aber das gleiche für den mobilen Browser zu beheben scheint schwieriger zu werden.
Ich würde einige Zeit dauern, diese später am Tag zu testen, . – Batuta
Sie müssen nicht, die 'localStorage' ist Teil der HTML5-API im Browser, eigentlich ist es auf dem' Fenster', Sie können es von überall mit 'window.localStorage' zugreifen – udidu
Habe es gerade ausprobiert und ich bekomme einen rootscope Fehler Fehler: $ rootScope: inprog Aktion läuft bereits – Batuta