123456789_123456789_123456789_123456789_123456789_

Class: WEBrick::HTTPAuth::DigestAuth

Relationships & Source Files
Namespace Children
Classes:
Extension / Inclusion / Inheritance Descendants
Subclasses:
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
Inherits: Object
Defined in: lib/webrick/httpauth/digestauth.rb

Overview

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 = WEBrick::HTTPAuth::Htdigest.new 'my_password_file'
htdigest.set_passwd config[:Realm], 'username', 'password'
htdigest.flush

config[:UserDB] = htdigest

digest_auth = WEBrick::HTTPAuth::DigestAuth.new 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.

Constant Summary

Authenticator - Included

AuthScheme

Class Method Summary

Instance Attribute Summary

  • #algorithm readonly

    Digest authentication algorithm.

  • #qop readonly

    Quality of protection.

Authenticator - Included

#logger

The logger for this authenticator.

#realm

The realm this authenticator covers.

#userdb

The user database for this authenticator.

Instance Method Summary

Constructor Details

.new(config, default = Config::DigestAuth) ⇒ DigestAuth

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 Config::DigestAuth for default configuration entries

You must supply the following configuration entries:

:Realm

The name of the realm being protected.

:UserDB

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

[ GitHub ]

  
# File 'lib/webrick/httpauth/digestauth.rb', line 87

def initialize(config, default=Config::DigestAuth)
  check_init(config)
  @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
  else
    msg = format('Algorithm "%s" is not supported.', @algorithm)
    raise ArgumentError.new(msg)
  end

  @instance_key = hexdigest(self.__id__, Time.now.to_i, Process.pid)
  @opaques = {}
  @last_nonce_expire = Time.now
  @mutex = Thread::Mutex.new
end

Class Method Details

.make_passwd(realm, user, pass)

Used by UserDB to create a digest password entry

[ GitHub ]

  
# File 'lib/webrick/httpauth/digestauth.rb', line 69

def self.make_passwd(realm, user, pass)
  pass ||= ""
  Digest::MD5::hexdigest([user, realm, pass].join(":"))
end

Instance Attribute Details

#algorithm (readonly)

Digest authentication algorithm

[ GitHub ]

  
# File 'lib/webrick/httpauth/digestauth.rb', line 59

attr_reader :algorithm

#qop (readonly)

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

[ GitHub ]

  
# File 'lib/webrick/httpauth/digestauth.rb', line 64

attr_reader :qop

Instance Method Details

#authenticate(req, res)

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

[ GitHub ]

  
# File 'lib/webrick/httpauth/digestauth.rb', line 121

def authenticate(req, res)
  unless result = @mutex.synchronize{ _authenticate(req, res) }
    challenge(req, res)
  end
  if result == :nonce_is_stale
    challenge(req, res, true)
  end
  return true
end

#challenge(req, res, stale = false)

Returns a challenge response which asks for authentication information

Raises:

  • (@auth_exception)
[ GitHub ]

  
# File 'lib/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
  end

  param = Hash.new
  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} " + param.map{|k,v| "#{k}=#{v}" }.join(", ")
  info("%s: %s", @response_field, res[@response_field]) if $DEBUG
  raise @auth_exception
end