Je développe un flux d'authentification OAuth uniquement en JavaScript et je souhaite montrer à l'utilisateur la fenêtre "Accorder l'accès" dans une fenêtre contextuelle, mais elle est bloquée.
Comment puis-je empêcher les fenêtres contextuelles créées par window.open
ou window.showModalDialog
d'être bloquées par les bloqueurs de fenêtres contextuelles des différents navigateurs?
La règle générale est que les bloqueurs de popup seront activés si window.open
ou similaire est invoqué à partir de javascript non invoqué par action directe de l'utilisateur . Autrement dit, vous pouvez appeler window.open
en réponse à un clic sur un bouton sans vous faire toucher par le bloqueur de popup, mais si vous mettez le même code dans un événement de minuterie, il sera bloqué. La profondeur de la chaîne d'appels est également un facteur - certains navigateurs plus anciens ne consultent que l'appelant immédiat. Les nouveaux navigateurs peuvent revenir en arrière pour voir si l'appelant a été un clic de souris, etc. Gardez-le aussi superficiel que possible pour éviter les bloqueurs de popup.
Basé sur Jason Sebring 's astuce très utile , et sur les éléments couverts ici et là , j'ai trouvé la solution parfaite pour mon cas:
Pseudo-code avec extraits de code Javascript:
créer immédiatement un popup vide sur l'action de l'utilisateur
var importantStuff = window.open('', '_blank');
Facultatif: ajoutez un message d'information "en attente". Exemples:
a) Une page HTML externe: remplacez la ligne ci-dessus par
var importantStuff = window.open('http://example.com/waiting.html', '_blank');
b) Texte: ajoutez la ligne suivante sous celle ci-dessus:
importantStuff.document.write('Loading preview...');
remplissez-le avec le contenu lorsqu'il est prêt (lorsque l'appel AJAX est renvoyé, par exemple)
importantStuff.location.href = 'http://shrib.com';
Enrichissez l'appel en window.open
avec les options supplémentaires dont vous avez besoin.
En fait, j'utilise cette solution pour une redirection mailto, et cela fonctionne sur tous mes navigateurs (Windows 7, Android). Le bit _blank
permet à la redirection mailto de fonctionner sur mobile, btw.
Ton expérience? Un moyen d'améliorer cela?
En plus de Swiss Mister post, dans mon cas, le window.open a été lancé dans le cadre d’une promesse qui a activé le bloqueur de popup, ma solution était:
$scope.gotClick = function(){
var myNewTab = browserService.openNewTab();
someService.getUrl().then(
function(res){
browserService.updateTabLocation(res.url, myNewTab);
}
);
};
browserService:
this.openNewTab = function(){
var newTabWindow = $window.open();
return newTabWindow;
}
this.updateTabLocation = function(tabLocation, tab) {
if(!tabLocation){
tab.close();
}
tab.location.href = tabLocation;
}
voici comment vous pouvez ouvrir un nouvel onglet en utilisant la réponse de promesse sans invoquer le bloqueur de popup.
En tant que bonne pratique, je pense que c'est une bonne idée de tester si un popup est bloqué et de prendre des mesures au cas par cas. Vous devez savoir que window.open a une valeur de retour, et cette valeur peut être null si l'action a échoué. Par exemple, dans le code suivant:
function pop(url,w,h) {
n=window.open(url,'_blank','toolbar=0,location=0,directories=0,status=1,menubar=0,titlebar=0,scrollbars=1,resizable=1,width='+w+',height='+h);
if(n==null) {
return true;
}
return false;
}
si le popup est bloqué, window.open retournera null. Donc, la fonction retournera false.
Par exemple, imaginez que vous appelez cette fonction directement à partir de n’importe quel lien avec
target="_blank"
: si le popup est ouvert avec succès, en retournantfalse
bloquera l'action du lien, sinon si le popup est bloqué, renvoyertrue
laissera le comportement par défaut (ouvrir une nouvelle fenêtre _blank ) et continuer.
<a href="http://whatever.com" target="_blank" onclick='return pop("http://whatever.com",300,200);' >
De cette façon, vous aurez un popup si cela fonctionne, et une fenêtre _blank si ne pas.
Si le popup ne s'ouvre pas, vous pouvez:
http://code.google.com/p/google-api-javascript-client/wiki/Authentication
Voir la zone où il se lit:
Configuration de l'authentification
L'implémentation d'OAuth 2.0 par le client utilise une fenêtre contextuelle pour inviter l'utilisateur à se connecter et à approuver l'application. Le premier appel à gapi.auth.authorize peut déclencher des bloqueurs de popup, car il ouvre la fenêtre popup indirectement. Pour empêcher le bloqueur de fenêtres contextuelles de se déclencher lors d'appels autorisés, appelez gapi.auth.init (rappel) lors du chargement du client. Le rappel fourni sera exécuté lorsque la bibliothèque sera prête à passer des appels avec authentification.
Je suppose que c'est lié à la vraie réponse ci-dessus dans la façon dont il explique s'il y a une réponse immédiate, cela ne déclenchera pas l'alarme contextuelle. Le "gapi.auth.init" fait en sorte que l'api se produit immédiatement.
Application pratique
J'ai créé un microservice d'authentification à source ouverte en utilisant le nœud passport sur npm et les différents packages de passeports pour chaque fournisseur. J'ai utilisé une approche de redirection standard au tiers en lui donnant une URL de redirection vers laquelle revenir. C’était programmatique afin que je puisse avoir différents endroits pour rediriger si je me connectais/m'inscris et sur des pages particulières.
Je ne voulais pas faire la nouvelle page à moins que le rappel soit retourné avec succès, alors je l'ai fait pour simuler l'utilisateur cliquer:
function submitAndRedirect {
apiCall.then(({ redirect }) => {
const a = document.createElement('a');
a.href = redirect;
a.target = '_blank';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
});
}
J'ai essayé plusieurs solutions, mais c'est la seule qui a réellement fonctionné pour moi dans tous les navigateurs.
let newTab = window.open();
newTab.location.href = url;