Sha256: 443ad42269ed8531660f00a4be42c84bc09cdbf2038495950709ff5589e7fb83

Contents?: true

Size: 1.48 KB

Versions: 3

Compression:

Stored size: 1.48 KB

Contents

require 'json/jwt'
require 'rack/prx_auth/certificate'
require 'rack/prx_auth/token_data'
require 'prx_auth'

module Rack
  class PrxAuth
    INVALID_TOKEN = [
      401, {'Content-Type' => 'application/json'},
      [{status: 401, error: 'Invalid JSON Web Token'}.to_json]
    ]

    DEFAULT_ISS = 'id.prx.org'

    attr_reader :issuer

    def initialize(app, options = {})
      @app = app
      @certificate = Certificate.new(options[:cert_location])
      @issuer = options[:issuer] || DEFAULT_ISS
    end

    def call(env)
      return @app.call(env) unless env['HTTP_AUTHORIZATION']

      token = env['HTTP_AUTHORIZATION'].split[1]
      claims = decode_token(token)

      return @app.call(env) unless should_validate_token?(claims)

      if valid?(claims, token)
        env['prx.auth'] = TokenData.new(claims)
        @app.call(env)
      else
        INVALID_TOKEN
      end
    end

    private

    def valid?(claims, token)
      !expired?(claims) && @certificate.valid?(token)
    end

    def decode_token(token)
      return {} if token.nil?

      begin
        JSON::JWT.decode(token, :skip_verification)
      rescue JSON::JWT::InvalidFormat
        {}
      end
    end

    def expired?(claims)
      now = Time.now.to_i - 30 # 30 second clock jitter allowance
      if claims['iat'] <= claims['exp']
        now > claims['exp']
      else
        now > (claims['iat'] + claims['exp'])
      end
    end

    def should_validate_token?(claims)
      claims['iss'] == @issuer
    end
  end
end

Version data entries

3 entries across 3 versions & 1 rubygems

Version Path
prx_auth-1.5.0 lib/rack/prx_auth.rb
prx_auth-1.4.1 lib/rack/prx_auth.rb
prx_auth-1.4.0 lib/rack/prx_auth.rb