This repository has been archived by the owner on Mar 8, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 126
/
credentials.clj
48 lines (40 loc) · 2.17 KB
/
credentials.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
(ns cemerick.friend.credentials
(:import org.mindrot.jbcrypt.BCrypt))
(defn hash-bcrypt
"Hashes a given plaintext password using bcrypt and an optional
:work-factor (defaults to 10 as of this writing). Should be used to hash
passwords included in stored user credentials that are to be later verified
using `bcrypt-credential-fn`."
[password & {:keys [work-factor]}]
(BCrypt/hashpw password (if work-factor
(BCrypt/gensalt work-factor)
(BCrypt/gensalt))))
(defn bcrypt-verify
"Returns true if the plaintext [password] corresponds to [hash],
the result of previously hashing that password."
[password hash]
(BCrypt/checkpw password hash))
(defn bcrypt-credential-fn
"A bcrypt credentials function intended to be used with `cemerick.friend/authenticate`
or individual authentication workflows. You must supply a function of one argument
that will look up stored user credentials given a username/id. e.g.:
(authenticate {:credential-fn (partial bcrypt-credential-fn load-user-record)
:other :config ...}
ring-handler-to-be-secured)
The credentials map returned by the provided function will only be returned if
the provided (cleartext, user-supplied) password matches the hashed
password in the credentials map.
The password in the credentials map will be looked up using a :password
key by default; if the credentials-loading function will return a credentials
map that stores the hashed password under a different key, it must specify
that alternative key via a :cemerick.friend.credentials/password-key slot
in the map's metadata. So, if a credentials map looks like:
{:username \"joe\" :app.foo/passphrase \"bcrypt hash\"}
...then the hash will be verified correctly as long as the credentials
map contains a [:cemerick.friend.credentials/password-key :app.foo/passphrase]
entry."
[load-credentials-fn {:keys [username password]}]
(when-let [creds (load-credentials-fn username)]
(let [password-key (or (-> creds meta ::password-key) :password)]
(when (bcrypt-verify password (get creds password-key))
(dissoc creds password-key)))))