diff --git a/CHANGELOG.md b/CHANGELOG.md index 6af01f56..4ddfb64d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - Remove 'typ' optional parameter [\#174](https://github.com/jwt/ruby-jwt/pull/174) ([xamenrax](https://github.com/xamenrax)) - Pass payload to keyfinder [\#172](https://github.com/jwt/ruby-jwt/pull/172) ([CodeMonkeySteve](https://github.com/CodeMonkeySteve)) - Use RbNaCl for HMAC if available with fallback to OpenSSL [\#149](https://github.com/jwt/ruby-jwt/pull/149) ([mwpastore](https://github.com/mwpastore)) +- Allow configuration of multiple acceptable issuers [\#210](https://github.com/jwt/ruby-jwt/pull/210) **Fixed bugs:** diff --git a/README.md b/README.md index 6edd953d..aa11dba6 100644 --- a/README.md +++ b/README.md @@ -277,6 +277,8 @@ From [Oauth JSON Web Token 4.1.1. "iss" (Issuer) Claim](https://tools.ietf.org/h > The `iss` (issuer) claim identifies the principal that issued the JWT. The processing of this claim is generally application specific. The `iss` value is a case-sensitive string containing a ***StringOrURI*** value. Use of this claim is OPTIONAL. +You can pass multiple allowed issuers as an Array, verification will pass if oCne of them matches the `iss` value in the payload. + ```ruby iss = 'My Awesome Company Inc. or https://my.awesome.website/' iss_payload = { :data => 'data', :iss => iss } diff --git a/lib/jwt/verify.rb b/lib/jwt/verify.rb index 6a738baf..a3d3c945 100644 --- a/lib/jwt/verify.rb +++ b/lib/jwt/verify.rb @@ -41,7 +41,8 @@ def verify_iat def verify_iss return unless (options_iss = @options[:iss]) - raise(JWT::InvalidIssuerError, "Invalid issuer. Expected #{options_iss}, received #{@payload['iss'] || ''}") if @payload['iss'].to_s != options_iss.to_s + return if Array(options_iss).map(&:to_s).include?(@payload['iss'].to_s) + raise(JWT::InvalidIssuerError, "Invalid issuer. Expected #{options_iss}, received #{@payload['iss'] || ''}") end def verify_jti diff --git a/spec/jwt/verify_spec.rb b/spec/jwt/verify_spec.rb index 46f5898d..a732765c 100644 --- a/spec/jwt/verify_spec.rb +++ b/spec/jwt/verify_spec.rb @@ -108,20 +108,39 @@ module JWT let(:invalid_token) { JWT.encode base_payload, payload[:secret] } - it 'must raise JWT::InvalidIssuerError when the configured issuer does not match the payload issuer' do - expect do - Verify.verify_iss(payload, options.merge(iss: 'mismatched-issuer')) - end.to raise_error JWT::InvalidIssuerError - end - - it 'must raise JWT::InvalidIssuerError when the payload does not include an issuer' do - expect do - Verify.verify_iss(base_payload, options.merge(iss: iss)) - end.to raise_error(JWT::InvalidIssuerError, /received /) - end - - it 'must allow a matching issuer to pass' do - Verify.verify_iss(payload, options.merge(iss: iss)) + context 'when iss is a String' do + it 'must raise JWT::InvalidIssuerError when the configured issuer does not match the payload issuer' do + expect do + Verify.verify_iss(payload, options.merge(iss: 'mismatched-issuer')) + end.to raise_error JWT::InvalidIssuerError + end + + it 'must raise JWT::InvalidIssuerError when the payload does not include an issuer' do + expect do + Verify.verify_iss(base_payload, options.merge(iss: iss)) + end.to raise_error(JWT::InvalidIssuerError, /received /) + end + + it 'must allow a matching issuer to pass' do + Verify.verify_iss(payload, options.merge(iss: iss)) + end + end + context 'when iss is an Array' do + it 'must raise JWT::InvalidIssuerError when no matching issuers in array' do + expect do + Verify.verify_iss(payload, options.merge(iss: %w[first second])) + end.to raise_error JWT::InvalidIssuerError + end + + it 'must raise JWT::InvalidIssuerError when the payload does not include an issuer' do + expect do + Verify.verify_iss(base_payload, options.merge(iss: %w[first second])) + end.to raise_error(JWT::InvalidIssuerError, /received /) + end + + it 'must allow an array with matching issuer to pass' do + Verify.verify_iss(payload, options.merge(iss: ['first', iss, 'third'])) + end end end