From 7a9d774ace5026ce6fe17d7c3971d8a534654d52 Mon Sep 17 00:00:00 2001 From: Yasumasa Ashida Date: Fri, 17 Feb 2023 23:34:11 +0900 Subject: [PATCH 1/5] feat: add Google One Tap sign-in support --- .gitignore | 4 +- lib/sorcery/controller/submodules/external.rb | 42 ++++++++++++++----- sorcery.gemspec | 1 + 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index ea821b4f..fdd5c666 100644 --- a/.gitignore +++ b/.gitignore @@ -56,4 +56,6 @@ spec/rails_app/log/* Gemfile*.lock gemfiles/*.lock .ruby-version -tags \ No newline at end of file +tags + +vendor/bundle \ No newline at end of file diff --git a/lib/sorcery/controller/submodules/external.rb b/lib/sorcery/controller/submodules/external.rb index 019a67a4..e5b84e5c 100644 --- a/lib/sorcery/controller/submodules/external.rb +++ b/lib/sorcery/controller/submodules/external.rb @@ -79,21 +79,43 @@ def sorcery_login_url(provider_name, args = {}) # get the user hash from a provider using information from the params and session. def sorcery_fetch_user_hash(provider_name) + sorcery_init_user_hash(provider_name) + + if provider_name == 'google' && params[:credential].present? + sorcery_get_google_user_hash(params[:credential]) + else + user_hash + end + nil + end + + def sorcery_init_user_hash(provider_name) # the application should never ask for user hashes from two different providers # on the same request. But if they do, we should be ready: on the second request, # clear out the instance variables if the provider is different provider = sorcery_get_provider provider_name - if @provider.nil? || @provider != provider - @provider = provider - @access_token = nil - @user_hash = nil - end + return unless @provider.nil? || @provider != provider - # delegate to the provider for the access token and the user hash. - # cache them in instance variables. - @access_token ||= @provider.process_callback(params, session) # sends request to oauth agent to get the token - @user_hash ||= @provider.get_user_hash(@access_token) # uses the token to send another request to the oauth agent requesting user info - nil + @provider = provider + @access_token = nil + @user_hash = nil + end + + def sorcery_get_google_user_hash(credential) + @user_hash = {} + @user_hash[:user_info] = + Google::Auth::IDTokens.verify_oidc(credential, + aud: Rails.application.config.sorcery.google.key) + @user_hash[:uid] = @user_hash[:user_info]['sub'] + end + + # delegate to the provider for the access token and the user hash. + # cache them in instance variables. + def user_hash + # sends request to oauth agent to get the token + @access_token ||= @provider.process_callback(params, session) + # uses the token to send another request to the oauth agent requesting user info + @user_hash ||= @provider.get_user_hash(@access_token) end # for backwards compatibility diff --git a/sorcery.gemspec b/sorcery.gemspec index 44e76074..34c03acb 100644 --- a/sorcery.gemspec +++ b/sorcery.gemspec @@ -36,6 +36,7 @@ Gem::Specification.new do |s| s.add_dependency 'bcrypt', '~> 3.1' s.add_dependency 'oauth', '>= 0.6' s.add_dependency 'oauth2', '~> 2.0' + s.add_dependency 'googleauth', '~> 1.3' s.add_development_dependency 'byebug', '~> 10.0.0' s.add_development_dependency 'rspec-rails', '~> 3.7.0' From da08bf35e2319c1235208c3a344cca59a63ab5e7 Mon Sep 17 00:00:00 2001 From: Yasumasa Ashida Date: Sat, 18 Feb 2023 06:49:51 +0900 Subject: [PATCH 2/5] feat: add Google One Tap sign-in support --- lib/sorcery/controller/submodules/external.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/sorcery/controller/submodules/external.rb b/lib/sorcery/controller/submodules/external.rb index e5b84e5c..70d6d8d0 100644 --- a/lib/sorcery/controller/submodules/external.rb +++ b/lib/sorcery/controller/submodules/external.rb @@ -89,10 +89,10 @@ def sorcery_fetch_user_hash(provider_name) nil end + # the application should never ask for user hashes from two different providers + # on the same request. But if they do, we should be ready: on the second request, + # clear out the instance variables if the provider is different def sorcery_init_user_hash(provider_name) - # the application should never ask for user hashes from two different providers - # on the same request. But if they do, we should be ready: on the second request, - # clear out the instance variables if the provider is different provider = sorcery_get_provider provider_name return unless @provider.nil? || @provider != provider From bdc73195e46e0ef1445f27636430600fc1e7e605 Mon Sep 17 00:00:00 2001 From: Yasumasa Ashida Date: Sat, 18 Feb 2023 07:17:37 +0900 Subject: [PATCH 3/5] feat: add Google One Tap sign-in support --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24e15520..ee5a0d59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Changelog ## HEAD +* Add support for Google One Tap sign-in +[#336](https://github.com/Sorcery/sorcery/pull/336) * Raise ArgumentError when calling change_password! with blank password [#333](https://github.com/Sorcery/sorcery/pull/333) ## 0.16.4 From 0d19c18acafb5efe2def93e3cd2db60c0184512a Mon Sep 17 00:00:00 2001 From: Yasumasa Ashida Date: Thu, 26 Oct 2023 19:06:04 +0900 Subject: [PATCH 4/5] feat: add Google One Tap sign-in support --- lib/sorcery/controller/submodules/external.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/sorcery/controller/submodules/external.rb b/lib/sorcery/controller/submodules/external.rb index 70d6d8d0..3b5b24b7 100644 --- a/lib/sorcery/controller/submodules/external.rb +++ b/lib/sorcery/controller/submodules/external.rb @@ -84,7 +84,7 @@ def sorcery_fetch_user_hash(provider_name) if provider_name == 'google' && params[:credential].present? sorcery_get_google_user_hash(params[:credential]) else - user_hash + sorcery_fetch_provider_user_hash end nil end @@ -111,12 +111,14 @@ def sorcery_get_google_user_hash(credential) # delegate to the provider for the access token and the user hash. # cache them in instance variables. - def user_hash + # rubocop: disable Naming/MemoizedInstanceVariableName + def sorcery_fetch_provider_user_hash # sends request to oauth agent to get the token @access_token ||= @provider.process_callback(params, session) # uses the token to send another request to the oauth agent requesting user info @user_hash ||= @provider.get_user_hash(@access_token) end + # rubocop: enable Naming/MemoizedInstanceVariableName # for backwards compatibility def access_token(*_args) From 0b681d96697412251175c228a398c8194366d993 Mon Sep 17 00:00:00 2001 From: Yasumasa Ashida Date: Sun, 31 Dec 2023 09:52:01 +0900 Subject: [PATCH 5/5] feat: add Google One Tap sign-in support --- lib/sorcery/controller/submodules/external.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/sorcery/controller/submodules/external.rb b/lib/sorcery/controller/submodules/external.rb index 3b5b24b7..09e9782e 100644 --- a/lib/sorcery/controller/submodules/external.rb +++ b/lib/sorcery/controller/submodules/external.rb @@ -82,7 +82,7 @@ def sorcery_fetch_user_hash(provider_name) sorcery_init_user_hash(provider_name) if provider_name == 'google' && params[:credential].present? - sorcery_get_google_user_hash(params[:credential]) + sorcery_get_google_user_hash else sorcery_fetch_provider_user_hash end @@ -101,10 +101,10 @@ def sorcery_init_user_hash(provider_name) @user_hash = nil end - def sorcery_get_google_user_hash(credential) + def sorcery_get_google_user_hash @user_hash = {} @user_hash[:user_info] = - Google::Auth::IDTokens.verify_oidc(credential, + Google::Auth::IDTokens.verify_oidc(params['credential'], aud: Rails.application.config.sorcery.google.key) @user_hash[:uid] = @user_hash[:user_info]['sub'] end