Live connect on chrome extension - javascript

Hello I am trying to use Microsoft OAuth in order to be able to login with Outlook credentials inside a chrome extension.
I am using the javascript Library (https://msdn.microsoft.com/en-us/library/hh550844.aspx) but i am not being able to do it. I am doing the following.
WL.init({
client_id: "foo_bar",
scope: "wl.signin",
redirect_uri:"http://www.contoso.com/redirect",
response_type: "token" });
and then
WL.login()
what is happening is that I am being redirected to http://www.contoso.com/redirect
but when I close the popup I get the following message
[WL]WL.login: The popup is closed without receiving consent.
I think the problem is the redirect_uri but how can I do this with a chrome extension?

I finally made it. Just follow this guide
http://blogs.msdn.com/b/onenotedev/archive/2014/07/23/how-to-authenticate-with-microsoft-account-in-a-chrome-extension.aspx
and you have the code here
https://github.com/jameslau-MSFT/MSAuthFromChromeExtSample
High-level Steps
Here are the things you need to do at a high-level:
Create a Client ID and make sure the API settings are set correctly.
Set up your Chrome extension properly to use at least 1 content script. We will need it in #4 below.
Create the UI in your Chrome extension to sign in, making sure you are setting the redirect URL properly to “https://login.live.com/oauth20_desktop.srf” and response type set to “token”.
In your Chrome extension’s content script, watch for the popup window from the Microsoft Account sign in flow. At the right point in time, we will catch the auth_token, store it, and then close the popup window.
Manifest should be something like this
{
"name": "MSAuthFromChromeExtSample",
"short_name": "MSAChromeExt",
"version": "1.0.0",
"description": "Chrome extension that demonstrates how to authenticate against Microsoft Account.",
/*"background":{
"page": "background.html"
},*/
"browser_action": {
/* "default_icon": {
"19": "./assets/icons/icon-19.png",
"38": "./assets/icons/icon-38.png"
},*/
"default_title": "MSA Auth Sample",
"default_popup": "./html/popup.html"
},
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["lib/jquery.min.js", "js/script.js"],
"run_at" : "document_end"
}
],
"permissions": ["history","tabs","storage", "webRequest", "notifications", "<all_urls>"],
"manifest_version": 2,
"update_url": "http://clients2.google.com/service/update2/crx",
"content_security_policy": "script-src 'self' https://js.live.net; object-src 'self'"
}
A few things to point out:
We included js/script.js as a content script. These scripts load each time a document is loaded in a window or tab. We need this to perform #4 above. We also included lib/jquery.min.js as a content script because I wanted to be able to use jquery in my script.js file.
We included “storage” in the permissions set because we will use Chrome storage later to store the auth_token.
We included this line: "content_security_policy": "script-src 'self' https://js.live.net; object-src 'self'" so the LiveSDK JavaScript library can be successfully loaded from popup.html
browser_action.default_popup is set to “./html/popup.html” – this specifies the HTML that will show up when user clicks the browser extension button. We will use this to show the login UI.
Login code
$('a#signin').click(function() {
$('div#signin_status').text('');
WL.init({
client_id: "000000004410CD1A", // replace with your own Client ID!!
redirect_uri: "https://login.live.com/oauth20_desktop.srf",
response_type: "token"
});
WL.login({
scope: ["wl.signin", "office.onenote_create"]
});
return false;
});
Content script
$(window).load(function() {
if (window.location.origin == "https://login.live.com") {
var hash = window.location.hash;
// get access token
var start = hash.indexOf("#access_token=");
if ( start >= 0 ) {
start = start + "#access_token=".length;
var end = hash.indexOf("&token_type");
var access_token = hash.substring(start, end);
// Store it
chrome.storage.local.set({"access_token":access_token});
// Close the window
window.close();
}
}
});

Related

failed to execute postMessage on DOMWindow : target origin

