I have this problem ... and I've been trying to get a username and password pair passed to background.js of my extension. The process goes as follows:
- A Credentials Server (CS) is started up with encrypted credential tokens
- Selenium opens the browser with custom extension
- The extension is triggered onAuthRequired
- The Native Messaging Host (NMH) starts then receives a 'ready' message
- The NMH uses a simple protocol to request tokens from the CS
- The NMH decrypts the tokens
- The NMH passes the credentials to background.js
- background.js returns the credentials to chrome
- Authentication magic happens on the remote server
I have solved everything right up to 6 ... maybe 7. The issue is that I am not able to actually capture what the NMH is sending. It seems to be that either the credentials are not formatted correctly, thus they're being rejected or there's a problem with how the JavaScript side is put together and so it's just a case of broken code. It's also possible that what I intend is not at all possible ... though I doubt that is the case.
I will provide as much code as I can ... and while I appreciate any help, I am happy to get a generic example which can be modified in my own time.
Got a better approach? I'm all ears! Happy to create a new question to address other ideas.
EDIT 1.0: I should add that, when run, the alert at line 9 does popup. When modified to read:
window.alert(String(response));
I get [object Object]
EDIT 2.0:
I changed window.alert(String(response)); to window.alert(JSON.stringify(response)); and it produced the expected outcome: {"username":"\"some_user\"","password":"\"1Password\"}
I expect this would translate to '{username:"some_user",password:"1Password"}'
There appears to be a problem passing the value of response to creds since the NMH fails to run at all once I try to access the username/password property of creds outside the callback. This is probably a scope issue ...
Edit 3.0: I found the issue - it's a synchronicity problem. I've found many, many questions on this - I'll answer this when I've come up with a work around myself. Feel free to answer with a solution, should you have one.
Current background.js (not working)
chrome.webRequest.onAuthRequired.addListener(() => {
 var hostName = "aardvark_nm_host";
 var creds = null;
 chrome.runtime.sendNativeMessage(
   hostName,
   { text: "Ready" },
   function(response){
     window.alert("response");
     console.log(response);
     creds = JSON.parse(response);
   }
 );
 return {authCredentials: creds};
},
 {urls: ["<all_urls>"]},
 ['blocking']
);Current aardvark_nm_host.py (Probably working)
#!/usr/bin/env python
from locksmith import decrypt_token, KEYFILE
import socket
import struct
import sys
import json
PORT = 9999
ADDR = 'localhost'
ERRMSG = {"username":"ERROR", "password":"password"}
def report_string(string):
  def transceive(signal):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server = (ADDR, PORT)
    sock.connect(server)
    try:
      sock.sendall(signal)
    except Exception as e:
      print >>sys.stderr, e
      sock.close()
    try:
      sock.sendall(string)
      sock.close()
    except Exception as e:
      print >>sys.stderr, e
      sock.close()
  transceive('S')
def get_tokens():
  def recv_burst(sock):
    total_data = []
    while True:
      data = sock.recv(1024)
      if not data:
        break
      total_data.append(data)
    return ''.join(total_data)
  def transceive(signal):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server = (ADDR, PORT)
    sock.connect(server)
    try:
      sock.sendall(signal)
      message = recv_burst(sock)
    except Exception as e:
      report_string(e)
    finally:
      sock.close()
      
    return message
  try:
    username = transceive('U')
    username = decrypt_token(username)
    report_string(username)
  except Exception as e:
    report_string(str(e))
    username = "TOKEN_ERROR"
  try:
    password = transceive('P')
    password = decrypt_token(password)
    report_string(password)
  except Exception as e:
    report_string(str(e))
    password = "TOKEN_ERROR"
  return {"username":username, "password":password}
def read_message():
  text_length = sys.stdin.read(4)
  if len(text_length) == 0:
    sys.exit(0)
  text_length = struct.unpack('@I', text_length)[0]
  text = sys.stdin.read(text_length)
  return json.loads(text)
  
def encode_message(message):
  encoded_content = json.dumps(message)
  encoded_length = struct.pack('@I', len(encoded_content))
  return {'length': encoded_length, 'content': encoded_content}
  
def send_message(encoded_message):
  sys.stdout.write(encoded_message['length'])
  sys.stdout.write(encoded_message['content'])
  sys.stdout.flush()
def interpretation(message):
  return message["text"] == "Ready"
while True:
  received_message = read_message()
  report_string(received_message)
  if interpretation(received_message):
    creds = get_tokens()
    send_message(encode_message(creds))
    creds = None
  else:
    send_message(encode_message(ERRMSG))Current extension manifest.json
{
    "version": "1.0.0",
    "manifest_version": 2,
    "name": "authvark",
    "permissions": [
        "<all_urls>",
        "webRequest",
        "webRequestBlocking",
        "nativeMessaging"
    ],
    "background": {
        "scripts": ["background.js"],
        "persistent": false
    }
}native-messaging-hosts/manifest.json
{
  "name": "aardvark_nm_host",
  "description": "Intermediary Credential Host",
  "path": "/path/to/aardvark_nm_host.py",
  "type": "stdio",
  "allowed_origins": [
    "chrome-extension://.../"
  ]
} 
    