This library implements HTTP Digest Authentication as per RFC2617.
Unlike Basic Authentication, digest authentication is based on
challenge-reponse and therefore does not need to send the password over
the (insecure) connection. In addition, it provides a count mechanism
that ensure that old credentials cannot be reused, which prevents
attackers from using old credentials with a new request. Digest
authentication have the following advantages and disadvantages:
- Advantages
- Authentication without exchanging the password
- No re-use of authentication data
- Disadvantages
- An extra round trip is needed for the first authentication
- Server-side storage of the password is the MD5 hash of the
user, realm and password. As MD5 hashes are quick to
compute, one needs strong passwords. This fixed algorithm
also allows for rainbow table attacks, although their
value is limited because you need to precompute the rainbow
table for every server (realm) and user.
- The connection is sensitive to man-in-the-middle attack,
where the attacker can both change the request and response.
- Both client and server need to keep an administration of
issued nonce values and associated nonce count values.
And, of course, the connection itself remains insecure. Digest based
authentication is a viable alternative if HTTPS is not a good option and
security of the data itself is not an issue.
This library acts as plugin for library(http/http_dispatch), where the
registered handler (http_handler/3) can be given the option below to
initiate digest authentication.
authentication(digest(PasswdFile, Realm))
Above, PasswdFile is a file containing lines of the from below, where
PasswordHash is computed using http_digest_password_hash/4. See also
library(http/http_authenticate), http_read_passwd_file/2 and
http_write_passwd_file/2.
User ":" PasswordHash (":" Extra)*
This library also hooks into library(http/http_open) if the option
authorization(digest(User, Password))
is given.
- See also
- - https://tools.ietf.org/html/rfc2617
- register_nonce(+Nonce, +Created) is det[private]
- Register a nonce created by the server. We need to do so to
ensure the client uses our nonce and that the connection should
not considered timed out.
- nonce_ok(+Nonce, +NC, -Stale) is semidet[private]
- True if Nonce at nonce-count NC is acceptable. That means the
nonce has not timed out and we have not seen the same sequence
number before. Note that requests may be concurrent and
therefore NC values may not come in order.
- gc_nonce[private]
- Garbage collect server nonce.
- private_key(-PrivateKey) is det[private]
- Return our private key.
- our_nonce(+Nonce, -Stamp:string) is semidet[private]
- True if we created Nonce at time Stamp.
- Arguments:
-
Stamp | - is the stamp as created by nonce//1: a time
stamp*1000+sequence number. |
- http_digest_challenge(+Realm, +Options)//
- Generate the content for a 401
WWW-Authenticate: Digest
header field.
- nonce(+Options)[private]
- Compute the server nonce value. Note that we should never
generate the same nonce twice for the same client. The client
may issue multiple requests without an authorization header
for resources appearing on a page. As long as we return distinct
nonce values, this is ok. If we do not, the server will reuse NC
counters on the same nonce, which will break the authentication.
- http_digest_authenticate(+Request, -User, -UserFields, +Options)[private]
- Validate the client reponse from the Request header. On success,
User is the validated user and UserFields are additional fields
from the password file. Options include:
- passwd_file(+File)
- Validate passwords agains the given password file. The
file is read using http_current_user/3 from
library(http/http_authenticate).
- stale(-Stale)
- The request may succeed on a timed-out server nonce. In
that case, Stale is unified with
true
.
- parse_digest_request(-Fields)//[private]
- Parse a digest request into a list of Name(Value) terms.
- parse_digest_reponse(-ResponseValues)//[private]
- http_parse_digest_challenge(+Challenge, -Fields) is det
- Parse the value of an HTTP
WWW-Authenticate
header into
a list of Name(Value) terms.
- http_digest_response(+Challenge, +User, +Password, -Reply, +Options)
- Formulate a reply to a digest authentication request. Options:
- path(+Path)
- The request URI send along with the authentication. Defaults
to
/
- method(+Method)
- The HTTP method. Defaults to
'GET'
- nc(+Integer)
- The nonce-count as an integer. This is formatted as an
8 hex-digit string.
- Arguments:
-
Challenge | - is a list Name(Value), normally from
http_parse_digest_challenge/2. Must contain
realm and nonce . Optionally contains
opaque . |
User | - is the user we want to authenticated |
Password | - is the user's password |
Options | - provides additional options |
- http_digest_password_hash(+User, +Realm, +Password, -Hash) is det
- Compute the password hash for the HTTP password file. Note that
the HTTP digest mechanism does allow us to use a seeded expensive
arbitrary hash function. Instead, the hash is defined as the MD5
of the following components:
<user>:<realm>:<password>.
The inexpensive MD5 algorithm makes the hash sensitive to brute
force attacks while the lack of seeding make the hashes sensitive
for rainbow table attacks, although the value is somewhat limited
because the realm and user are part of the hash.
- http:authenticate(+Digest, +Request, -Fields)[multifile]
- Plugin for
library(http_dispatch)
to perform basic HTTP
authentication. Note that we keep the authentication details
cached to avoid a `nonce-replay' error in the case that the
application tries to verify multiple times.
This predicate throws http_reply(authorise(digest(Digest)))
- Arguments:
-
Digest | - is a term digest(File, Realm, Options) |
Request | - is the HTTP request |
Fields | - describes the authenticated user with the option
user(User) and with the option user_details(Fields) if
the password file contains additional fields after the
user and password. |
- http:authenticate_client(+URL, +Action) is semidet[multifile]
- This hooks is called by http_open/3 with the following Action
value:
- send_auth_header(+AuthData, +Out, +Options)
- Called when sending the initial request. AuthData contains
the value for the http_open/3 option
authorization(AuthData)
and Out is a stream on which to write additional HTTP headers.
- auth_reponse(+Headers, +OptionsIn, -Options)
- Called if the server replies with a 401 code, challenging the
client. Our implementation adds a
request_header(authorization=Digest)
header to Options, causing
http_open/3 to retry the request with the additional option.
- digest_credentials(+Authority, +Path, -Nonce, -Fields) is semidet[private]
- True if we have digest credentials for Authority on Path with the
server nonce Nonce and additional Fields.
- keep_digest_credentials(+URL, +Fields)[private]
- Keep the digest credentials for subsequent connections.