# class Rack::Auth::Digest::MD5

`Rack::Auth::Digest::MD5` implements the `MD5` algorithm version of HTTP `Digest` Authentication, as per RFC 2617.

Initialize with the [Rack] application that you want protecting, and a block that looks up a plaintext password for a given username.

`opaque` needs to be set to a constant base64/hexadecimal string.

### Constants

QOP

### Attributes

opaque[RW]
passwords_hashed[W]

### Public Class Methods

new(app, realm = nil, opaque = nil, &authenticator) click to toggle source
Calls superclass method `Rack::Auth::AbstractHandler::new`

    # File lib/rack/auth/digest/md5.rb, line 26
    def initialize(app, realm = nil, opaque = nil, &authenticator)
      @passwords_hashed = nil
      if opaque.nil? and realm.respond_to? :values_at
        realm, opaque, @passwords_hashed = realm.values_at :realm, :opaque, :passwords_hashed
      end
      super(app, realm, &authenticator)
      @opaque = opaque
    end

### Public Instance Methods

call(env) click to toggle source

    # File lib/rack/auth/digest/md5.rb, line 39
    def call(env)
      auth = Request.new(env)

      unless auth.provided?
        return unauthorized
      end

      if !auth.digest? || !auth.correct_uri? || !valid_qop?(auth)
        return bad_request
      end

      if valid?(auth)
        if auth.nonce.stale?
          return unauthorized(challenge(stale: true))
        else
          env['REMOTE_USER'] = auth.username

          return @app.call(env)
        end
      end

      unauthorized
    end

passwords_hashed?() click to toggle source

    # File lib/rack/auth/digest/md5.rb, line 35
    def passwords_hashed?
      !!@passwords_hashed
    end

### Private Instance Methods

A1(auth, password) click to toggle source

    # File lib/rack/auth/digest/md5.rb, line 114
    def A1(auth, password)
      "#{auth.username}:#{auth.realm}:#{password}"
    end

A2(auth) click to toggle source

    # File lib/rack/auth/digest/md5.rb, line 118
    def A2(auth)
      "#{auth.method}:#{auth.uri}"
    end

H(data)
Alias for: md5
KD(secret, data) click to toggle source

    # File lib/rack/auth/digest/md5.rb, line 110
    def KD(secret, data)
      H "#{secret}:#{data}"
    end

challenge(hash = {}) click to toggle source

    # File lib/rack/auth/digest/md5.rb, line 79
    def challenge(hash = {})
      "Digest #{params(hash)}"
    end

digest(auth, password) click to toggle source

    # File lib/rack/auth/digest/md5.rb, line 122
    def digest(auth, password)
      password_hash = passwords_hashed? ? password : H(A1(auth, password))

      KD password_hash, "#{auth.nonce}:#{auth.nc}:#{auth.cnonce}:#{QOP}:#{H A2(auth)}"
    end

md5(data) click to toggle source

    # File lib/rack/auth/digest/md5.rb, line 104
    def md5(data)
      ::Digest::MD5.hexdigest(data)
    end

Also aliased as: H
params(hash = {}) click to toggle source

    # File lib/rack/auth/digest/md5.rb, line 68
    def params(hash = {})
      Params.new do |params|
        params['realm'] = realm
        params['nonce'] = Nonce.new.to_s
        params['opaque'] = H(opaque)
        params['qop'] = QOP

        hash.each { |k, v| params[k] = v }
      end
    end

valid?(auth) click to toggle source

    # File lib/rack/auth/digest/md5.rb, line 83
    def valid?(auth)
      valid_opaque?(auth) && valid_nonce?(auth) && valid_digest?(auth)
    end

valid_digest?(auth) click to toggle source

    # File lib/rack/auth/digest/md5.rb, line 99
    def valid_digest?(auth)
      pw = @authenticator.call(auth.username)
      pw && Rack::Utils.secure_compare(digest(auth, pw), auth.response)
    end

valid_nonce?(auth) click to toggle source

    # File lib/rack/auth/digest/md5.rb, line 95
    def valid_nonce?(auth)
      auth.nonce.valid?
    end

valid_opaque?(auth) click to toggle source

    # File lib/rack/auth/digest/md5.rb, line 91
    def valid_opaque?(auth)
      H(opaque) == auth.opaque
    end

valid_qop?(auth) click to toggle source

    # File lib/rack/auth/digest/md5.rb, line 87
    def valid_qop?(auth)
      QOP == auth.qop
    end