class Rack::Jwt::Auth::Authenticate

Constants

DECODE_OPTIONS

Public Class Methods

new(app, opts = {}) click to toggle source
# File lib/rack/jwt/auth/authenticate.rb, line 20
def initialize(app, opts = {})
  @app  = app
  @opts = opts

  raise 'Secret must be provided' if opts[:secret].nil?

  # @see https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
  # @see https://github.com/jwt/ruby-jwt/pull/184
  raise 'Algorithm must be provided for security reason' if opts[:algorithm].nil?

  @secret = opts[:secret]

  @authenticated_routes   = compile_paths(opts[:only])
  @unauthenticated_routes = compile_paths(opts[:except])
end

Public Instance Methods

call(env) click to toggle source
# File lib/rack/jwt/auth/authenticate.rb, line 36
def call(env)
  with_authorization(env) do |payload|
    env['rack.jwt.session'] = payload
    @app.call(env)
  end
end

Private Instance Methods

authenticated_route?(env) click to toggle source
# File lib/rack/jwt/auth/authenticate.rb, line 45
def authenticated_route?(env)
  if @authenticated_routes.length > 0
    @authenticated_routes.find { |route| route =~ env['PATH_INFO'] }
  else
    !@unauthenticated_routes.find { |route| route =~ env['PATH_INFO'] }
  end
end
compile(path) click to toggle source
# File lib/rack/jwt/auth/authenticate.rb, line 83
def compile(path)
  if path.respond_to? :to_str
    special_chars = %w{. + ( )}
    pattern =
      path.to_str.gsub(/((:\w+)|[\*#{special_chars.join}])/) do |match|
        case match
        when "*"
          "(.*?)"
        when *special_chars
          Regexp.escape(match)
        else
          "([^/?&#]+)"
        end
      end
    /^#{pattern}$/
  elsif path.respond_to? :match
    path
  else
    raise TypeError, path
  end
end
compile_paths(paths) click to toggle source
# File lib/rack/jwt/auth/authenticate.rb, line 75
def compile_paths(paths)
  return [] if paths.nil?

  paths.map do |path|
    compile(path)
  end
end
extract_decode_options(opts) click to toggle source
# File lib/rack/jwt/auth/authenticate.rb, line 53
def extract_decode_options(opts)
  opts.select { |k, _| DECODE_OPTIONS.include?(k) }
end
with_authorization(env) { |payload| ... } click to toggle source
# File lib/rack/jwt/auth/authenticate.rb, line 57
def with_authorization(env)
  if authenticated_route?(env)
    header  = env['HTTP_AUTHORIZATION']

    return [401, {}, [{message: 'Missing Authorization header'}.to_json]] if header.nil?

    scheme, token = header.split(" ")

    return [401, {}, [{message: 'Format is Authorization: Bearer [token]'}.to_json]] unless scheme.match(/^Bearer$/i) && !token.nil?

    payload = AuthToken.valid?(token, @secret, extract_decode_options(@opts))

    return [401, {}, [{message: 'Invalid Authorization'}.to_json]] unless payload
  end

  yield payload
end