i am working on firefox addon. i have 2 scripts filler.js and aws.js
filler.js
document.getElementById("orderNow").addEventListener("click", function() {
var domain = 'https://www.amazon.com/';
var openWin = window.open(domain);
//message sender
var message = "WS Iron Man";
openWin.postMessage(message,domain); //sending the message
});
aws.js
window.onload = function () {
//alert('page loaded successfully'); //alert function working here
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
if (event.origin !== "http://localhost/waveapp/includes/pages/order_details.html")
return;
// alert to check function working or not
var msg = event.data;
alert(msg);
}
};
manifest.json
{
"manifest_version": 2,
"name": "Borderify",
"version": "1.0",
"description": "Copy details to amazon.com.",
"icons": {
"48": "icons/border-48.png"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["filler.js"]
},
{
"matches": ["*://*.amazon.com/*"],
"js": ["aws.js"]
}
],
"permissions": [
"clipboardRead",
"unlimitedStorage",
"storage"
]
}
filler.js running in my localhost and aws.js run on amazon.com. this is a firefox extension.
when i run, i am getting error msg in console
"Failed to execute ‘postMessage’ on ‘DOMWindow’: The target origin provided (‘https://www.amazon.com’) does not match the recipient window’s origin (‘null’)"
also getting this msg
"Storage access automatically granted for tracker “https://www.amazon.com” on “http://localhost”"
Please help me fix it, i am sorry for my bad english
I suggest you to read into Window.postMessage().
It says and I quote:
Normally, scripts on different pages are allowed to access each other
if and only if the pages they originate from share the same protocol,
port number, and host (also known as the "same-origin policy").
window.postMessage() provides a controlled mechanism to securely
circumvent this restriction (if used properly).
So it is not a CORS error, because those don't apply in this situation.
There are multiple reasons why this might happen:
You are actually using a different URL than the one provided
You closed your open window already (window will set everything to null, when it is closed)
You are doing something in between window.open and window.postMessage, which might change what is stored inside your reference

Content script not executing in new window

I am trying to create a Chrome extension that, when clicked, opens a new incognito window and performs some DOM action on it. These are the files I'm using:
manifest.json
{
"manifest_version": 2,
"name": "SampleExtension",
"description": "",
"version": "1.0",
"incognito": "spanning",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["http://www.google.com"],
"js": ["myscript.js"]
}
],
"permissions": [
"tabs",
"activeTab",
"http://www.google.com"
]
}
popup.js
chrome.windows.create({
"url": "http://www.google.com",
"focused": true,
"incognito": true
});
chrome.tabs.executeScript(null, {
"file": "myscript.js",
"run_at": "document_end",
"all_frames": true
});
myscript.js
document.querySelector('a[target]').click();
The extension opens the new window, but my content script doesn't seem to be executing. Any thoughts?
Edit: Added "incognito": "spanning" to the manifest. Still doesn't work, however.
First of all, I understand that you have enabled to run in Incognito Mode. Extensions are disabled by default and, hence, it would not run otherwise.
Secondly, your match pattern needs to end with a slash:
"matches": ["http://www.google.com/"],
Thirdly, Google will redirect you to its https version, hence I would improve the match pattern like this:
"matches": ["*://www.google.com/"],
Still, it didn't work for me as I was redirected to my local Google domain. Hence, I had to do add more:
"matches": [
"*://www.google.com/*",
"*://www.google.com.sg/*"
],
Also, I added the final wildcard, because Google was adding some ?urlParams that I had to match too. And this made it work. Note that I tried with other pages like "*://www.stackoverflow.com/*", and it was easier than Google :)
In case your Google page was just a test, I'd advise to use some less redirected pages to test with.
A final note: I do not think it's possible to use the wildcard for the domain (I tried). However, you can request all the main domains, or request all_pages and then add the logic for Google only on my_script.js to decide whether to execute the action or not. (However, this last piece is not ideal).
Edit post comments:
It seems your function fails because the element is not loaded yet. An easy way to solve this is by doing an interval which checks whether the element is on the page. When it finds it, clicks it and removes the interval.
// Function which clicks element if existing and clears interval after doing it.
var clickLink = function() {
if (document.querySelectorAll('a[target]').length > 0) {
clearInterval(waitAndClick); // stop interval
document.querySelector('a[target]').click(); // click element.
}
}
// Run click function every second, until it clicks it.
var waitAndClick = setInterval(clickLink, 1000);

Which URLs are restricted to operate on with Chrome extensions? [duplicate]

