I want to make a Chrome extension that does this (automatically logs onto a website, probably not the best approach since it was my first time doing JS) and has an option page where the user can set up his info and get it saved (localstorage?) so that the content script can access it as well as the options page.
Here's what I've come to after a whole lot of researching, looking at examples etc.:
http://pastebin.com/yTiXp4VY (source code of all files there).
In the end I gave up and just used trial and error so there's tons of errors there. The console is reporting it can't run for security reasons. Please explain me what is wrong with this version. I don't need you to fix my code, I am just learning JS.
For most part you code seems to be correct. Only one note: your options page can access localStorage directly, it doesn't need the background page for that. But the main issue seems to be the way your content script is built - it assumes that the user/password data will be available immediately (synchronously). That's not how it works: you are sending a message to the background page, eventually the background page will answer and your callback in the content script will be called. The simplest approach is to delay all actions until that happens and you have the data. And it should be easier to send a single message to the background page that will give you all the data. Something like this:
var userName = null;
var passWord = null;
chrome.extension.sendRequest( { eventName: "getLogin" },
function(response) {
userName = response.user;
passWord = response.pass;
// Now we can continue doing whatever we are doing
checkIfAutoUrl();
}
);
And the message processing in your background page would look like this:
function onRequest(request, sender, sendResponse) {
if (request.eventName == "getLogin") {
sendResponse({user: getStorage("user"), pass: getStorage("pass")});
}
}
Note that the response is an object with two properties user and pass here - this way the content script can immediately continue once it got the response, it has all the necessary data and doesn't need to wait for a second response.
Update: Concerning the error message you get: the Content Security Policy is meant to protect your extension from being exploited by a malicious website. One part of that protection is disallowing inline scripts in HTML - like onload="load_options()". All scripts that will run need to be placed in your JavaScript files. So instead of this onload attribute you can put the following into options.js:
window.addEventListener("load", load_options, false);
See addEventListener documentation on MDN.
Related
We're using both GFC as our consent platform and client side PreBid along with Google DFP.
The implementation looks correct and most of the time we see the bids appearing correctly along with the consent tokens, however, on some occasions we get the following error message from prebid:
ERROR: CMP not found. Canceling auction as per consentManagement config. undefined.
We load both scripts asynchronously, but we do load Google's script first and then Prebid.js right after that.
We suspect that Google's implementation doesn't create the __tcfapi or __cmp objects immediately on the global scope, and that if those are not present, PreBid cancels the auction and doesn't fire the bids.
Did anyone else stumble upon this issue and can verify? Is there a way to prevent this from happening without delaying the page load or the ads? If not, is there a way to register an error handler on prebid?
We had the same problem. We use fundingchoices which is now integrated into Google AdManager.
Try
window.googlefc = window.googlefc || {};
window.googlefc.ccpa = window.googlefc.ccpa || {}
window.googlefc.callbackQueue = window.googlefc.callbackQueue || [];
// wait for consent
googlefc.callbackQueue.push({
'CONSENT_DATA_READY': () => {
// do prebidding
}
});
But it seems to be very slow as the Google Publisher Tag (gpt.js) must be loaded which then decides that a FundingChoice/CMP is needed which gets loaded and then after a while the consent is available.
We don't have it production because it is too slow. Does somebody knwo how to speed things up with fundingchoice aka AdManger-GDPR-Messages
I have a custom button which is to query and possibly update an Administration App in Quickbase, which the current user doesn't require access to.
I have JS code which is executed on a button click by the user to check the admin app, etc...
my API call to check the app has the appropriate apptoken and usertoken. However, the browser still has the current user's session cached, so the API call errors out with an access denied error message.
I'm looking for either a way to make a hidden incognito window, to then execute this code, or a way to problematically force the usertoken to supersede the current user access/permissions.
I've seen where chrome extensions can use chrome.windows.create... but I have no experience with extensions, and Ideally, I don't want to have to have an extension for just this functionality, and have to possibly install it on every user's PC for this to work...
Here is a snippet of my current code... This code does work if someone has permissions to the Administration App... but this code is residing in a different application:
PreProcURL = "https://<domain>.quickbase.com/db/<dbid>?a=API_DoQuery&apptoken=<>&usertoken=<>&query={'3'.EX.'1'}";
PreProcQuery.open('GET', PreProcURL, 'async');
PreProcQuery.send();
PreProcQuery.onload = function(){
console.log(PreProcQuery.responseXML);
RunBit = (PreProcQuery.responseXML.documentElement.getElementsByTagName("runbit"))[0].innerHTML;
SupportData = (PreProcQuery.responseXML.documentElement.getElementsByTagName("supportdata"))[0].innerHTML;
if(RunBit != "1"){
$.get("https://<domain>.quickbase.com/db/<dbid>?a=API_EditRecord&rid=1&_fid_6=1&_fid_7="+rid+"&apptoken=<>&usertoken=<>");
}else{
if(SupportData == rid){
alert("This PreProc File is already in progress... please wait.");
}else{
alert("Another PreProc is already in progress... please wait.");
}
}
};
Thanks in advance for any assistance on this.
API calls executed in JavaScript that is hosted within quickbase.com (button, pages, etc.) will run as that logged in user that triggered the script. The usertoken gets ignored.
The most common way to accomplish what you are after is to write the API_DoQuery code on a server side location and then trigger it from your JS code.
I have been reading over the chrome extension message passing documentation, but I cannot seem to establish communication from within the inspected window.
For example,
chrome.devtools.inspectedWindow.eval('function() {
.
.
.
/* send message to dev-tools panel */
chrome.runtime.sendMessage({foo:"foo"});<-- Uncaught Error: Invalid arguments to connect. Why is the extensionId required within chrome.devtools.inspectedWindow.eval? This made me step back and ask the question.
}')
I have tried leveraging both background and content scripts to listen for these messages, but nothing seems to trigger. My actual implementation is listening for WebSocket traffic, I left that out for brevity. I am able to listen to each request/response, however I cannot seem to establish communication within inspectedWindow.eval. In the end, my goal is to simply communicate with my dev-tools panel so I can update the UI.
Update
I found an interesting repo from someone that faced a similar issue. They however did not seem to find a valid solution. Could it be that this sort of messaging is not allowed by design?
https://github.com/thomasboyt/injectedWindow.eval-communication-sadness
You said you considered using a content script.
In that case, you can raise a custom DOM event, and the content script will be able to process it.
// Content script
window.addEventListener("RebroadcastExtensionMessage", function(evt) {
chrome.runtime.sendMessage(evt.detail);
}, false);
// Eval'd code
var message = {/* whatever */};
var event = new CustomEvent("RebroadcastExtensionMessage", {detail: message});
window.dispatchEvent(event);
The downside, of course, is that the page can listen in on those events if it so chooses as well as spoof them. If that's a serious concern, you can include nonces into event names and messages originating from dev tools. But then again, a really hostile page can override CustomEvent.. In a way, this is not a solvable problem, since anything you inspectedWindow.eval() fully shares context (and API access) with the page.
I've been trying to figure out a way to use notifications on a background process and couldnt find anything online about it. So, I figured out one way around it and wanted to share (Not sure if this is the best way to go about doing this but here goes:)
Problem: I want to notify the user of new info when the page is running but in the background (blurred). I could use alert('new info!'); to get the taskbar icon to flash, but then you have to manually dismiss it (tried it and it's hella annoying). I really liked the notifications, but they only work if the user performs an action, so not helpful...
I hope I won't be telling something stupid, but from where I see it (and remember from school) that's basically how http works : a request is sent to the server, which issues a response eventually after executing some server-side code.
Basically you're asking for a "PUSH" functionality from server to client, and in that case you can't make use of HTTP.
Some tricks exist to work around this limitation, but basically they're all issuing requests at a certain frequency (Dave's answer does exactly that). If your site doesn't change that much, that means a lot of requests are issued for no reason (nothing has changed), consuming bandwith for nothing.
From what I know, the answer to this is called Websockets, which are supported by recent browsers only. I never had the chance to use it though so I couldn't tell much more about it. This allows full duplex communication, thus allowing server to "push" data to the client. I guess that's what SO uses for "new message" notifications (top left of the screen - you see immediately when you receive a new message)
My solution: I made a chrome extension that runs in the background and triggers the notifications. It's a little limited in scope as you need to have chrome to do it, but it does what i need it to, and for the purposes of the problem i'm working on, i can just make my user group use chrome ;D
The specifics: The extension only has two components, the manifest and a script. Currently, i setup the manifest so that it only works on my site using the match identifier... and i set the permissions to include notifications.
The JS script has a window.setinterval that looks for an element in the page with the id NOTIFIER. If it's empty, it does nothing, otherwise it creates a notification based on the content and then clears the content to prevent showing the same notification multiple times... (I tried using .onchange for that element, but couldn't get the event to trigger... I'd prefer to do this on an event rather then setInterval)
Notify.js
function onExtLoad() {
var timer = setInterval(refresh,1000);
}
document.addEventListener('DOMContentLoaded', onExtLoad());
function refresh() {
if (document.getElementById('NOTIFIER').innerHTML == "") {
//do nothing?
} else {
var notification = webkitNotifications.createNotification("",
"You got a new message",
document.getElementById('NOTIFIER').innerHTML);
notification.show();
document.getElementById('NOTIFIER').innerHTML = "";
}
}
Then, all i need to do is have the JS on the page control when it adds info the the NOTIFIER and voila! notifications!
Hope this helps someone else.
#ExpertSystem: I messed around with the MutationObserver but I can only get it to trigger once. Here's a JSFiddle: http://jsfiddle.net/BTX8x/1/
Am I missing something? Is there a way to reset it?
EDIT: Figured it out, i needed subtree:true
I am starting to build/design a new single page web application and really wanted to primarily use client-side technology (HTML, CSS, JavaScript/CoffeScript) for the front-end while having a thin REST API back-end to serve data to the front-end. An issue that has come up is about the security of JavaScript. For example, there are going to be certain links and UI elements that will only be displayed depending on the roles and resources the user has attached to them. When the user logs in, it will make a REST call that will validate the credentials and then return back a json object that has all the permissions for that user which will be stored in a JavaScript object.
Lets take this piece of javascript:
// Generated by CoffeeScript 1.3.3
(function() {
var acl, permissions, root;
root = typeof exports !== "undefined" && exports !== null ? exports : this;
permissions = {
//data…
};
acl = {
hasPermission: function(resource, permission, instanceId) {
//code….
}
};
root.acl = acl;
}).call(this);
Now this code setup make sure even through the console, no one can modify the variable permissions. The issue here is that since this is a single page application, I might want to update the permissions without having to refresh the page (maybe they add a record that then needs to be added to thier permissions). The only way I can think of doing this is by adding something like
setPermission: function(resource, permission, instanceId){
//code…
}
to the acl object however if I do that, that mean someone in the browser console could also use that to add permissions to themself that they should not have. Is there any way to add code that can not be accessed from the browser console however can be accessed from code in the JavaScript files?
Now even if I could prevent the issue described above, I still have a bigger one. No matter what I am going to need to have the hasPermission functionality however when it is declared this way, I can in the browser console overwrite that method by just doing:
acl.hasPermission(resource, permission, instanceId){return true;}
and now I would be able to see everything. Is there anyway to define this method is such a way that a user can not override it (like marking it as final or something)?
Something to note is that every REST API call is also going to check the permissions too so even if they were to see something they should not, they would still not be able to do anything and the REST API would regret the request because of permissions issue. One suggestion has been made to generate the template on the server side however I really don't like that idea as it is creating a very strong coupling between the front-end and back-end technology stacks. If for example for whatever reason we need to move form PHP to Python or Ruby, if the templates are built on the client-side in JavaScript, I only have to re-build the REST API and all the front-end code can stay the same but that is not the case if I am generating templates on the server side.
Whatever you do: you have to check all the permissions on the server-side as well (in your REST backend, as you noted). No matter what hoops you jump through, someone will be able to make a REST call that they are not supposed to make.
This effectively makes your client-side security system an optimization: you try to display only allowed operations to the user and you try to avoid round-trips to the server to fetch what is allowed.
As such you don't really need to care if a user can "hack" it: if they break your application, they can keep both parts. Nothing wrong can happen, because the server won't let them execute an action that they are not authorized to.
However, I'd still write the client-side code in a way that it expect an "access denied" as a valid answer (and not necessary an exception). There are many reasons why that response might come: If the permissions of the logged-in user are changed while he has a browser open, then the security descriptions of the client no longer match the server and that situation should be handled gracefully (display "Sorry, this operation is not permitted" and reload the security descriptions, for example).
Don't ever trust Javascript code or the front-end in general. People can even modify the code before it reaches your browser (sniffers etc) and most variables are accessible and modifiable anyways... Trust me: you are never going to be safe on the front-end :)
Always check credentials on the server-side, never only on the front-end!
In modern browsers, you can use Object.freeze or Object.defineProperty to make sure the hasPermission method cannot be redefined.
I don't know yet how to overcome the problem with setPermission. Maybe it's best to just rely on the server-side security there, which as you said you have anyway.