firebase_token_auth 0.9.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca7bb6f1b60938f8c7f4d37120e1cea83bb8b6a09ed2b1094a69f8f89649fc18
4
- data.tar.gz: 1d3adda763efeed626ed051b654dbba735e38af56c59d970e4b72d99ff4661d5
3
+ metadata.gz: 70ba9577033bd9cea4a260988ef4f59d12bf8740316e1ac0f063d9b3b4c96814
4
+ data.tar.gz: 15f4220908cf05164357bc438494a92b8730ebcb5ec6689a367b7dfcbdb638ef
5
5
  SHA512:
6
- metadata.gz: c9c8edc8f21d3702239d1b4cc82b4c586c595147e99de741c089a5c25ad23ef5e8fc8b5dcb6b91ea59ca97e4b50858ed1572b67aebc4b26d3ba9aa5b1ce22281
7
- data.tar.gz: 3aeb0e99cb6684b7a2f54b47e834aa4613011399ea82ad7e1d5a7b0fb34f61fe77955b06fba76d5ab56093c6a2ebc7e7146895f37d79e711972a724e1ce909ae
6
+ metadata.gz: f6e52a8dd7b81c06d140b9a7e8d350879e74fc21c6c261267a247ce4f80d233dd2b3ebbea4945d9bd1f0d5450a6ae2ce819dc4a1d325c976290c48f8d38ec4e5
7
+ data.tar.gz: 6812e67073338a0a5af317b83255a64916023054ce1e9638dd0ade1dd997353df4b2b3aba51ea19e6367e9b428c5d94ffb953384359ed01e8de93cac567670f3
@@ -0,0 +1,56 @@
1
+ name: rspec
2
+
3
+ on: push
4
+
5
+ jobs:
6
+ rspec:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ matrix:
10
+ ruby: [ 2.4, 2.5, 2.6, 2.7, "3.0" ]
11
+ steps:
12
+ - uses: actions/checkout@v2
13
+
14
+ - name: Set up Ruby
15
+ uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: ${{ matrix.ruby }}
18
+
19
+ - name: Configure Bundler
20
+ run: |
21
+ gem update --system
22
+ gem --version
23
+ gem install -N bundler -v 2
24
+
25
+ - uses: actions/cache@v1
26
+ with:
27
+ path: vendor/bundle
28
+ key: ${{ runner.os }}-gem-${{ hashFiles(format('{0}{1}', github.workspace, '/Gemfile.lock')) }}
29
+ restore-keys: ${{ runner.os }}-gem-
30
+
31
+ - name: Install ruby dependencies
32
+ run: |
33
+ bundle check || bundle install --jobs 4 --retry 3 --path vendor/bundle
34
+
35
+ - name: rspec
36
+ run: |
37
+ bundle exec rspec
38
+ env:
39
+ TEST_UID: ${{ secrets.TEST_UID }}
40
+ TEST_PROJECT_ID: ${{ secrets.TEST_PROJECT_ID }}
41
+ TEST_WEB_API_KEY: ${{ secrets.TEST_WEB_API_KEY }}
42
+ TEST_USER_EMAIL: ${{ secrets.TEST_USER_EMAIL }}
43
+ GOOGLE_ACCOUNT_TYPE: ${{ secrets.GOOGLE_ACCOUNT_TYPE }}
44
+ GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
45
+ GOOGLE_CLIENT_EMAIL: ${{ secrets.GOOGLE_CLIENT_EMAIL }}
46
+ GOOGLE_PRIVATE_KEY: ${{ secrets.GOOGLE_PRIVATE_KEY }}
47
+
48
+ - name: slack notification
49
+ uses: 8398a7/action-slack@v2
50
+ if: always()
51
+ with:
52
+ status: ${{ job.status }}
53
+ author_name: 'github action firebase_token_auth build'
54
+ env:
55
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
56
+ SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
data/.gitignore CHANGED
@@ -12,3 +12,4 @@
12
12
  .rspec_status
13
13
 
14
14
  Gemfile.lock
15
+ .ruby-version
data/.rubocop.yml CHANGED
@@ -9,3 +9,6 @@ Style/Documentation:
9
9
 
10
10
  Layout/IndentationConsistency:
11
11
  EnforcedStyle: indented_internal_methods