I have created a Chrome extension that, as part of it's operation, opens a new tab with a specified url.
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "open_new_tab" ) {
chrome.tabs.create({"url": request.url});
}
}
);
(Full code available on GitHub)
This works fine on tabs with webpages, but I cannot get it to work on empty tabs, for example: chrome://apps/ To clarify, if I have a tab open and it is on stackoverflow.com, then when I click on my extension button it opens a new tab loading a generated url. When I am on a new tab, or a tab where the url begins with chrome:// then the extension does not work.
What permissions do I need to include to allow the extension to open in ANY tab? Including new tabs and any chrome:// tab?
Manifest.json:
{
"manifest_version": 2,
"name": "MyMiniCity Checker",
"short_name": "MyMiniCity Checker",
"description": "Checks what your city needs most and redirects the browser accordingly.",
"version": "0.2",
"author":"Richard Parnaby-King",
"homepage_url": "https://github.com/richard-parnaby-king/MyMiniCity-Checker/",
"icons": {
"128": "icon-big.png"
},
"options_page": "options/options.html",
"browser_action": {
"default_icon": "icon.png"
},
"permissions": ["tabs","storage","http://*.myminicity.com/","http://*/*", "https://*/*"],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_scripts": [ {
"matches": [ "http://*/*", "https://*/*"],
"js": [ "jquery-1.11.3.min.js" ]
}]
}
Background.js:
//When user clicks on button, run script
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, { file: "jquery-1.11.3.min.js" }, function() {
chrome.tabs.executeScript(null, { file: "contentscript.js" });
});
});
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "open_new_tab" ) {
chrome.tabs.create({"url": request.url});
}
}
);
It appears as though the background.js file is not being executed. I suspect this to be a permissions. What permissions do I need in order to run this extension in every tab?
Well, this message is supposed to come from a content script you're trying to inject into the current tab.
The widest permission you can request is "<all_urls>", however, there are still URLs that are excluded from access.
You can only normally access http:, https:, file: and ftp: schemes.
file: scheme requires the user to manually approve the access in chrome://extensions/:
Chrome Web Store URLs are specifically blacklisted from access for security reasons. There is no override.
chrome:// URLs (also called WebUI) are excluded for security reasons. There is a manual override in the flags: chrome://flags/#extensions-on-chrome-urls, but you can never expect it to be there.
There is an exception to the above, chrome://favicon/ URLs are accessible if you declare the exact permission.
All in all, even with the widest permissions you cannot be sure you have access. Check for chrome.runtime.lastError in the callback of executeScript and fail gracefully.
As I was wanting this to run on EVERY page it meant I could not have the code in the content script. I moved all the code into the background script:
chrome.browserAction.onClicked.addListener(function(tab) {
//...
chrome.tabs.create({"url": newTabUrl});
//...
});
So when I click on my button the above code is called, using the enclosed jquery script.

Chrome extension: load and execute external script

I have trouble loading and executing external js-script into my chrome extension. Looks the same as this question, but I still cant't figure out why it doesn't work in my case.
The idea is that I want to have in my content script some default function which should parse a web-page content. And for some specific web-pages I want to load and use specific parsers, so I try to load proper js-script for a wep-page, and this script shoud extend functionality of default parser.
By now I try only execute code from external script, but have such error: Unchecked runtime.lastError while running tabs.executeScript: No source code or file specified at Object.callback
This is my manifest.json:
{
"name": "Extension name",
"version": "1.2",
"description": "My chrome extension",
"browser_action": {
"default_popup": "popup.html",
},
"content_scripts": [{
"css": [
"style.css"
],
"js": [
"bower_components/jquery/dist/jquery.js",
"bower_components/bootstrap/dist/js/bootstrap.js",
"content.js"
],
"matches": ["*://*/*"]
}],
"web_accessible_resources": [
"frame.html",
"logo-48.png"
],
"icons": {
"16": "logo-16.png",
"48": "logo-48.png",
"128": "logo-128.png"
},
"permissions": [
"tabs",
"storage",
"http://*/",
"https://*/"
],
"manifest_version": 2
}
This is popup.html
<!doctype html>
<html>
<head>
<title>Title</title>
<script src="popup.js"></script>
</head>
<body>
<ul>
<li>Some link</li>
</ul>
</body>
</html>
And in popup.js i execute scrip like this:
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.executeScript(tabs[0].id, {file: "http://127.0.0.1:8000/static/plugin/somesite.js"});
});
What am I dong wrong, did I miss something? Or should I use another approach to solve the issue?
Running scripts from external sources like you try is forbidden by google chrome and will block or even not publish your extension. All scripts must be in the extension. But there is a solution,
from google chrome doc:
The restriction against resources loaded over HTTP applies only to
those resources which are directly executed. You're still free, for
example, to make XMLHTTPRequest connections to any origin you like;
the default policy doesn't restrict connect-src or any of the other
CSP directives in any way.
If you need badly an external source, you can do a XML HTTP request and use the eval to the content. Here is a part of code from google doc:
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://127.0.0.1:8000/static/plugin/somesite.js", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// WARNING! Might be evaluating an evil script!
var resp = eval("(" + xhr.responseText + ")");
// Or this if it's work
chrome.tabs.executeScript(tabs[0].id, {code: xhr.responseText});
}
}
xhr.send();
or you can use some library, $.get() with jquery or $http with angularjs.
if you add eval in your code you must add in manifest.json this:
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"`,
As per the discussion here: https://groups.google.com/a/chromium.org/forum/#!topic/chromium-extensions/LIH7LGXeQHo,
Running scripts from external sources may cause your extension to be unpublished or blocked.
Just providing another approach, you could make an ajax call to the content script then call chrome.tabs.executeScript
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
$.get("http://127.0.0.1:8000/static/plugin/somesite.js", function(result) {
chrome.tabs.executeScript(tabs[0].id, {code: result});
}, "text");
});
The 'file' option for executeScript only relates to files embedded in your extension. I know, the documentation isn't clear on that and while it might work with URLs, it sounds like a hack, not a feature. In order to load scripts from external sources into your active page, you usually have to execute a script that creates a script tag inside the DOM of the loaded document there.
I feel I have answered parts of this question before here: Why is chrome.tabs.executeScript() necessary to change the current website DOM and how can I use jQuery to achieve the same effect?
To summarize:
1) in order to have access to web pages from the extension, you need to add permissions for it:
"permissions" : [
"tabs",
[...]
"http://*/*",
"https://*/*" ],
2) you need to execute some sort of code that creates the DOM script element that loads what you need:
chrome.tabs.executeScript(tab.id, {
code : 'var script=document.createElement(\'script\');' +
'script.onload=function() { /*do something in the page after the script was loaded*/ };' +
'script.src=\'http://127.0.0.1:8000/static/plugin/somesite.js\';' +
'document.body.appendChild(script);'
}, function (returnedValue) {
// do something in the extension context after the code was executed
});
Take a look at the remex function in the link above, which I think solves a lot of the ugliness of javascript written as a string as here.

