Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
strategy:
fail-fast: false
matrix:
RUBY_VERSION: ["2.5", "2.6", "3.1"]
RUBY_VERSION: ["3.1", "3.4"]

steps:
- name: Check out code
Expand All @@ -30,8 +30,11 @@ jobs:
ruby-version: ${{ matrix.RUBY_VERSION }}
bundler-cache: true

- name: Lint
run: bundle exec rubocop

- name: Run Tests
run: bundle exec rake
run: bundle exec rspec

results:
if: ${{ always() }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ spec/reports
test/tmp
test/version_tmp
tmp
.rubocop-https*
2 changes: 2 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
inherit_from:
- https://raw.githubusercontent.com/aptible/dryer-lint/main/rspec_3_plus/.rubocop.base.yml
15 changes: 15 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM ruby:3.4

WORKDIR /app

COPY Gemfile /app/Gemfile
COPY fridge.gemspec /app/fridge.gemspec
COPY lib/ /app/lib

RUN bundle install

COPY spec/ /app/spec
COPY .rspec /app/.rspec
COPY Rakefile /app/Rakefile

CMD ["true"]
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

source 'https://rubygems.org'

# Specify your gem's dependencies in fridge.gemspec
Expand Down
2 changes: 2 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'bundler/gem_tasks'

require 'aptible/tasks'
Expand Down
6 changes: 6 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
services:
fridge:
build:
context: .
volumes:
- .:/app
17 changes: 12 additions & 5 deletions fridge.gemspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# encoding: utf-8
# frozen_string_literal: true

lib = File.expand_path('../lib', __FILE__)
lib = File.expand_path('lib', __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)

require 'English'
Expand All @@ -17,16 +17,23 @@ Gem::Specification.new do |spec|
spec.license = 'MIT'

spec.files = `git ls-files`.split($RS)
spec.test_files = spec.files.grep(%r{^spec/})
spec.require_paths = ['lib']
spec.required_ruby_version = '>= 3.0'

spec.add_dependency 'gem_config'
spec.add_dependency 'jwt', '~> 2.3.0'

spec.add_development_dependency 'aptible-tasks'
spec.add_development_dependency 'pry'
spec.add_development_dependency 'rails'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'rspec', '~> 3.0'
spec.add_development_dependency 'rspec'
spec.add_development_dependency 'rspec-rails'
spec.add_development_dependency 'rubocop'
spec.add_development_dependency 'rubocop-capybara'
spec.add_development_dependency 'rubocop-factory_bot'
spec.add_development_dependency 'rubocop-rails'
spec.add_development_dependency 'rubocop-rake'
spec.add_development_dependency 'rubocop-rspec'
spec.add_development_dependency 'rubocop-rspec_rails'
spec.metadata['rubygems_mfa_required'] = 'true'
end
15 changes: 15 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
init:
rm Gemfile.lock || true
docker compose build

test:
docker compose run fridge bundle exec rspec

lint:
docker compose run fridge bundle exec rubocop

pretty:
docker compose run fridge bundle exec rubocop -a

shell:
docker compose run fridge bash
6 changes: 3 additions & 3 deletions lib/fridge.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'gem_config'

require 'fridge/version'
Expand All @@ -8,17 +10,15 @@

require 'fridge/railtie' if defined?(Rails)

# Fridge provides JWT token validation for distributed resource servers.
module Fridge
include GemConfig::Base

with_configuration do
has :private_key, classes: [String]
has :public_key, classes: [String]

# rubocop:disable Style/PercentLiteralDelimiters
has :signing_algorithm, values: %w[RS512 RS256], default: 'RS512'
# rubocop:enable Style/PercentLiteralDelimiters

# A validator must raise an exception or return a false value for an
# invalid token
has :validator, classes: [Proc], default: ->(token) { token.valid? }
Expand Down
15 changes: 9 additions & 6 deletions lib/fridge/access_token.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# frozen_string_literal: true

require 'jwt'

module Fridge
# Represents a JWT-based access token with encoding and decoding support.
class AccessToken
attr_accessor :id, :issuer, :subject, :scope, :expires_at, :actor,
:jwt, :attributes
Expand All @@ -15,7 +18,7 @@ def initialize(jwt_or_options = nil)
else {}
end

[:id, :issuer, :subject, :scope, :expires_at, :actor].each do |key|
%i[id issuer subject scope expires_at actor].each do |key|
send "#{key}=", options.delete(key)
end
self.attributes = options
Expand All @@ -35,7 +38,7 @@ def serialize

def encode_and_sign
h = {}
[:id, :issuer, :subject, :scope, :expires_at, :actor].each do |key|
%i[id issuer subject scope expires_at actor].each do |key|
h[key] = send(key)
end
h.merge!(attributes)
Expand Down Expand Up @@ -63,7 +66,7 @@ def valid?
end

def expired?
expires_at.nil? || expires_at < Time.now
expires_at.nil? || expires_at < Time.zone.now
end

def private_key
Expand Down Expand Up @@ -107,7 +110,7 @@ def respond_to_missing?(method, include_private = false)
end

def validate_parameters!
[:subject, :expires_at].each do |attribute|
%i[subject expires_at].each do |attribute|
next if send(attribute)

raise SerializationError, "Missing attribute: #{attribute}"
Expand Down Expand Up @@ -159,12 +162,12 @@ def decode_from_jwt(hash)
scope: hash.delete('scope')
}.delete_if { |_, v| v.nil? }

