From 90c5c3fa79ebf1eaaba97fbf07bd243ae40f5c32 Mon Sep 17 00:00:00 2001 From: Chris Tran Date: Mon, 23 Dec 2024 16:00:10 -0600 Subject: [PATCH 1/6] feat!: remove deprecated Client methods --- lib/passageidentity/client.rb | 66 ----------------------------------- tests/app_test.rb | 31 ---------------- 2 files changed, 97 deletions(-) delete mode 100644 tests/app_test.rb diff --git a/lib/passageidentity/client.rb b/lib/passageidentity/client.rb index 065c8d3..e3cc9c1 100644 --- a/lib/passageidentity/client.rb +++ b/lib/passageidentity/client.rb @@ -1,11 +1,9 @@ # frozen_string_literal: true -require 'rubygems' require_relative 'auth' require_relative 'user_api' require_relative 'error' require_relative 'version' -require_relative '../openapi_client' module Passage COOKIE_STRATEGY = 0 @@ -18,8 +16,6 @@ module Passage class Client attr_reader :auth, :user - extend Gem::Deprecate - def initialize(app_id:, api_key: '', auth_strategy: COOKIE_STRATEGY) @app_id = app_id @api_key = api_key @@ -44,70 +40,8 @@ def initialize(app_id:, api_key: '', auth_strategy: COOKIE_STRATEGY) @req_opts[:header_params] = header_params @req_opts[:debug_auth_names] = ['header'] - # initialize auth class @auth = Passage::Auth.new(@app_id, @api_key, @auth_strategy) - - # initialize user class @user = Passage::UserAPI.new(@app_id, @api_key) - - @magic_links_client = OpenapiClient::MagicLinksApi.new - end - - # rubocop:disable Naming/AccessorMethodName - def get_app - client = OpenapiClient::AppsApi.new - client.get_app(@app_id).app - rescue StandardError => e - raise e - end - # rubocop:enable Naming/AccessorMethodName - - # rubocop:disable Metrics/ParameterLists, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity - def create_magic_link( - user_id: '', - email: '', - phone: '', - channel: '', - send: false, - magic_link_path: '', - redirect_url: '', - language: '', - ttl: 60, - type: 'login' - ) - args = {} - args['user_id'] = user_id unless user_id.empty? - args['email'] = email unless email.empty? - args['phone'] = phone unless phone.empty? - - unless [PHONE_CHANNEL, EMAIL_CHANNEL].include? channel - raise PassageError.new( - message: - 'channel: must be either Passage::EMAIL_CHANNEL or Passage::PHONE_CHANNEL' - ) - end - - args['channel'] = channel unless channel.empty? - args['type'] = type - args['send'] = send - - args['language'] = language unless language.empty? - args['magic_link_path'] = magic_link_path unless magic_link_path.empty? - args['redirect_url'] = redirect_url unless redirect_url.empty? - args['ttl'] = ttl unless ttl.zero? - - begin - @magic_links_client.create_magic_link(@app_id, args, @req_opts).magic_link - rescue Faraday::Error => e - raise PassageError.new( - status_code: e.response[:status], - body: e.response[:body] - ) - end end - # rubocop:enable Metrics/ParameterLists, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity - - deprecate(:create_magic_link, 'Passage::Auth.create_magic_link', 2025, 1) - deprecate(:get_app, :none, 2025, 1) end end diff --git a/tests/app_test.rb b/tests/app_test.rb deleted file mode 100644 index 831d197..0000000 --- a/tests/app_test.rb +++ /dev/null @@ -1,31 +0,0 @@ -# frozen_string_literal: true - -require_relative '../lib/passageidentity/client' -require 'dotenv' -require 'faraday' -require 'test/unit' - -Dotenv.load('.env') - -# This is a test suite for the Passage App API using the Test::Unit framework. -class TestAppAPI < Test::Unit::TestCase - PassageClient = - Passage::Client.new(app_id: ENV['APP_ID'], api_key: ENV['API_KEY']) - - def test_get_app - app = PassageClient.get_app - assert_equal ENV['APP_ID'], app.id - end - - def test_create_magic_link - magic_link = - PassageClient.create_magic_link( - email: 'passage@passage.id', - channel: Passage::EMAIL_CHANNEL, - ttl: 122 - ) - - assert_equal 122, magic_link.ttl - assert_equal 'passage@passage.id', magic_link.identifier - end -end From ddbac29b19f69dc431db6d61b66e872766c248fc Mon Sep 17 00:00:00 2001 From: Chris Tran Date: Mon, 23 Dec 2024 16:05:18 -0600 Subject: [PATCH 2/6] feat!: remove deprecated Auth methods --- lib/passageidentity/auth.rb | 69 +--------------------------- tests/auth_test.rb | 91 +------------------------------------ 2 files changed, 2 insertions(+), 158 deletions(-) diff --git a/lib/passageidentity/auth.rb b/lib/passageidentity/auth.rb index 66b7a60..1a6ccea 100644 --- a/lib/passageidentity/auth.rb +++ b/lib/passageidentity/auth.rb @@ -2,15 +2,12 @@ require 'active_support' require 'jwt' -require 'rubygems/deprecate' require_relative 'client' require_relative '../openapi_client' module Passage # The Passage::Auth class provides methods for authenticating requests and tokens class Auth - extend Gem::Deprecate - def initialize(app_id, api_key, auth_strategy) @app_cache = ActiveSupport::Cache::MemoryStore.new @app_id = app_id @@ -30,37 +27,6 @@ def initialize(app_id, api_key, auth_strategy) @magic_links_client = OpenapiClient::MagicLinksApi.new end - def authenticate_request(request) - # Get the token based on the strategy - if @auth_strategy == Passage::COOKIE_STRATEGY - unless request.cookies.key?('psg_auth_token') - raise PassageError.new( - status_code: 401, - body: { - error: 'missing authentication token: expected "psg_auth_token" cookie', - code: 'invalid_access_token' - } - ) - end - @token = request.cookies['psg_auth_token'] - else - headers = request.headers - unless headers.key?('Authorization') - raise PassageError.new( - status_code: 401, - body: { - error: 'no authentication token in header', - code: 'invalid_access_token' - } - ) - end - - @token = headers['Authorization'].split(' ').last - end - - validate_jwt(@token) - end - def validate_jwt(token) raise ArgumentError, 'jwt is required.' unless token && !token.empty? @@ -101,19 +67,6 @@ def validate_jwt(token) ) end - def revoke_user_refresh_tokens(user_id) - warn 'NOTE: Passage::Auth#revoke_user_refresh_tokens is deprecated; - use Passage::User#revoke_refresh_tokens instead. It will be removed on or after 2024-12.' - user_exists?(user_id) - - @tokens_client.revoke_user_refresh_tokens(@app_id, user_id, @req_opts) - rescue Faraday::Error => e - raise PassageError.new( - status_code: e.response[:status], - body: e.response[:body] - ) - end - def create_magic_link_with_email(email, type, send, opts = {}) args = {} args['email'] = email @@ -144,17 +97,7 @@ def create_magic_link_with_user(user_id, channel, type, send, opts = {}) create_magic_link(args, opts) end - def fetch_app - client = OpenapiClient::AppsApi.new - response = client.get_app(@app_id) - - response.app - rescue Faraday::Error => e - raise PassageError.new( - status_code: e.response[:status], - body: e.response[:body] - ) - end + private def fetch_jwks app_cache = get_cache(@app_id) @@ -180,12 +123,6 @@ def fetch_jwks end end - def authenticate_token(token) - validate_jwt(token) - end - - private - def create_magic_link(args, opts) args['language'] = opts['language'] args['magic_link_path'] = opts['magic_link_path'] @@ -234,9 +171,5 @@ def get_cache(key) def set_cache(key:, jwks:) @app_cache.write(key, jwks, expires_in: 86_400) end - deprecate(:authenticate_request, :validate_jwt, 2025, 1) - deprecate(:authenticate_token, :validate_jwt, 2025, 1) - deprecate(:fetch_app, :none, 2025, 1) - deprecate(:fetch_jwks, :none, 2025, 1) end end diff --git a/tests/auth_test.rb b/tests/auth_test.rb index 8434eb3..b84f5bd 100644 --- a/tests/auth_test.rb +++ b/tests/auth_test.rb @@ -2,32 +2,13 @@ require_relative '../lib/passageidentity/client' require 'dotenv' -require 'faraday' -require 'rack' require 'test/unit' Dotenv.load('.env') # This is a test suite for the Passage Auth API using the Test::Unit framework. class TestAuthAPI < Test::Unit::TestCase - PassageClient = - Passage::Client.new(app_id: ENV['APP_ID'], api_key: ENV['API_KEY']) - PassageHeaderClient = - Passage::Client.new( - app_id: ENV['APP_ID'], - api_key: ENV['API_KEY'], - auth_strategy: Passage::HEADER_STRATEGY - ) - - def setup - @test_user = - PassageClient.user.create( - email: 'passage+test-ruby@passage.id', - user_metadata: { - example1: 'cool' - } - ) - end + PassageClient = Passage::Client.new(app_id: ENV['APP_ID'], api_key: ENV['API_KEY']) def test_valid_jwt user_id = PassageClient.auth.validate_jwt(ENV['PSG_JWT']) @@ -39,74 +20,4 @@ def test_invalid_jwt PassageClient.auth.validate_jwt('invalid_token') end end - - def test_valid_authenticate_request_cookie - env = Rack::MockRequest.env_for('https://test.com') - env['HTTP_COOKIE'] = "psg_auth_token=#{ENV['PSG_JWT']}" - cookie_request = Rack::Request.new(env) - user_id = PassageClient.auth.authenticate_request(cookie_request) - assert_equal ENV['TEST_USER_ID'], user_id - end - - def test_invalid_authenticate_request_cookie - env_bad_cookie = Rack::MockRequest.env_for('https://test.com') - env_bad_cookie['HTTP_COOKIE'] = 'psg_auth_token=invalid_token}' - bad_cookie_request = Rack::Request.new(env_bad_cookie) - assert_raises Passage::PassageError do - PassageClient.auth.authenticate_request(bad_cookie_request) - end - no_cookie_request = Rack::Request.new({}) - assert_raises Passage::PassageError do - PassageClient.auth.authenticate_request(no_cookie_request) - end - end - - def test_valid_authenticate_request_header - headers = { 'Authorization' => "Bearer #{ENV['PSG_JWT']}" } - header_request = Faraday.new(url: 'https://test.com', headers: headers) - user_id = PassageHeaderClient.auth.authenticate_request(header_request) - assert_equal ENV['TEST_USER_ID'], user_id - end - - def test_invalid_authenticate_request_header - invalid_headers = { 'Authorization' => 'Bearer invalid_token' } - no_header_request = Faraday.new(url: 'https://test.com') - assert_raises Passage::PassageError do - PassageHeaderClient.auth.authenticate_request(no_header_request) - end - Faraday.new(url: 'https://test.com', headers: invalid_headers) - assert_raises Passage::PassageError do - PassageHeaderClient.auth.authenticate_request(no_header_request) - end - end - - def test_create_magic_link - magic_link = - PassageClient.create_magic_link( - email: 'passage@passage.id', - channel: Passage::EMAIL_CHANNEL, - ttl: 122 - ) - - assert_equal 122, magic_link.ttl - assert_equal 'passage@passage.id', magic_link.identifier - end - - def test_invalid_create_magic_link - assert_raises Passage::PassageError do - PassageClient.create_magic_link( - email: 'passage@passage.id', - ttl: 122 - ) - end - end - - def test_revoke_user_refresh_tokens - success = PassageClient.auth.revoke_user_refresh_tokens(@test_user.id) - assert_equal nil, success - end - - def teardown - PassageClient.user.delete(user_id: @test_user.id) - end end From 9db826222cebdb6a9db3a3003f4c61b1a3882162 Mon Sep 17 00:00:00 2001 From: Chris Tran Date: Mon, 23 Dec 2024 16:06:17 -0600 Subject: [PATCH 3/6] feat!: remove deprecated User methods --- lib/passageidentity/user_api.rb | 17 ----------------- tests/user_api_test.rb | 8 +------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/lib/passageidentity/user_api.rb b/lib/passageidentity/user_api.rb index cac0e28..70eee39 100644 --- a/lib/passageidentity/user_api.rb +++ b/lib/passageidentity/user_api.rb @@ -1,15 +1,11 @@ # frozen_string_literal: true -require 'rubygems/deprecate' require_relative 'client' module Passage # The UserAPI class provides methods for interacting with Passage Users class UserAPI - extend Gem::Deprecate - # rubocop:disable Metrics/AbcSize - # This class will require an API key def initialize(app_id, api_key) @app_id = app_id @api_key = api_key @@ -146,11 +142,6 @@ def revoke_device(user_id:, device_id:) end end - def delete_device(user_id:, device_id:) - revoke_device(user_id: user_id, device_id: device_id) - true - end - def list_devices(user_id:) raise ArgumentError, 'user_id is required.' unless user_id && !user_id.empty? @@ -165,11 +156,6 @@ def list_devices(user_id:) end end - def signout(user_id:) - revoke_refresh_tokens(user_id: user_id) - true - end - def revoke_refresh_tokens(user_id:) raise ArgumentError, 'user_id is required.' unless user_id && !user_id.empty? @@ -211,8 +197,5 @@ def update_v2(user_id:, options: {}) ) end # rubocop:enable Metrics/AbcSize - - deprecate(:signout, :revoke_refresh_tokens, 2025, 1) - deprecate(:delete_device, :revoke_device, 2025, 1) end end diff --git a/tests/user_api_test.rb b/tests/user_api_test.rb index 120aa43..c3010d5 100644 --- a/tests/user_api_test.rb +++ b/tests/user_api_test.rb @@ -9,8 +9,7 @@ # This is a test suite for the Passage User API using the Test::Unit framework. class TestUserAPI < Test::Unit::TestCase - PassageClient = - Passage::Client.new(app_id: ENV['APP_ID'], api_key: ENV['API_KEY']) + PassageClient = Passage::Client.new(app_id: ENV['APP_ID'], api_key: ENV['API_KEY']) def setup @test_user = @@ -116,11 +115,6 @@ def test_list_devices assert_equal [], devices end - def test_signout - success = PassageClient.user.signout(user_id: @test_user.id) - assert_equal true, success - end - def teardown PassageClient.user.delete(user_id: @test_user.id) end From ea7d56eb708ac7bfb3ee3ecd88b62e883a979fd1 Mon Sep 17 00:00:00 2001 From: Chris Tran Date: Mon, 23 Dec 2024 16:20:47 -0600 Subject: [PATCH 4/6] feat!: update client ctor signature --- lib/passageidentity/client.rb | 40 ++++++++++++++--------------------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/lib/passageidentity/client.rb b/lib/passageidentity/client.rb index e3cc9c1..b53d964 100644 --- a/lib/passageidentity/client.rb +++ b/lib/passageidentity/client.rb @@ -2,7 +2,6 @@ require_relative 'auth' require_relative 'user_api' -require_relative 'error' require_relative 'version' module Passage @@ -16,32 +15,25 @@ module Passage class Client attr_reader :auth, :user - def initialize(app_id:, api_key: '', auth_strategy: COOKIE_STRATEGY) - @app_id = app_id - @api_key = api_key - - # check for valid auth strategy - unless [COOKIE_STRATEGY, HEADER_STRATEGY].include? auth_strategy - raise PassageError.new( - status_code: 400, - body: { - error: 'Invalid auth strategy', - code: 'invalid_argument' - } - ) + def initialize(app_id:, api_key:) + unless app_id && !app_id.empty? + raise ArgumentError, + 'A Passage App ID is required. Please include (app_id: YOUR_APP_ID, api_key: YOUR_API_KEY).' + end + unless api_key && !api_key.empty? + raise ArgumentError, + 'A Passage API key is required. Please include (app_id: YOUR_APP_ID, api_key: YOUR_API_KEY).' end - @auth_strategy = auth_strategy - - header_params = { 'Passage-Version' => "passage-ruby #{Passage::VERSION}" } - header_params['Authorization'] = "Bearer #{@api_key}" if @api_key != '' - - @req_opts = {} - @req_opts[:header_params] = header_params - @req_opts[:debug_auth_names] = ['header'] + req_opts = {} + req_opts[:header_params] = { + 'Passage-Version' => "passage-ruby #{Passage::VERSION}", + 'Authorization' => "Bearer #{api_key}" + } + req_opts[:debug_auth_names] = ['header'] - @auth = Passage::Auth.new(@app_id, @api_key, @auth_strategy) - @user = Passage::UserAPI.new(@app_id, @api_key) + @auth = Passage::Auth.new(app_id: app_id, req_opts: req_opts) + @user = Passage::UserAPI.new(app_id: app_id, req_opts: req_opts) end end end From 0c078caecb6b8e2b90ea312a88feb4f788462457 Mon Sep 17 00:00:00 2001 From: Chris Tran Date: Mon, 23 Dec 2024 16:21:31 -0600 Subject: [PATCH 5/6] feat!: update auth ctor signature --- lib/passageidentity/auth.rb | 15 +++------------ lib/passageidentity/client.rb | 3 --- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/lib/passageidentity/auth.rb b/lib/passageidentity/auth.rb index 1a6ccea..e65540d 100644 --- a/lib/passageidentity/auth.rb +++ b/lib/passageidentity/auth.rb @@ -8,22 +8,13 @@ module Passage # The Passage::Auth class provides methods for authenticating requests and tokens class Auth - def initialize(app_id, api_key, auth_strategy) - @app_cache = ActiveSupport::Cache::MemoryStore.new + def initialize(app_id:, req_opts:) @app_id = app_id - @api_key = api_key - @auth_strategy = auth_strategy + @req_opts = req_opts + @app_cache = ActiveSupport::Cache::MemoryStore.new fetch_jwks - header_params = { 'Passage-Version' => "passage-ruby #{Passage::VERSION}" } - header_params['Authorization'] = "Bearer #{@api_key}" if @api_key != '' - - @req_opts = {} - @req_opts[:header_params] = header_params - @req_opts[:debug_auth_names] = ['header'] - - @tokens_client = OpenapiClient::TokensApi.new @magic_links_client = OpenapiClient::MagicLinksApi.new end diff --git a/lib/passageidentity/client.rb b/lib/passageidentity/client.rb index b53d964..58ee817 100644 --- a/lib/passageidentity/client.rb +++ b/lib/passageidentity/client.rb @@ -5,9 +5,6 @@ require_relative 'version' module Passage - COOKIE_STRATEGY = 0 - HEADER_STRATEGY = 1 - EMAIL_CHANNEL = 'email' PHONE_CHANNEL = 'phone' From 5410bd944e00911d144775ae1c90b0ec0ecd6cd8 Mon Sep 17 00:00:00 2001 From: Chris Tran Date: Mon, 23 Dec 2024 16:23:23 -0600 Subject: [PATCH 6/6] feat!: update user ctor signature --- lib/passageidentity/user_api.rb | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/lib/passageidentity/user_api.rb b/lib/passageidentity/user_api.rb index 70eee39..06050a4 100644 --- a/lib/passageidentity/user_api.rb +++ b/lib/passageidentity/user_api.rb @@ -6,18 +6,13 @@ module Passage # The UserAPI class provides methods for interacting with Passage Users class UserAPI # rubocop:disable Metrics/AbcSize - def initialize(app_id, api_key) + def initialize(app_id:, req_opts:) @app_id = app_id - @api_key = api_key + @req_opts = req_opts + @user_client = OpenapiClient::UsersApi.new @user_device_client = OpenapiClient::UserDevicesApi.new - - header_params = { 'Passage-Version' => "passage-ruby #{Passage::VERSION}" } - header_params['Authorization'] = "Bearer #{@api_key}" if @api_key != '' - - @req_opts = {} - @req_opts[:header_params] = header_params - @req_opts[:debug_auth_names] = ['header'] + @tokens_client = OpenapiClient::TokensApi.new end def get(user_id:) @@ -160,8 +155,7 @@ def revoke_refresh_tokens(user_id:) raise ArgumentError, 'user_id is required.' unless user_id && !user_id.empty? begin - tokens_client = OpenapiClient::TokensApi.new - tokens_client.revoke_user_refresh_tokens(@app_id, user_id, @req_opts) + @tokens_client.revoke_user_refresh_tokens(@app_id, user_id, @req_opts) rescue Faraday::Error => e raise PassageError.new( status_code: e.response[:status],