Accessing Cookies in Chrome Extension

I'm trying to write a chrome extension that works with YouTube and need to access some of YouTube's cookie information. I cant seem to get my extension to see any cookies. (Even though I can see them under resources in the "Inspect Element" developer portion of Chrome).
I'm pretty sure I've set up permissions correctly in the manifest 2 file because when I take out the "cookies" permission just to test it I get an error saying "Cannot call method 'getAll'". My current problem is just that no cookies are returned by the callback function.
{
"manifest_version": 2,
"name": "YouTube Viewer",
"description": "This extension is for YouTube videos.",
"version": "1.7",
"icons": {
"128": "ytblack.png"
},
"permissions": [
"cookies",
"https://www.youtube.com/",
"http://www.youtube.com/",
"tabs",
"storage"
],
"background": {
"scripts": ["bootstrap.js"],
"persistent": false
},
"page_action": {
"default_title": "YT View",
"default_icon": "ytblack.png",
"default_popup": "popup.html"
}
}
My manifest calls the bootstrap.js. Inside bootstrap.js there is a call to another file ytview.js but I'm not concerned with that. The code in that is working fine. But inside bootstrap.js my cookies.length is returning as 0 when I look at my "background page" console. The log for "Callback for cookies came in fine." fires correctly. But then it says "cookies.length=0". Like I said, I know the cookies exist because I can see them in the resources.
chrome.tabs.onUpdated.addListener(function(id, info, tab){
// decide if we're ready to inject content script
if (tab.status !== "complete"){
console.log("not yet");
return;
}
if (tab.url.toLowerCase().indexOf("youtube.com/watch") === -1){
console.log("you are not on a YouTube video");
return;
}
chrome.cookies.getAll({domain: "www.youtube.com"}, function(cookies) {
console.log('Callback for cookies came in fine.');
console.log('cookies.length=' + cookies.length);
for(var i=0; i<cookies.length;i++) {
console.log('cookie=' + cookies[i].name);
}
});
chrome.tabs.executeScript(null, {"file": "ytview.js"});
});
Any ideas why no cookies are being returned? Maybe something with "domain" in the .getAll statement? I've tried lots of combinations like www.youtube.com, youtube.com, https://www.youtube.com with no luck.
for future users:
youtube.com use ".youtube.com" as cookie domain to allow the site to share cookies across all youtube subdomains so in your example you should use domain name without 'www' subdomain for example:
chrome.cookies.getAll({domain: "youtube.com"}, function(cookies) {
//...
});
you can clearly see cookies domain using default chrome developer tools
I figured it out. In my manifest I was asking for permission on www.youtube.com but the cookies I was trying to read were on simply youtube.com without the www. Adding the plain youtube.com to the permissions in manifest fixed it.

Categories

Resources