Skip to content

Commit c9b568d

Browse files
committed
Allow special placeholders in key/value pairs
1 parent 68f35ad commit c9b568d

File tree

5 files changed

+71
-41
lines changed

5 files changed

+71
-41
lines changed

CHANGELOG.adoc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
= Changelog
22

3+
== v0.5.0
4+
5+
*Changes*
6+
7+
* Migrate from distutils to setuptools.
8+
* Rename nativePass script to chrome_pass
9+
10+
*Improvements*
11+
12+
* Allow special placeholders in key/value pairs.
13+
314
== v0.4.0
415

516
*Improvements*

DEPLOY.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@
33
## Chrome Extension
44

55
1. Create extension zip `zip -r extension.zip extension`.
6-
2. Go to [Chrome Developer Dashboard](https:
7-
//chrome.google.com/webstore/devconsole).
6+
2. Go to [Chrome Developer Dashboard](https://chrome.google.com/webstore/devconsole).
87
3. Login with developer account (hxxxx.sxxxx@gmail.com).
98
4. Go to the extension details -> build -> package -> Upload new package.
109
5. After uploading the extension.zip file edit the store listing description.
1110
6. Press `submit for review` to publish.
1211

1312
## Native App
1413

15-
1. pip3 install --user twine
16-
2. Configure pypi API token in ~/.pypirc file.
14+
1. Configure pypi API token in ~/.pypirc file.
1715
https://pypi.org/help/#apitoken
18-
3. Update the version string below.
19-
4. Build package with `python3 setup.py sdist`
20-
5. Upload package with `twine upload dist/*`
16+
2. cd application
17+
3. pip3 install --user twine build setuptools
18+
4. Update the version string in the pyproject.toml file.
19+
5. Build package with `python3 -m build`
20+
6. Upload package with `twine upload dist/*`

README.md

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ symbolic link to work around this limitation.
5959

6060
This plugin assumes that the last two parts of each password path follows this structure:
6161

62-
[Service URL]/[Account]
62+
[Service URL]/[Username]
6363

6464
For example to keep some Gmail and Amazon accounts:
6565

@@ -103,21 +103,41 @@ logic to be able to fill all information in the login page.
103103
│   └── accountalias
104104

105105
1. The [Service URL] must be `signin.aws.amazon.com` that is the URL for login into
106-
the console.
106+
the console.
107107
2. For root accounts the [Account] can be the root account email used for login.
108108
3. For IAM accounts the [Account] can be anything that uniquely identifies the
109109
credentials. For example the account 12-digit ID, or the account alias, or a
110110
combination of the account 12-digit ID and the IAM username.
111-
4. For IAM accounts it is necessary to edit the password GPG file using `pass edit`
112-
and add two key/value pairs: `username=[IAM username]` and `account=[12 digit
113-
account id or alias]`. When filling AWS login forms, chrome-pass uses
114-
these key/value pairs to fill the username and account input fields.
111+
4. For IAM accounts edit the password GPG file using `pass edit ...` and add two
112+
key/value pairs:
113+
- `username=[IAM username]`
114+
- `account=[12 digit AWS account id or alias]`
115115

116116
### Custom input fields
117117

118-
Using the same feature for IAM accounts, chrome-pass looks for any key/value pairs
119-
in the pass gpg files and fills any input field with ID equal to the `key` with
120-
the corresponding `value`.
118+
The chrome-pass extension looks for any key/value pairs in the pass gpg files
119+
and fills any input field with ID equal to the `key` with the corresponding
120+
`value`.
121+
122+
In addition if the `value` is set to the following placeholder values they are
123+
replaced:
124+
125+
- `pass__user`: Replaced with the `[Username]` extracted from the last part of
126+
the pass path.
127+
- `pass__password`: Replaced with the decrypted pass password.
128+
- `otpauth`: Replaced with the pass-otp code if available.
129+
130+
This allows chrome-pass to work with some non-standard login forms like the
131+
[Apple Id](https://appleid.apple.com/sign-in) login form. This login page lacks
132+
a form element and relies in javascript to work. Fortunatelly the username and
133+
password input fields have well defined IDs that we can set in the chrome-pass
134+
file to let it work:
135+
136+
```
137+
# chrome-pass for Apple ID login from.
138+
account_name_text_field=pass__user
139+
password_text_field=pass__password
140+
```
121141

122142
## Install from source
123143

extension/content.js

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ function writeValueWithEvents(input, value) {
5151
// Fill MFA TOTP code
5252
function fillTOTP(code) {
5353

54+
if(!code) { return; }
55+
5456
if(document.baseURI.includes("zoom.us")) {
5557
var zoomInput = document.querySelector("[class=form-masked-pin]");
5658

@@ -111,10 +113,11 @@ function copyToClipboard(txt) {
111113

112114
function fillForm(creds) {
113115

114-
// Try filling TOTP code.
115-
if(creds["otpauth"]) {
116-
fillTOTP(creds["otpauth"]);
117-
}
116+
const password = creds["pass__password"];
117+
const username = creds["pass__user"];
118+
const totp = creds["otpauth"];
119+
120+
fillTOTP(totp);
118121

119122
// AWS signin forms has two text inputs for username and account. Here we
120123
// specifically fill username.
@@ -132,43 +135,39 @@ function fillForm(creds) {
132135
writeValueWithEvents(input, creds["account"]);
133136
} else {
134137
// If placeholder is not empty, the form expects a root user email.
135-
writeValueWithEvents(input, creds["pass__user"]);
138+
writeValueWithEvents(input, username);
136139
}
137140
}
138141

139142
var userInput = document.querySelector("input[id=username]");
140143

141144
if(userInput) {
142-
writeValueWithEvents(userInput, creds["pass__user"]);
145+
writeValueWithEvents(userInput, username);
143146
}
144147

145148
var passInput = document.querySelector("input[type=password]");
146149

147150
if(passInput) {
148-
writeValueWithEvents(passInput, creds["pass__password"]);
149-
}
150-
151-
} else if(document.baseURI.includes("idmsa.apple.com")) {
152-
153-
var userInput = document.querySelector("#account_name_text_field");
154-
155-
if(userInput) {
156-
writeValueWithEvents(userInput, creds["pass__user"]);
151+
writeValueWithEvents(passInput, password);
157152
}
153+
} else {
154+
fillDefaultForm(username, password);
155+
}
158156

159-
var passwordInput = document.querySelector("input[type=password]");
157+
for(const [id, content] of Object.entries(creds)) {
160158

161-
if(passwordInput) {
162-
writeValueWithEvents(passwordInput, creds["pass__password"]);
163-
focus(passwordInput);
159+
// Skip special keys.
160+
if(["pass__password", "pass__user", "otpauth"].includes(id)) {
161+
continue;
164162
}
165-
} else {
166-
fillDefaultForm(creds["pass__user"], creds["pass__password"])
167-
}
168163

164+
var input = document.querySelector("input[id=" + id + "]");
165+
var value = content;
169166

170-
for(const [key, value] of Object.entries(creds)) {
171-
var input = document.querySelector("input[name=" + key + "]");
167+
// Replace special values.
168+
if(content == "pass__user") { value = username; }
169+
if(content == "pass__password") { value = password; }
170+
if(content == "otpauth") { value = totp; }
172171

173172
if(input != null) {
174173
writeValueWithEvents(input, value);

extension/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "chrome-pass (ZX2C4)",
4-
"version": "0.4.0",
4+
"version": "0.5.0",
55
"description": "Chrome plugin for *pass* the standard unix password manager.",
66
"minimum_chrome_version": "107.0",
77
"author": "Horacio Sanson",

0 commit comments

Comments
 (0)