firebase_token_auth 0.9.0 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
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