12
+
13
+ Style/BracesAroundHashParameters:
14
+ EnforcedStyle: braces
data/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # FirebaseTokenAuth
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/firebase_token_auth`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ FirebaseTokenAuth is an Firebase Auth Client. It supports below.
4
+ - verify id_token method
5
+ - create custom token
6
+ - fetch user info by uid/email
7
+ - update user info
6
8
 
7
9
  ## Installation
8
10
 
@@ -22,17 +24,131 @@ Or install it yourself as:
22
24
 
23
25
  ## Usage
24
26
 
25
- TODO: Write usage instructions here
27
+ on Rails, config/initializers/firebase_token_auth.rb
28
+ ```ruby
29
+ FirebaseTokenAuth.configure do |config|
30
+ ## for id_token_verify
31
+ # firebase web console => project settings => general => project ID
32
+ config.project_id = "your_project_id" # required
33
+
34
+ # firebase web console => project settings => service account => firebase admin sdk => generate new private key
35
+ # pass string of path to credential file to config.json_key_io
36
+ config.json_key_io = "#{Rails.root}/path/to/service_account_credentials.json"
37
+ # Or content of json key file wrapped with StringIO
38
+ # config.json_key_io = StringIO.new('{ ... }')
39
+
40
+ # Or set environment variables
41
+ # ENV['GOOGLE_ACCOUNT_TYPE'] = 'service_account'
42
+ # ENV['GOOGLE_CLIENT_ID'] = '000000000000000000000'
43
+ # ENV['GOOGLE_CLIENT_EMAIL'] = 'xxxx@xxxx.iam.gserviceaccount.com'
44
+ # ENV['GOOGLE_PRIVATE_KEY'] = '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n\'
45
+ end
46
+ ```
47
+ for more detail. see [here](https://github.com/googleapis/google-auth-library-ruby#example-service-account).
48
+
49
+ ### token verify
50
+ ```ruby
51
+ require 'firebase_token_auth'
52
+
53
+ FirebaseTokenAuth.configure do |config|
54
+ config.project_id = 'your_project_id'
55
+ end
56
+
57
+ client = FirebaseTokenAuth.build
58
+ result = client.verify_id_token(id_token)
59
+
60
+ puts result.uid
61
+ # => "hMPHt8RyDpOsHi1oH5XaVirSYyq2"
62
+
63
+ puts result.id_token.payload # you can see decoded id_token payload
64
+ # => {"iss"=>"https://securetoken.google.com/<your_project_id>",
65
+ # "aud"=>"<your_project_id>",
66
+ # "auth_time"=>1594494935,
67
+ # "user_id"=>"hMPHt8RyDpOsHi1oH5XaVirSYyq2",
68
+ # "sub"=>"hMPHt8RyDpOsHi1oH5XaVirSYyq2",
69
+ # "iat"=>1594494935,
70
+ # "exp"=>1594498535,
71
+ # "email"=>"<your_user_email>",
72
+ # "email_verified"=>false,
73
+ # "firebase"=>{"identities"=>{"email"=>["<your_user_email>"]}, "sign_in_provider"=>"custom"}}
74
+
75
+ puts result.id_token.header
76
+ # => {"alg"=>"RS256", "kid"=>"7623e10a045140f1cfd4be0466cf80352b59f81e", "typ"=>"JWT"}
77
+ ```
78
+
79
+ ### custom token create
80
+ ```ruby
81
+ require 'firebase_token_auth'
26
82
 