hash.delete('exp').tap { |e| out[:expires_at] = Time.at(e) if e }
hash.delete('exp').tap { |e| out[:expires_at] = Time.zone.at(e) if e }
hash.delete('act').tap { |a| out[:actor] = decode_from_jwt(a) if a }

# Extra attributes
hash.delete_if { |_, v| v.nil? }
hash = Hash[hash.map { |k, v| [k.to_sym, v] }]
hash = hash.to_h { |k, v| [k.to_sym, v] }
out.merge!(hash)

out
Expand Down
2 changes: 2 additions & 0 deletions lib/fridge/expired_token.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module Fridge
class ExpiredToken < InvalidToken
end
Expand Down
2 changes: 2 additions & 0 deletions lib/fridge/invalid_token.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module Fridge
class InvalidToken < StandardError
end
Expand Down
15 changes: 9 additions & 6 deletions lib/fridge/rails_helpers.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# frozen_string_literal: true

module Fridge
# Rails controller helpers for bearer token and session cookie management.
module RailsHelpers
extend ActiveSupport::Concern

Expand All @@ -8,15 +11,15 @@ module RailsHelpers
end

def token_scope
current_token.scope if current_token
current_token&.scope
end

def token_subject
current_token.subject if current_token
current_token&.subject
end

def token_actor
current_token.actor if current_token
current_token&.actor
end

def current_token
Expand All @@ -29,15 +32,15 @@ def current_token

def bearer_token
header = request.env['HTTP_AUTHORIZATION']
header.gsub(/^Bearer /, '') unless header.nil?
header&.gsub(/^Bearer /, '')
end

def session_subject
session_token.subject if session_token
session_token&.subject
end

def session_actor
session_token.actor if session_token
session_token&.actor
end

def session_token
Expand Down
5 changes: 4 additions & 1 deletion lib/fridge/railtie.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# frozen_string_literal: true

require 'fridge/rails_helpers'

module Fridge
# Railtie that automatically includes RailsHelpers into ActionController::Base.
class Railtie < Rails::Railtie
initializer 'fridge.rails_helpers' do
ActionController::Base.send :include, RailsHelpers
ActionController::Base.include RailsHelpers
end
end
end
2 changes: 2 additions & 0 deletions lib/fridge/serialization_error.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module Fridge
class SerializationError < StandardError
end
Expand Down
4 changes: 3 additions & 1 deletion lib/fridge/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module Fridge
VERSION = '1.0.1'.freeze
VERSION = '1.0.1'
end
8 changes: 8 additions & 0 deletions spec/fixtures/app.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# frozen_string_literal: true

module Aptible
module Auth
def self.configuration; end
end
end

module Rails
class App
def env_config
Expand Down
Loading
Loading