Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
jwt-couchdb
Advanced tools
JWT endpoint to authenticate users and create JSON Web Tokens out of the CouchDB's session API
JWT endpoint to authenticate users and create JSON Web Tokens out of the CouchDB's session API.
Install it:
npm i -g jwt-couchdb
Run it:
COUCH=/path/to/config.json jwt-couchdb
It will open up a server on http://localhost:5985
that accepts POST requests to create JWT
tokens out of a valid CouchDB's authenticated user.
In order to get a token we need valid credentials. Both basic HTTP authentication and a JWT token are valid choices. Practically, both approaches are the same because they both give you a new token. Semantically they are different though, as using HTTP authentication means that you're logging in, while using an existing JWT token means you want to renew it.
The config file is in JSON format, here's an example of all the options you can set:
{
"endpoint": "http://127.0.0.1:5984",
"options": {
"algorithms": ["HS256"],
"expiresIn": "30s"
},
"secret": "supersecret",
"port": 3000
}
At a minimum, you need to set the secret
. This value is the same that you used on
couch_jwt_auth
on your CouchDB server's configuration.
In order for CouchDB to accept JWT tokens, you need to have an authentication handler on CouchDB's
land. Your best bet is to use couch_jwt_auth
.
Until merged, I suggest you use UXtemple's
fork as it supports token
blacklisting which can come in very handy if a token goes missing in the wild and a possible
attacker gains access to it.
### Basic HTTP auth
You need to send a POST
with an Authorization
header that looks like
Basic BASE64_USERNAME_COLON_PASSWORD
.
curl -vX POST -H "Authorization: Basic dGVzdDpwYXNz" http://127.0.0.1:5985
BASE64_USERNAME_COLON_PASSWORD
is a base64 encoded version of username:password
. The example
above encodes test:pass
into dGVzdDpwYXNz
.
How to base64 that value?
btoa('test:pass')
,require('btoa')('test:pass')
, andecho -n 'test:pass' | openssl base64
.Authenticating with a token isn't that different at all. You need to send a POST
with an
Authorization
header that looks like Bearer JWT_TOKEN
.
curl -vX POST -H "Authorization: Bearer
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiU29tZSBVc2VyIiwicm9sZXMiOltdfQ.v4QRSYnAOen_NMBzlMER_Jrkep0xEz2kL09KscALC_c" http://127.0.0.1:5985
Now, those examples were done with curl
and despite us loving curl
we don't use it (at least
directly) from the web or node.
// login for the first time and get a token
fetch('http://127.0.0.1:5985', {
method: 'POST',
headers: {
// remember we need to use `btoa` to base64 our user and password credentials
Authorization: `Basic ${btoa('user:password')}`
}
}).then(res => res.json()).then(token => {
// use token to authenticate somewhere else like:
fetch('https://auth-only-stuff.com/resource', {
headers: {
Authorization: `Bearer ${token}`
}
});
// since you'll probably want to use the token across requests, it might be a good idea to store
// it somewhere you can access later, like a variable in a closure that your fetch has access to:
var myToken = token;
// in sessionStorage to persist across page refreshes
sessionStorage.setItem('token', token);
// or in localStorage to use it when the user closes and opens the browser
localStorage.setItem('token', token);
});
A token may expire. How do you know if it does? It will hold an exp
claim in its payload
.
If it does it's probably a good idea to have a mechanism to renew it before it expires so that our
users is always logged in throughout their use of our app.
That's when token renewing comes in handy. The good thing about this library is that creating a token out of a user and password is almost the same as renewing that token you previously got.
The only difference from the example above is in the Authorization
header, instead of using
the keyword Basic
we use Bearer
which tells the server which auth mechanism we want to use.
E.g.:
the type of authentication
var token = `eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiU29tZSBVc2VyIiwicm9sZXMiOltdfQ.v4QRSYnAOen_NMBzlMER_Jrkep0xEz2kL09KscALC_c`;
// renew token
fetch('http://127.0.0.1:5985', {
method: 'POST',
headers: {
Authorization: `Basic ${token}`
}
}).then(res => res.json()).then(newToken => {
// do something with the new token :)
});
Sometimes (particularly when renewing a token) it might come in handy to get the list of roles from
the _users
database in CouchDB again. To do so, query the service with refresh-roles
at the end
like: http://127.0.0.1:5985/refresh-roles
.
See this as that's couch_jwt_auth's realm.
Sending authentication credentials over an unencrypted connection is a very bad practice. Plus, now that Let's Encrypt has been giving away free SSL certs for a while, securing your endpoints isn't an excuse anymore.
If you plan on exposing this endpoint directly to the internet, you may want to grab the handler and put together your own server that deals with HTTPS. Because our setups most times have multiple services running on SSL, we're generally putting this behind nginx to proxy requests to the service. Here's an nginx config file that may come in handy.
server {
listen 80;
server_name my-login.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name my-login.com;
root /usr/share/nginx/html;
ssl on;
ssl_certificate /etc/letsencrypt/live/my-login.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/my-login.com/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_session_cache shared:SSL:1m;
location / {
proxy_pass http://localhost:5985;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Ssl on;
}
}
License MIT.
with <3 by UXtemple.
FAQs
JWT endpoint to authenticate users and create JSON Web Tokens out of the CouchDB's session API
We found that jwt-couchdb demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.