Storing user login/password input in a Greasemonkey script on install

I'm doing a Greasemonkey script that communicates with the Redmine ticket manager through the REST API. As the user needs to login to get the data from Redmine, I need a way to ask the user for his credentials at script installation and save them to the script.

Can this be achieved without asking the user to edit the values directly in the script itself?

EDIT:
Since there is already an answer to this question I will validate the answer given just below as it is a very good framework.

Answers:

Answer

Here is a framework for getting and storing login credentials. The script prompts for the information on the very first run and stores it, encrypted, using GM_setValue().

It also adds two items to the Greasemonkey context menu to allow changing the username or password.

// ==UserScript==
// @name     _Autologin, sensitive info framework
// @include  http://YOUR_SERVER.COM/YOUR_PATH/*
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require  http://crypto.stanford.edu/sjcl/sjcl.js
// @grant    GM_getValue
// @grant    GM_setValue
// @grant    GM_registerMenuCommand
// ==/UserScript==

var encKey  = GM_getValue ("encKey",  "");
var usr     = GM_getValue ("lognUsr", "");
var pword   = GM_getValue ("lognPwd", "");

if ( ! encKey) {
    encKey  = prompt (
        'Script key not set for ' + location.hostname + '. Please enter a random string:',
        ''
    );
    GM_setValue ("encKey", encKey);

    usr     = pword = "";   // New key makes prev stored values (if any) unable to decode.
}
usr         = decodeOrPrompt (usr,   "U-name", "lognUsr");
pword       = decodeOrPrompt (pword, "P-word", "lognPwd");


function decodeOrPrompt (targVar, userPrompt, setValVarName) {
    if (targVar) {
        targVar     = unStoreAndDecrypt (targVar);
    }
    else {
        targVar     = prompt (
            userPrompt + ' not set for ' + location.hostname + '. Please enter it now:',
            ''
        );
        GM_setValue (setValVarName, encryptAndStore (targVar) );
    }
    return targVar;
}

function encryptAndStore (clearText) {
    return  JSON.stringify (sjcl.encrypt (encKey, clearText) );
}

function unStoreAndDecrypt (jsonObj) {
    return  sjcl.decrypt (encKey, JSON.parse (jsonObj) );
}

//-- Add menu commands that will allow U and P to be changed.
GM_registerMenuCommand ("Change Username", changeUsername);
GM_registerMenuCommand ("Change Password", changePassword);

function changeUsername () {
    promptAndChangeStoredValue (usr,   "U-name", "lognUsr");
}

function changePassword () {
    promptAndChangeStoredValue (pword, "P-word", "lognPwd");
}

function promptAndChangeStoredValue (targVar, userPrompt, setValVarName) {
    targVar     = prompt (
        'Change ' + userPrompt + ' for ' + location.hostname + ':',
        targVar
    );
    GM_setValue (setValVarName, encryptAndStore (targVar) );
}

// ADD YOUR CODE TO SET THE USERNAME AND PASSWORD ON THE LOGIN PAGE, HERE.

Important:

  1. Logging in with a userscript always carries risk.
  2. This framework greatly reduces that risk, but the storage mechanisms available to Greasemonkey and Tampermonkey are not secure and browser vendors CYA against storing confidential information. If a bad guy gets both your userscript and your browser data, then he can reverse engineer your password. Of course if he has that, he's most likely pwned one of your machines anyway.
  3. The smart thing to do is to use a password manager like LastPass, KeePass, etc.
  4. The absolute worst thing to do, is to store credentials in a userscript itself. Even a guest can see them then and you will be "hacked", guaranteed.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.