JWT Authentication server using email, password, captcha and Google Authenticator
Main Features:
- Password strengthening using scrypt RFC7914
- Password authentication using SRP-6a RFC2945 RFC5054
- One time tokens using TOTP RFC4226 RFC6238
- Human detection using reCAPTCHA
- Authorized using JWT RFC7519
yarn
Generate a keypair:
openssl ecparam -genkey -name secp521r1 -noout -out ec512.prv.pem
openssl ec -in ec512.prv.pem -pubout > ec512.pub.pem
Run tests & lint:
yarn test & yarn lint
Start server:
yarn start
You can find a client-side library here: authentication-client
Column | Type | Description |
---|---|---|
uuid |
text | UuidV4 |
email |
text | |
newEmail |
text | New unconfirmed email |
emailToken |
text | Email confirmation token |
created |
timestamp | Creation time |
updated |
timestamp | Last update time |
lastUsed |
timestamp | Last usage time) |
kdfSalt |
blob | Key derivation function salt |
srpSalt |
blob | SRP salt |
srpVerifier |
blob | SRP verifier |
totpSecret |
boob | Time bases one time passsword secret (2FA) |
N |
16384 |
r |
8 |
p |
1 |
dkLen |
32 |
The result taken in raw binary
form. 256 bit random salt.
4096-bit Group parameters (RFC5054 §A.5). 256 bit random salts and nonces.
Note: Captcha prevents this from automated detecting user existence
- User: generates random 32 byte
kdfSalt
- User: generates random 32 byte
srpSalt
- User:
key = scrypt(password, kdfSalt)
- User:
verifier = SRP6A_verifier(email, key, srpSalt)
- User calls
/api/signup
with:email
kdfSalt
srpSalt
verifier
captcha
- Server validates recaptcha
- Server generates
totpSecret
- Server creates new user with submitted data
- Server returns
totpSecret
- User calls
/api/login-data
with:email
- Server responds with:
kdfSalt
srpSalt
serverPublicKey
- encrypted and authenticated:
serverPrivateKey
- User calls
/api/login
with:clientProof
clientPublicKey
email
timeBasedOneTimeToken
- encrypted and authenticated:
serverPrivateKey
- Server verifies all the data and checks:
- the client proof
- integrity of encrypted part
- 2FA token
- Server issues the JSON Web Token
- Server returns:
token
serverProof
- Client verifies server proof
-
Because they often have low entropy (like the codes on a suitcase, you can try all options in a few days).
-
Because people use the same password in many places, so even if your site is not important—the same password may access the users bank account.
CA's are unreliable, TLS is too complex/buggy.
- http://heartbleed.com/
- https://en.wikipedia.org/wiki/Cloudbleed
- https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/eUAKwjihhBs
Does not protect against password brute forcing. An attacker who has the salt and hash can rapidly try combinations.
It's a lot better, but an attacker that has the salt and hash can still try passwords without being detected. Just much more slowly.
SRP protects against eavesdroppers, nothing send over the wire will help an attacker.
But now the server stores something that is roughly similar to a salted hash: if an attacker obtains the user database, (s)he can quickly do an brute force.
By using both we make it impossible to attack the password when the TLS leaks and very hard when the user database is leaked.
It is in the clients interest to protect itself.