Maintenance of Ruby 2.0.0 ended on February 24, 2016. Read more

In Files

  • webrick/httpauth/digestauth.rb


RFC 2617 Digest Access Authentication for WEBrick

Use this class to add digest authentication to a WEBrick servlet.

Here is an example of how to set up DigestAuth:

config = { :Realm => 'DigestAuth example realm' }

htdigest = 'my_password_file'
htdigest.set_passwd config[:Realm], 'username', 'password'

config[:UserDB] = htdigest

digest_auth = config

When using this as with a servlet be sure not to create a new DigestAuth object in the servlet’s initialize. By default WEBrick creates a new servlet instance for every request and the DigestAuth object must be used across requests.



Digest authentication algorithm


Quality of protection. RFC 2617 defines “auth” and “auth-int”

Public Class Methods

make_passwd(realm, user, pass) click to toggle source

Used by UserDB to create a digest password entry

               # File webrick/httpauth/digestauth.rb, line 68
def self.make_passwd(realm, user, pass)
  pass ||= ""
  Digest::MD5::hexdigest([user, realm, pass].join(":"))
new(config, default=Config::DigestAuth) click to toggle source

Creates a new DigestAuth instance. Be sure to use the same DigestAuth instance for multiple requests as it saves state between requests in order to perform authentication.

See WEBrick::Config::DigestAuth for default configuration entries

You must supply the following configuration entries:


The name of the realm being protected.


A database of usernames and passwords. A WEBrick::HTTPAuth::Htdigest instance should be used.

               # File webrick/httpauth/digestauth.rb, line 86
def initialize(config, default=Config::DigestAuth)
  @config                 = default.dup.update(config)
  @algorithm              = @config[:Algorithm]
  @domain                 = @config[:Domain]
  @qop                    = @config[:Qop]
  @use_opaque             = @config[:UseOpaque]
  @use_next_nonce         = @config[:UseNextNonce]
  @check_nc               = @config[:CheckNc]
  @use_auth_info_header   = @config[:UseAuthenticationInfoHeader]
  @nonce_expire_period    = @config[:NonceExpirePeriod]
  @nonce_expire_delta     = @config[:NonceExpireDelta]
  @internet_explorer_hack = @config[:InternetExplorerHack]

  case @algorithm
  when 'MD5','MD5-sess'
    @h = Digest::MD5
  when 'SHA1','SHA1-sess'  # it is a bonus feature :-)
    @h = Digest::SHA1
    msg = format('Algorithm "%s" is not supported.', @algorithm)

  @instance_key = hexdigest(self.__id__,,
  @opaques = {}
  @last_nonce_expire =
  @mutex =

Public Instance Methods

authenticate(req, res) click to toggle source

Authenticates a req and returns a 401 Unauthorized using res if the authentication was not correct.

               # File webrick/httpauth/digestauth.rb, line 120
def authenticate(req, res)
  unless result = @mutex.synchronize{ _authenticate(req, res) }
    challenge(req, res)
  if result == :nonce_is_stale
    challenge(req, res, true)
  return true
challenge(req, res, stale=false) click to toggle source

Returns a challenge response which asks for for authentication information

               # File webrick/httpauth/digestauth.rb, line 134
def challenge(req, res, stale=false)
  nonce = generate_next_nonce(req)
  if @use_opaque
    opaque = generate_opaque(req)
    @opaques[opaque].nonce = nonce

  param =
  param["realm"]  = HTTPUtils::quote(@realm)
  param["domain"] = HTTPUtils::quote(@domain.to_a.join(" ")) if @domain
  param["nonce"]  = HTTPUtils::quote(nonce)
  param["opaque"] = HTTPUtils::quote(opaque) if opaque
  param["stale"]  = stale.to_s
  param["algorithm"] = @algorithm
  param["qop"]    = HTTPUtils::quote(@qop.to_a.join(",")) if @qop

  res[@response_field] =
    "#{@auth_scheme} " +{|k,v| "#{k}=#{v}" }.join(", ")
  info("%s: %s", @response_field, res[@response_field]) if $DEBUG
  raise @auth_exception