lib/rack/auth/digest/md5.rb in rack-2.2.10 vs lib/rack/auth/digest/md5.rb in rack-3.0.0.beta1
- old
+ new
@@ -1,131 +2 @@
-# frozen_string_literal: true
-
-require_relative '../abstract/handler'
-require_relative 'request'
-require_relative 'params'
-require_relative 'nonce'
-require 'digest/md5'
-
-module Rack
- module Auth
- module Digest
- # 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.
- #
- class MD5 < AbstractHandler
-
- attr_accessor :opaque
-
- attr_writer :passwords_hashed
-
- 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
-
- def passwords_hashed?
- !!@passwords_hashed
- end
-
- 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
-
-
- private
-
- QOP = 'auth'
-
- 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
-
- def challenge(hash = {})
- "Digest #{params(hash)}"
- end
-
- def valid?(auth)
- valid_opaque?(auth) && valid_nonce?(auth) && valid_digest?(auth)
- end
-
- def valid_qop?(auth)
- QOP == auth.qop
- end
-
- def valid_opaque?(auth)
- H(opaque) == auth.opaque
- end
-
- def valid_nonce?(auth)
- auth.nonce.valid?
- end
-
- def valid_digest?(auth)
- pw = @authenticator.call(auth.username)
- pw && Rack::Utils.secure_compare(digest(auth, pw), auth.response)
- end
-
- def md5(data)
- ::Digest::MD5.hexdigest(data)
- end
-
- alias :H :md5
-
- def KD(secret, data)
- H "#{secret}:#{data}"
- end
-
- def A1(auth, password)
- "#{auth.username}:#{auth.realm}:#{password}"
- end
-
- def A2(auth)
- "#{auth.method}:#{auth.uri}"
- end
-
- 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
-
- end
- end
- end
-end
+require_relative '../digest'