Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rubocop fixes #3

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ jobs:
bundler-cache: true # 'bundle install' and cache
- name: Run specs
run: |
bundle exec rspec
bundle exec rspec
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ jobs:
bundler-cache: true # 'bundle install' and cache
- name: Run specs
run: |
bundle exec rubocop
bundle exec rubocop
16 changes: 10 additions & 6 deletions lib/warden/jwt_auth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ module Warden
module JWTAuth
extend Dry::Configurable

@@jwks = nil
@jwks = nil

def symbolize_keys(hash)
hash.transform_keys(&:to_sym)
Expand All @@ -39,14 +39,18 @@ def constantize_values(hash)
end

def init_jkws_loader(url)
if url
@@jwks = JWKS.new(url)
JWTAuth.config.algorithm = @@jwks.algo
end
return unless url

@jwks = JWKS.new(url)
JWTAuth.config.algorithm = @jwks.algo
end

def self.jwks
@@jwks
@jwks
end

def jwks
self.class.jwks
end

module_function :init_jkws_loader, :constantize_values, :symbolize_keys, :upcase_first_items
Expand Down
2 changes: 1 addition & 1 deletion lib/warden/jwt_auth/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class NilUser < JWT::DecodeError
class WrongScope < JWT::DecodeError
end

# Error raised when trying to decode a token without scope claim and
# Error raised when trying to decode a token without scope claim and
# no default_scope set
class MissingScopeWithNoDefaultFallback < JWT::DecodeError
end
Expand Down
18 changes: 10 additions & 8 deletions lib/warden/jwt_auth/jwks.rb
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
# frozen_string_literal: true

module Warden
module JWTAuth
# JWKS fetcher class.
#
# Uses a Rails cache key to store the payload
class JWKS

JWKS_CACHE_KEY = "auth/jwks-json".freeze
JWKS_CACHE_KEY = 'auth/jwks-json'

def initialize(url)
@jwks_url = url
end

def loader(options={})
def loader(options = {})
jwks(force: options[:invalidate]) || {}
end

def algo(key_index=0)
def algo(key_index = 0)
loader[:keys][key_index][:alg]
end

private

def fetch_jwks
response = Faraday.get(@jwks_url)
if response.status == 200
JSON.parse(response.body.to_s)
end
JSON.parse(response.body.to_s) if response.status == 200
end

def jwks(force: false)
Expand All @@ -32,4 +34,4 @@ def jwks(force: false)
end
end
end
end
end
7 changes: 4 additions & 3 deletions lib/warden/jwt_auth/strategy.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require 'warden'
require 'semantic_logger'

module Warden
module JWTAuth
Expand All @@ -21,13 +22,13 @@ def authenticate!
aud = EnvHelper.aud_header(env)
user = UserDecoder.new.call(token, scope, aud)

logger.warn("JWT accepted", user: user.id) if user
logger.warn('JWT accepted', user: user.id) if user

success!(user)
rescue JWT::DecodeError => e
logger.error("JWT decoding failed", message: e.message)
logger.error('JWT decoding failed', message: e.message)

fail!(e.message)
fail!(e.message)
end

private
Expand Down
13 changes: 2 additions & 11 deletions lib/warden/jwt_auth/token_decoder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,9 @@ def call(token)
def decode(token, secret)
if JWTAuth.config.jwks_url
jwks = Warden::JWTAuth.jwks
JWT.decode(token,
secret,
true,
algorithm: jwks.algo,
verify_jti: true,
jwks: jwks.loader)[0]
JWT.decode(token, secret, true, algorithm: jwks.algo, verify_jti: true, jwks: jwks.loader)[0]
else
JWT.decode(token,
secret,
true,
algorithm: algorithm,
verify_jti: true)[0]
JWT.decode(token, secret, true, algorithm: algorithm, verify_jti: true)[0]
end
end
end
Expand Down
25 changes: 20 additions & 5 deletions lib/warden/jwt_auth/user_decoder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,17 @@ def initialize(**args)
# encoded user
# @raise [Errors::NilUser] when decoded user is nil
# @raise [Errors::WrongScope] when encoded scope does not match with scope
# @raise [Errors::WrongAud] when encoded aud does not match with aud
# argument
# @raise [Errors::WrongAud] when encoded aud does not match with aud argument
# rubocop:disable Metrics/MethodLength
def call(token, scope, aud)
config = JWTAuth.config
payload = TokenDecoder.new.call(token)

