next-auth + Chrome extension - google-chrome-extension

I would like to use next-auth on a site that has a front-end as well as a backend. That is easy with next-auth, however, I can't figure out a way of authenticating users from a Chrome extension that would communicate with the backend.
The idea is to create data on the site and be able to use it with the Chrome extension for the user that created it.
I can't store secrets on the Chrome extension.
Any ideas?
I have an idea of authenticating users like on TVs and other devices.. they generate a code on the site and insert it on the Chrome extension. Of course, it would be valid for a short time.
But before I go on that road I would like to hear if someone has a better solution.

What worked for me was to make a request from the extension to the next-auth session endpoint: /api/auth/session
If a session doesn't exist, I'll open a new tab with the login page then go from there.
Here's what my manifest.json looks like:
{
"manifest_version": 3,
"name": "Timer Extension",
"version": "1.0.0",
"description": "Hello Chrome World!",
"icons": {
"16": "grin.png",
"48": "grin.png",
"128": "grin.png"
},
"action": {
"default_icon": {
"16": "grin.png",
"24": "grin.png",
"32": "grin.png"
},
"default_title": "Timer Extension Action Title",
"default_popup": "popup.html"
},
"background": {
"service_worker": "authCheck.js"
},
"host_permissions": [
"https://*/"
]
}
Here's the authCheck.js service worker:
chrome.runtime.onMessage.addListener(
function (request, sender, onSuccess) {
console.log("running check")
fetch("<your-domain>/api/auth/session", {
mode: 'cors',
})
.then(response => response.json())
.then((session) => {
if (Object.keys(session).length > 0) {
onSuccess(session)
} else {
onSuccess(null)
}
})
.catch(err => {
console.error(err);
onSuccess(null)
})
return true; // Will respond asynchronously.
}
);
Then in the js file for the default_popup html I have this:
chrome.runtime.sendMessage(
{action: 'AUTH_CHECK'},
(session) => {
if (session) {
//user is logged in
} else {
//no session means user not logged in
chrome.tabs.create({
url: '<link to your login page>'
});
}
}
);

Related

How to access iframes using scripting API?

I have a chrome extension I need to access all the iframes on the attached page using the scripting API
{
"manifest_version": 3,
"name": "My example extension",
"version": "0.0.1",
"permissions": ["tabs", "scripting"],
"devtools_page": "devtools.html",
"host_permissions": [
"<all_urls>"
]
}
I can run the script on the inspectedWindow easily enough
// devtools.html -> js
chrome.devtools.panels.create("Sample Panel", "icon.png", "/panel.html", panel => {
// code invoked on panel creation
});
// panel.html -> js
chrome.scripting.executeScript({
target: { tabId: chrome.devtools.inspectedWindow.tabId },
injectImmediately: true,
func: () => {
console.log('foo')
}
})
I want this script to run on the page and all children iframes immediately (before anything else is run, just like a content_script).
It seems this only runs on the host page. When I try to query for child iframes, it doesn't seem to find anything
> await chrome.tabs.query({ windowId: chrome.devtools.inspectedWindow.tabId })
// []
Did I miss a permission?

declarativeNetRequest Regex rules for redirecting YT shorts work when the url is typed out or opened in a new tab but not when clicked from YT itself

I'm making a Chrome extension from redirecting youtube.com/shorts/... to youtube.com/watch?v=...
Everything works fine when I open those shorts links in new tabs or when I type them out but when I click from the homepage itself, they don't get redirected.
Here is my rules.json file:
[
{
"id": 1,
"priority": 1,
"action": { "type": "redirect", "redirect": { "regexSubstitution":"https://youtube.com/watch?v=\\1" } },
"condition": { "regexFilter": "^.*youtube\\.com/shorts/(.*)", "resourceTypes": ["main_frame"] }
}
]
Here is my manifest.json file:
{
"manifest_version": 3,
"name": "No Shorts",
"version": "0.5",
"description": "Play YT shorts as regular videos instead of in a separate player",
"action": {
"default_icon": "images/no-shorts-ico.png"
},
"declarative_net_request": {
"rule_resources": [{
"id": "ruleset_1",
"enabled": true,
"path": "rules.json"
}]
},
"icons":{
"16": "images/16.png",
"48": "images/48.png",
"128": "images/128.png"
},
"permissions":[ "declarativeNetRequest"],
"host_permissions":["*://*.youtube.com/*"]
}
I clicked on a short video from the homepage and it did not get redirected. However, when I refreshed it, it did get redirected. It also got redirected when I clicked open in new tab or typed out the url myself.
If I had to guess, I think it is happening because of something that is similar to client-side navigation but I really can't say for sure. Is there a fix for this?
There is no network request to intercept in such inner navigation as it uses the history API in JS.
You can run a script on the entire youtube domain and intercept the click event:
// page.js:
addEventListener('click', e => {
const thumb = e.target.closest('ytd-thumbnail');
const cmd = thumb?.__data.data.navigationEndpoint.commandMetadata.webCommandMetadata;
if (cmd?.webPageType !== 'WEB_PAGE_TYPE_SHORTS') return;
cmd.webPageType = 'WEB_PAGE_TYPE_WATCH';
cmd.url = cmd.url.replace('/shorts/', '/watch?v=');
for (const a of thumb.querySelectorAll('a'))
a.href = a.href.replace('/shorts/', '/watch?v=');
}, true);
// manifest.json:
"background": { "service_worker": "bg.js" },
"permissions": ["scripting"],
"host_permissions": ["*://www.youtube.com/"],
// bg.js
chrome.runtime.onInstalled.addListener(async () => {
const scripts = [{
id: 'page',
world: 'MAIN',
matches: ['*://www.youtube.com/*'],
runAt: 'document_start',
js: ['page.js'],
}];
await chrome.scripting.unregisterContentScripts({ids: scripts.map(s => s.id)})
.catch(() => {});
await chrome.scripting.registerContentScripts(scripts);
for (const script of scripts) {
const execCfg = {
target: {},
files: script.js,
injectImmediately: true,
world: script.world,
};
for (const tab of await chrome.tabs.query({url: script.matches})) {
execCfg.target.tabId = tab.id;
chrome.scripting.executeScript(execCfg);
}
}
});