27
- ## Development
83
+ FirebaseTokenAuth.configure do |config|
84
+ config.project_id = 'your_project_id'
85
+ config.json_key_io = "#{Rails.root}/path/to/service_account_credentials.json"
86
+ end
28
87
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
88
+ client = FirebaseTokenAuth.new
89
+ c_token = client.create_custom_token(test_uid)
90
+ puts c_token
91
+ # => "eyJhbGciOXXX.eyJpc3MiOiJmaXJlYmFzXXXX.v7y7LoBXXXXX" # dummy
92
+ ```
30
93
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
94
+ ### fetch users info from firebase
95
+ ```ruby
96
+ require 'firebase_token_auth'
97
+
98
+ FirebaseTokenAuth.configure do |config|
99
+ config.project_id = 'your_project_id'
100
+ config.json_key_io = "#{Rails.root}/path/to/service_account_credentials.json"
101
+ end
102
+
103
+ client = FirebaseTokenAuth.new
104
+ result = client.user_search_by_email(test_user_email)
105
+ # result = client.user_search_by_uid(test_uid)
106
+ puts result
107
+ # => [{:created_at=>1594132097140,
108
+ # :custom_auth=>true,
109
+ # :disabled=>false,
110
+ # :email=>"<your_user_email>",
111
+ # :email_verified=>false,
112
+ # :last_login_at=>1594495792373,
113
+ # :local_id=>"hMPHt8RyDpOsHi1oH5XaVirSYyq2",
114
+ # :password_hash=>"REDACTED",
115
+ # :password_updated_at=>1594132097140,
116
+ # :provider_user_info=>
117
+ # [{:email=>"<your_user_email>",
118
+ # :federated_id=>"<your_user_email>",
119
+ # :provider_id=>"password",
120
+ # :raw_id=>"<your_user_email>"}],
121
+ # :valid_since=>1594132097}]
122
+ ```
123
+
124
+ ### update user info
125
+ ```ruby
126
+ require 'firebase_token_auth'
127
+
128
+ FirebaseTokenAuth.configure do |config|
129
+ config.project_id = 'your_project_id'
130
+ config.json_key_io = "#{Rails.root}/path/to/service_account_credentials.json"
131
+ end
132
+
133
+ client = FirebaseTokenAuth.new
134
+ # NOTE: parameter_name is snake_case
135
+ update_params = { # ref. https://firebase.google.com/docs/reference/rest/auth#section-update-profile
136
+ display_name: 'updated_name',
137
+ }
138
+ result = client.update_user(test_uid, update_params)
139
+ puts result
140
+ # => {:display_name=>"updated_name",
141
+ # :email=>"<your_user_email>",
142
+ # :email_verified=>false,
143
+ # :kind=>"identitytoolkit#SetAccountInfoResponse",
144
+ # :local_id=>"hMPHt8RyDpOsHi1oH5XaVirSYyq2",
145
+ # :password_hash=>"REDACTED",
146
+ # :provider_user_info=>[{:display_name=>"updated_name", :federated_id=>"<your_user_email>", :provider_id=>"password"}]}
147
+ ```
32
148
 
33
149
  ## Contributing
34
150
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/firebase_token_auth.
151
+ Bug reports and pull requests are welcome on GitHub at https://github.com/miyataka/firebase_token_auth.
36
152
 
37
153
 
38
154
  ## License
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.description = 'Firebase Authentication API wrapper for serverside. It support custom token auth. Of course it has id_token verify feature.'
11
11
  spec.homepage = 'https://github.com/miyataka/firebase_token_auth'
12
12
  spec.license = 'MIT'
13
- spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
13
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
14
14
 
15
15
  spec.metadata['homepage_uri'] = spec.homepage
16
16
  spec.metadata['source_code_uri'] = spec.homepage
@@ -24,6 +24,6 @@ Gem::Specification.new do |spec|
24
24
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
25
  spec.require_paths = ['lib']
26
26
 
27
- spec.add_dependency 'google-api-client'
27
+ spec.add_dependency 'google-apis-identitytoolkit_v3'
28
28
  spec.add_dependency 'jwt'
29
29
  end
@@ -13,5 +13,18 @@ module FirebaseTokenAuth
13
13
  request = Google::Apis::IdentitytoolkitV3::GetAccountInfoRequest.new(**params)
14
14
  service.get_account_info(request)
15
15
  end
16
+
17
+ def update_existing_account(uid, attributes)
18
+ update_params = { local_id: uid }.merge!(permit_attributes(attributes))
19
+ request = Google::Apis::IdentitytoolkitV3::SetAccountInfoRequest.new(**update_params)
20
+ service.set_account_info(request)
21
+ end
22
+
23
+ private
24
+
25
+ def permit_attributes(attr_hash)
26
+ permit_keys = %i[disabled display_name email email_verified password phone_number photo_url multi_factor]
27
+ attr_hash.select { |k, _v| permit_keys.include?(k) }
28
+ end
16
29
  end
17
30
  end
@@ -5,6 +5,7 @@ require 'jwt'
5
5
  require 'firebase_token_auth/public_key_manager'
6
6
  require 'firebase_token_auth/validator'
7
7
  require 'firebase_token_auth/admin_client'
8
+ require 'firebase_token_auth/exceptions'
8
9
 
9
10
  module FirebaseTokenAuth
10
11
  ALGORITHM = 'RS256'.freeze
@@ -25,19 +26,19 @@ module FirebaseTokenAuth
25
26
  end
26
27
 
27
28
  def verify_id_token(id_token, options = {})
28
- raise if id_token.nil? || id_token.empty?
29
+ raise ArgumentError, 'Firebase ID token must not null or blank strings.' if id_token.nil? || id_token.empty?
29
30
 
30
31
  public_key_id, decoded_jwt = validator.extract_kid(id_token)
31
32
  public_key_manager.refresh_publickeys!
32
33
  validator.validate(configuration.project_id, decoded_jwt)
33
34
  default_options = { algorithm: ALGORITHM, verify_iat: true, verify_expiration: true, exp_leeway: configuration.exp_leeway }
35
+ raise ValidationError, 'Public key may have expired.' unless public_key_manager.public_keys.include?(public_key_id)
34
36
  jwt = JWT.decode(id_token, public_key_manager.public_keys[public_key_id].public_key, true, default_options.merge!(options))
35
37
  IdTokenResult.new(jwt[0]['sub'], IdToken.new(jwt[0], jwt[1]))
36
38
  end
37
39
 
38
40
  def create_custom_token(uid, additional_claims = nil)
39
- # TODO: implement Error
40
- raise unless configuration.configured_for_custom_token?
41
+ raise ConfigurationError, 'To create custom token, You must configure credentials via json or environmental variables.' unless configuration.configured_for_custom_token?
41
42
 
42
43
  now_seconds = Time.now.to_i
43
44
  payload = { iss: configuration.client_email,
@@ -58,6 +59,10 @@ module FirebaseTokenAuth
58
59
  admin_client.get_account_info({ local_id: [uid] })&.users&.map(&:to_h)
59
60
  end
60
61
 
62
+ def update_user(uid, attribute_hash)
63
+ admin_client.update_existing_account(uid, attribute_hash).to_h
64
+ end
65
+
61
66
  private
62
67
 
63
68
  def admin_client
@@ -24,8 +24,7 @@ module FirebaseTokenAuth
24
24
  end
25
25
 
26
26
  def prepare
27
- # TODO: implement error
28
- raise unless project_id
27
+ raise ConfigurationError, 'project_id is required to use firebase_token_auth gem.' unless project_id
29
28
  return unless configured_for_custom_token?
30
29
 
31
30
  @auth = if json_key_io
@@ -45,7 +44,7 @@ module FirebaseTokenAuth
45
44
  @private_key = OpenSSL::PKey::RSA.new(parsed['private_key'])
46
45
  @client_email = parsed['client_email']
47
46
  else
48
- @private_key = OpenSSL::PKey::RSA.new(ENV['GOOGLE_PRIVATE_KEY'])
47
+ @private_key = OpenSSL::PKey::RSA.new(unescape(ENV['GOOGLE_PRIVATE_KEY']))
49
48
  @client_email = ENV['GOOGLE_CLIENT_EMAIL']
50
49
  end
51
50
  end
@@ -53,5 +52,11 @@ module FirebaseTokenAuth
53
52
  def configured_for_custom_token?
54
53
  json_key_io || (ENV['GOOGLE_PRIVATE_KEY'] && ENV['GOOGLE_CLIENT_EMAIL'])
55
54
  end
55
+
56
+ def unescape(str)
57
+ str = str.gsub('\n', "\n")
58
+ str = str[1..-2] if str.start_with?('"') && str.end_with?('"')
59
+ str
60
+ end
56
61
  end
57
62
  end
@@ -0,0 +1,104 @@
1
+ module FirebaseTokenAuth
2
+ class APIError < StandardError; end
3
+ class NetworkError < APIError; end
4
+
5
+ class HttpError < APIError
6
+ attr_reader :response
7
+
8
+ def initialize(message, response)
9
+ super(message)
10
+ @response = response
11
+ end
12
+ end
13
+
14
+ class ClientError < HttpError; end
15
+
16
+ class BadRequest < ClientError; end # status: 400
17
+ class Unauthorized < ClientError; end # status: 401
18
+ class PaymentRequired < ClientError; end # status: 402
19
+ class Forbidden < ClientError; end # status: 403
20
+ class NotFound < ClientError; end # status: 404
21
+ class MethodNotAllowed < ClientError; end # status: 405
22
+ class NotAcceptable < ClientError; end # status: 406
23
+ class ProxyAuthenticationRequired < ClientError; end # status: 407
24
+ class RequestTimeout < ClientError; end # status: 408
25
+ class Conflict < ClientError; end # status: 409
26
+ class Gone < ClientError; end # status: 410
27
+ class LengthRequired < ClientError; end # status: 411
28
+ class PreconditionFailed < ClientError; end # status: 412
29
+ class PayloadTooLarge < ClientError; end # status: 413
30
+ class URITooLong < ClientError; end # status: 414
31
+ class UnsupportedMediaType < ClientError; end # status: 415
32
+ class RangeNotSatisfiable < ClientError; end # status: 416
33
+ class ExpectationFailed < ClientError; end # status: 417
34
+ class ImaTeapot < ClientError; end # status: 418
35
+ class MisdirectedRequest < ClientError; end # status: 421
36
+ class UnprocessableEntity < ClientError; end # status: 422
37
+ class Locked < ClientError; end # status: 423
38
+ class FailedDependency < ClientError; end # status: 424
39
+ class UpgradeRequired < ClientError; end # status: 426
40
+ class PreconditionRequired < ClientError; end # status: 428
41
+ class TooManyRequests < ClientError; end # status: 429
42
+ class RequestHeaderFieldsTooLarge < ClientError; end # status: 431
43
+ class UnavailableForLegalReasons < ClientError; end # status: 451
44
+
45
+ class ServerError < HttpError; end
46
+
47
+ class InternalServerError < ServerError; end # status: 500
48
+ class NotImplemented < ServerError; end # status: 501
49
+ class BadGateway < ServerError; end # status: 502
50
+ class ServiceUnavailable < ServerError; end # status: 503
51
+ class GatewayTimeout < ServerError; end # status: 504
52
+ class HTTPVersionNotSupported < ServerError; end # status: 505
53
+ class VariantAlsoNegotiates < ServerError; end # status: 506
54
+ class InsufficientStorage < ServerError; end # status: 507
55
+ class LoopDetected < ServerError; end # status: 508
56
+ class NotExtended < ServerError; end # status: 510
57
+ class NetworkAuthenticationRequired < ServerError; end # status: 511
58
+
59
+ STATUS_TO_EXCEPTION_MAPPING = {
60
+ '400' => BadRequest,
61
+ '401' => Unauthorized,
62
+ '402' => PaymentRequired,
63
+ '403' => Forbidden,
64
+ '404' => NotFound,
65
+ '405' => MethodNotAllowed,
66
+ '406' => NotAcceptable,
67
+ '407' => ProxyAuthenticationRequired,
68
+ '408' => RequestTimeout,
69
+ '409' => Conflict,
70
+ '410' => Gone,
71
+ '411' => LengthRequired,
72
+ '412' => PreconditionFailed,
73
+ '413' => PayloadTooLarge,
74
+ '414' => URITooLong,
75
+ '415' => UnsupportedMediaType,
76
+ '416' => RangeNotSatisfiable,
77
+ '417' => ExpectationFailed,
78
+ '418' => ImaTeapot,
79
+ '421' => MisdirectedRequest,
80
+ '422' => UnprocessableEntity,
81
+ '423' => Locked,
82
+ '424' => FailedDependency,
83
+ '426' => UpgradeRequired,
84
+ '428' => PreconditionRequired,
85
+ '429' => TooManyRequests,
86
+ '431' => RequestHeaderFieldsTooLarge,
87
+ '451' => UnavailableForLegalReasons,
88
+ '500' => InternalServerError,
89
+ '501' => NotImplemented,
90
+ '502' => BadGateway,
91
+ '503' => ServiceUnavailable,
92
+ '504' => GatewayTimeout,
93
+ '505' => HTTPVersionNotSupported,
94
+ '506' => VariantAlsoNegotiates,
95
+ '507' => InsufficientStorage,
96
+ '508' => LoopDetected,
97
+ '510' => NotExtended,
98
+ '511' => NetworkAuthenticationRequired
99
+ }.freeze
100
+
101
+ class ValidationError < StandardError; end
102
+ class ConfigurationError < StandardError; end
103
+ class ArgumentError < StandardError; end
104
+ end
@@ -19,7 +19,7 @@ module FirebaseTokenAuth
19
19
  private
20
20
 
21
21
  def fetch_publickeys_hash
22
- res = Net::HTTP.get_response(URI(PUBLIC_KEY_URL))
22
+ res = exception_handler(Net::HTTP.get_response(URI(PUBLIC_KEY_URL)))
23
23
  @public_keys = JSON.parse(res.body).transform_values! { |v| OpenSSL::X509::Certificate.new(v) }
24
24
  @expire_time = cache_control_header_to_expire_time(res['Cache-Control'])
25
25
  end
@@ -31,5 +31,12 @@ module FirebaseTokenAuth
31
31
  def cache_control_header_to_expire_time(cache_control_header)
32
32
  Time.now.to_i + cache_control_header.match(/max-age=([0-9]*)/)[1].to_i
33
33
  end
34
+
35
+ def exception_handler(response)
36
+ error = STATUS_TO_EXCEPTION_MAPPING[response.code]
37
+ raise error.new("Receieved an error response #{response.code} #{error.to_s.split('::').last}: #{response.body}", response) if error
38
+
39
+ response
40
+ end
34
41
  end
35
42
  end
@@ -7,13 +7,13 @@ module FirebaseTokenAuth
7
7
  payload = decoded_jwt[0]
8
8
  header = decoded_jwt[1]
9
9
  issuer = ISSUER_BASE_URL + project_id
10
- raise unless header['kid']
11
- raise unless header['alg'] == ALGORITHM
12
- raise unless payload['aud'] == project_id
13
- raise unless payload['iss'] == issuer
14
- raise unless payload['sub'].is_a?(String)
15
- raise if payload['sub'].empty?
16
- raise if payload['sub'].size > 128
10
+ raise ValidationError, 'Firebase ID token has no "kid" claim.' unless header['kid']
11
+ raise ValidationError, "Firebase ID token has incorrect algorithm. Expected \"#{ALGORITHM}\" but got \"#{header['alg']}\"." unless header['alg'] == ALGORITHM
12
+ raise ValidationError, "Firebase ID token has incorrect \"aud\" (audience) claim. Expected \"#{project_id}\" but got \"#{payload['aud']}\"." unless payload['aud'] == project_id
13
+ raise ValidationError, "Firebase ID token has \"iss\" (issuer) claim. Expected \"#{issuer}\" but got \"#{payload['iss']}\"." unless payload['iss'] == issuer
14
+ raise ValidationError, 'Firebase ID token has no "sub" (subject) claim.' unless payload['sub'].is_a?(String)
15
+ raise ValidationError, 'Firebase ID token has an empty string "sub" (subject) claim.' if payload['sub'].empty?
16
+ raise ValidationError, 'Firebase ID token has "sub" (subject) claim longer than 128 characters.' if payload['sub'].size > 128
17
17
  end
18
18
 
19
19
  def extract_kid(id_token)
@@ -1,3 +1,3 @@
1
1
  module FirebaseTokenAuth
2
- VERSION = '0.9.0'.freeze
2
+ VERSION = '1.2.2'.freeze
3
3
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: firebase_token_auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 1.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - miyataka
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-07-08 00:00:00.000000000 Z
11
+ date: 2021-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: google-api-client
14
+ name: google-apis-identitytoolkit_v3
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
@@ -46,6 +46,7 @@ executables: []
46
46
  extensions: []
47
47
  extra_rdoc_files: []
48
48
  files:
49
+ - ".github/workflows/test.yml"
49
50
  - ".gitignore"
50
51
  - ".rspec"
51
52
  - ".rubocop.yml"
@@ -61,6 +62,7 @@ files:
61
62
  - lib/firebase_token_auth/admin_client.rb
62
63
  - lib/firebase_token_auth/client.rb
63
64
  - lib/firebase_token_auth/configuration.rb
65
+ - lib/firebase_token_auth/exceptions.rb
64
66
  - lib/firebase_token_auth/public_key_manager.rb
65
67
  - lib/firebase_token_auth/validator.rb
66
68
  - lib/firebase_token_auth/version.rb
@@ -78,14 +80,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
78
80
  requirements:
79
81
  - - ">="
80
82
  - !ruby/object:Gem::Version
81
- version: 2.3.0
83
+ version: 2.4.0
82
84
  required_rubygems_version: !ruby/object:Gem::Requirement
83
85
  requirements:
84
86
  - - ">="
85
87
  - !ruby/object:Gem::Version
86
88
  version: '0'
87
89
  requirements: []
88
- rubygems_version: 3.1.2
90
+ rubygems_version: 3.1.4
89
91
  signing_key:
90
92
  specification_version: 4
91
93
  summary: Firebase Authentication API wrapper for serverside. It support custom token