if payload_has_no_scope?(payload)
raise Errors::MissingScopeWithNoDefaultFallback, 'payload has no scp claim and no default_scope is set' unless config.default_scope
unless config.default_scope
raise Errors::MissingScopeWithNoDefaultFallback, 'payload has no scp claim and no default_scope is set'
end

scope = payload['scp'] = config.default_scope
end

Expand All @@ -43,22 +46,34 @@ def call(token, scope, aud)
check_valid_user(payload, user, scope)
user
end
# rubocop:enable Metrics/MethodLength

private

def check_valid_claims(payload, scope, aud)
raise Errors::WrongScope, 'wrong scope' unless helper.scope_matches?(payload, scope)

if aud.nil? && !payload['aud'].nil?
raise Errors::MissingAudHeaderWithNoFallback, 'aud_header is missing and valid_auds setting is unset' unless JWTAuth.config.valid_auds
raise Errors::WrongAud, 'aud_header missing and aud claim is not part of the valid_auds setting' unless helper.aud_matches_valid_ones?(payload)
check_empty_aud_header(payload)
else
raise Errors::WrongAud, 'wrong aud' unless helper.aud_matches?(payload, aud)
end

scope
end

def check_empty_aud_header(payload)
unless JWTAuth.config.valid_auds
raise Errors::MissingAudHeaderWithNoFallback, 'aud_header is missing and valid_auds setting is unset'
end

# rubocop:disable Style/GuardClause
unless helper.aud_matches_valid_ones?(payload)
raise Errors::WrongAud, 'aud_header missing and aud claim is not part of the valid_auds setting'
end
# rubocop:enable Style/GuardClause
end

def check_valid_user(payload, user, scope)
raise Errors::NilUser, 'nil user' unless user

Expand Down
4 changes: 4 additions & 0 deletions spec/support/fixtures.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ module Fixtures
class User
include Singleton

def id
1
end

def jwt_subject
'1'
end
Expand Down
12 changes: 7 additions & 5 deletions spec/warden/jwt_auth/strategy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@
end
end

context "when issuer is configured" do
let(:token) { Warden::JWTAuth::TokenEncoder.new.call({issuer: issuer}) }
# rubocop:disable RSpec/NestedGroups
context 'when issuer is configured' do
let(:token) { Warden::JWTAuth::TokenEncoder.new.call({ issuer: issuer }) }
let(:env) { { 'HTTP_AUTHORIZATION' => "Bearer #{token}" } }
let(:issuer) { 'http://example.com' }
let(:strategy) { described_class.new(env, :user) }
Expand All @@ -43,20 +44,21 @@
end
end

context "when the issuer claim matches the configured issuer" do
context 'when the issuer claim matches the configured issuer' do
it 'returns true' do
expect(strategy).to be_valid
end
end

context "when the issuer claim does not match the configured issuer" do
let(:token) { Warden::JWTAuth::TokenEncoder.new.call({"iss" => 'http://example.org'}) }
context 'when the issuer claim does not match the configured issuer' do
let(:token) { Warden::JWTAuth::TokenEncoder.new.call({ 'iss' => 'http://example.org' }) }

it 'returns false' do
expect(strategy).not_to be_valid
end
end
end
# rubocop:enable RSpec/NestedGroups
end

describe '#persist?' do
Expand Down
1 change: 1 addition & 0 deletions spec/warden/jwt_auth/token_encoder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@

context 'with issuer claim' do
let(:issuer) { 'http://example.com' }

before do
Warden::JWTAuth.configure do |config|
config.issuer = issuer
Expand Down