Chrome Extension: Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist

Recently, it is reported that the context menu of my app is vanished. If you remove the app and reinstall it, it works. But the vanishment happens again.
I found an error. I'm not sure if the error causes the vanishment of the context menu. But I'd like to fix this matter, because all I found is this.
This app shows texts you select in a page. When you select texts in an ordinaly page and click browser action button, it works without error. But if you try it on Google Docs, you will get error "Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist".
I'm afraid I don't know what to do with this. And I might have two problems. It'll be great help if you could give me some advice.
[manifest.js]
{
"manifest_version": 2,
"name": "Test Chrome Extension",
"short_name": "Test",
"version": "1.0",
"description": "This is a test.",
"icons": {
"128": "128.png"
},
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["googleDocsUtil.js", "content_scripts.js"]
}],
"background": {
"scripts": ["background.js"],
"persistent": true
},
"browser_action": {
"default_icon": {
"48": "48.png"
},
"default_title": "Test Chrome Extension"
},
"permissions": [
"contextMenus",
"tabs",
"background",
"http://*/*",
"https://*/*"
]
}
[background.js]
chrome.contextMenus.create({
type: 'normal',
id: 'testchromeextension',
title: 'Test Chrome Extension',
contexts:['selection']
});
chrome.contextMenus.onClicked.addListener(function(info,tab){
if( info.menuItemId == 'testchromeextension' ){
var selectedText = info.selectionText.replace(/ /g, "\n");
doSomething(selectedText);
}
});
chrome.browserAction.onClicked.addListener( function(tab) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {method: "getSelection"}, function(response) {
doSomething(response.data);
});
});
});
function doSomething(selectedText) {
console.log(selectedText);
}
[content_scripts.js]
chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) {
if (request.method == "getSelection") {
var post_val = window.getSelection().toString();
if ( !post_val ) {
var googleDocument = googleDocsUtil.getGoogleDocument();
post_val = googleDocument.selectedText;
}
sendResponse({data: post_val});
}
});
I believe this error is caused when you update the local version of an extension and then try to use the extension with its old/not-updated source code.
The fix: after you reload your local extension at chrome://extensions/, make sure you refresh the page you're using the extension on. You should no longer see the error.

Why I get an undefined object when I use chrome.bluetooth.getAdapterState?

I'm using Google Chrome 33.0.1729.3 dev on Linux (elementary os 0.2 based on Ubuntu 12.04)
I create a Chrome App and configured the manifest.json to grant bluetooth permissions:
{
"name": "App Name",
"description": "App Desc",
"version": "0.1.0",
"app": {
"background": {
"scripts": ["background.js"]
}
},
"permissions": ["bluetooth"],
"icons": { "16": "app-icon-16.png", "128": "app-icon-128.png" }
}
when I trigger this script on the app
chrome.bluetooth.getAdapterState( function( result ) {
console.log( result );
});
The result is an undefined
According to the documentation of Google Chrome Apps the method returns an AdapterState object to the callback.
What I'm doing wrong?
Try this:
chrome.bluetooth.getAdapterState( function( result ) {
if (result) {
console.log(result);
} else {
console.log(chrome.runtime.lastError);
}
});
Many of the chrome.* APIs use chrome.runtime.lastError to communicate errors to you. Even though it's not documented at http://developer.chrome.com/apps/bluetooth.html, it might work in this case.

