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
Public Class Methods
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
# 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
# File lib/rack/auth/digest/md5.rb, line 35 def passwords_hashed? !!@passwords_hashed end
Private Instance Methods
# File lib/rack/auth/digest/md5.rb, line 114 def A1(auth, password) "#{auth.username}:#{auth.realm}:#{password}" end
# File lib/rack/auth/digest/md5.rb, line 118 def A2(auth) "#{auth.method}:#{auth.uri}" end
# File lib/rack/auth/digest/md5.rb, line 110 def KD(secret, data) H "#{secret}:#{data}" end
# File lib/rack/auth/digest/md5.rb, line 79 def challenge(hash = {}) "Digest #{params(hash)}" end
# 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
# File lib/rack/auth/digest/md5.rb, line 104 def md5(data) ::Digest::MD5.hexdigest(data) end
# 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
# File lib/rack/auth/digest/md5.rb, line 83 def valid?(auth) valid_opaque?(auth) && valid_nonce?(auth) && valid_digest?(auth) end
# 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
# File lib/rack/auth/digest/md5.rb, line 95 def valid_nonce?(auth) auth.nonce.valid? end
# File lib/rack/auth/digest/md5.rb, line 91 def valid_opaque?(auth) H(opaque) == auth.opaque end
# File lib/rack/auth/digest/md5.rb, line 87 def valid_qop?(auth) QOP == auth.qop end