Chrome ext tabs :Port error: Could not establish connection. Receiving end does not exist

i try to connect to just created new tab , my end mission is to update html widget on all open tabs
any way each time i try to connect to tabs via id i fail with error . im using Version 23.0.1271.64 m
var channelTabs = [];
function isInclude(arr,obj) {
return (arr.indexOf(obj) != -1);
}
chrome.tabs.onCreated.addListener(function(tab) {
// add tab when opened
if (channelTabs.indexOf(tab.id) == -1) {
channelTabs.push(tab.id);
}
chrome.windows.getCurrent(function(win)
{
// get an array of the tabs in the window
chrome.tabs.getAllInWindow(win.id, function(tabs)
{
for (i in tabs) // loop over the tabs
{
// if the tab is not the selected one
if(isInclude(channelTabs,tabs[i].id))
{
if(/^(https?|file):/.test(tabs[i].url))
{
console.log('Debug Background sending update to open tab id:'+tabs[i].id);
var port = chrome.tabs.connect(tabs[i].id,{name: "content_tab_request"});
port.postMessage({resp: "tab_update",data:"some string song1"});
}
}
}
});
});
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo,tab) {
// Example: allow http:, https: and file:
if (/^(https?|file):/.test(tab.url)) {
console.log('Debug Background sending onUpdated to open tab id:'+tabId);
var port = chrome.tabs.connect(tabId,{name: "content_tab_request"});
port.postMessage({resp: "tab_update",data:"some string song1"});
}
});
});
but each time it try to chrome.tabs.connect it gives me :
Port error: Could not establish connection. Receiving end does not exist. miscellaneous_bindings:235
chromeHidden.Port.dispatchOnDisconnect miscellaneous_bindings:235
chrome.Event.dispatch_ event_bindings:371
dispatchArgs event_bindings:249
chromeHidden.Event.dispatchEvent
and the content script :
// Register this tab to the background script
var port = chrome.extension.connect({name: "content_request"});
port.postMessage({req: "Hello"});
port.onMessage.addListener(function(msg) {
if (msg.resp == "World")
{
port.postMessage({answer: "good"});
}
else if(msg.answer == "bye")
{
console.log('Debug contentscript.js reciving answer from background msg.answer:'+msg.answer);
}
else
{
console.log('Debug contentscript.js reciving answer from background is wrong:'+msg);
}
if(port.name == "content_tab_request")
{
console.log('Debug contentscript.js reciving request from background Tab function:'+msg);
if(msg.resp=="tab_update ")
{
var data_recive = msg.data;
console.log('Debug contentscript.js reciving request data from background Tab to update page data_recive:'+data_recive);
}
}
});
json file :
{
"background": {
"page": "background.html"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["contentscript.js"],
"run_at": "document_start",
"all_frames": true
}
],
"web_accessible_resources": [
"script_inpage.js"
],
"browser_action": {
"default_icon": "icon19.png",
"default_popup": "popup.html",
"default_title": "Simple test"
},
"content_security_policy": "script-src 'self'; media-src *; object-src 'self'",
"description": "Simple test.",
"icons": {
"128": "icon128.png",
"16": "icon16.png",
"32": "icon32.png",
"48": "icon48.png"
},
"manifest_version": 2,
"minimum_chrome_version": "20",
"name": "Simple test",
"permissions": [
"unlimitedStorage",
"http://*/",
"<all_urls>",
"tabs"
],
"version": "2.6"
}
by the way connection from content script to background working just fine !
Ok, it seems you are trying to synchronize asynchronous events, after simplification of your code i got it running with modifications and achieved your functional requirement of posting message to all tabs when a new tab is created.
Output:
I was able to see this message on all tabs
manifest.json
{
"name":"Sample communication from content to background",
"description":"This is a sample for Simulating communication from content to background",
"manifest_version":2,
"version":"2",
"background":{
"scripts":["background.js"]
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["myscript.js"],
"run_at":"document_start"
}
]
}
"background.js"
chrome.tabs.onCreated.addListener(function(tab) {
chrome.windows.getCurrent(function(win){
chrome.tabs.getAllInWindow(win.id, function(tabs){
for (i=0;i<tabs.length;i++){
console.log(tabs[i]);
chrome.tabs.sendMessage(tabs[i].id,{name: "content_tab_request"});
}
});
});
});
"myscript.js"
chrome.extension.onMessage.addListener(function(msg) {
console.log("Message Recieved "+ msg);
});
Also some chrome extentions may produce this error. i had this problem and the problem was Aside extention (for saving articles to Pocket).
the error was:
Port error: Could not establish connection. Receiving end does not exist. miscellaneous_bindings:235
chromeHidden.Port.dispatchOnDisconnect

Resources