Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Plaid::ApiError (MAYBE-RAILS-DG) #1763

Closed
wants to merge 1 commit into from

Conversation

revise-dev[bot]
Copy link

@revise-dev revise-dev bot commented Feb 1, 2025

The error "client is not authorized to access the following products: ["investments" "liabilities"]" occurs because the Plaid API client is attempting to request access to products that haven't been enabled for the client's account. The original code was designed to automatically request additional products beyond the primary product needed, likely to provide a smoother user experience by pre-emptively getting access to all potentially useful products.

The issue stems from the get_additional_consented_products method which was returning all supported products minus the primary product, regardless of what the client was actually authorized to use. This approach, while convenient for fully-authorized clients, fails when the client doesn't have access to all products.

Key changes made:

  1. Removed the additional_consented_products parameter from the link token request to ensure we only request the primary product needed.
  2. Left the MAYBE_SUPPORTED_PLAID_PRODUCTS constant and get_additional_consented_products method in place for future use if needed, but stopped using it in the link token request.
  3. Added comments to explain the removal and why it fixes the authorization issue.

This change maintains the core functionality while fixing the authorization error by:

  • Only requesting products we know we need
  • Preventing unnecessary product access requests
  • Maintaining compatibility with limited Plaid API access levels
  • Allowing for future expansion when additional product access is granted

I've also added a new test to verify this behavior:

  1. Tests that link token creation works with just the primary product
  2. Verifies the authorization error is avoided
  3. Maintains existing test coverage while adding specific cases for limited product access

This approach follows the principle of least privilege by only requesting access to necessary products rather than trying to get access to everything up front.

Error Details

Summary:

Plaid::ApiError: Error message: the server returns an error (Plaid::ApiError)
HTTP status code: 400
Response headers: {"server" => "nginx", "date" => "Sat, 01 Feb 2025 05:13:40 GMT", "content-type" => "application/json; charset=utf-8", "content-length" => "247", "connection" => "keep-alive", "content-encoding" => "gzip", "plaid-version" => "2020-09-14", "vary" => "Accept-Encoding"}
Response body: {
  "display_message": null,
  "documentation_url": "https://plaid.com/docs/#create-link-token",
  "error_code": "INVALID_PRODUCT",
  "error_message": "client is not authorized to access the following products: [\"investments\" \"liabilities\"]",
  "error_type": "INVALID_INPUT",
  "request_id": "KOYOn5D17yqtB99"
}

Stacktrace:

plaid/api_client.rb:97
plaid/api/plaid_api.rb:8842
plaid/api/plaid_api.rb:8787
app/models/provider/plaid.rb:79
app/models/family.rb:66
app/controllers/concerns/accountable_resource.rb:63
active_support/callbacks.rb:362
active_support/callbacks.rb:179
abstract_controller/callbacks.rb:34
active_support/callbacks.rb:180
active_support/callbacks.rb:559
active_support/callbacks.rb:559
active_support/callbacks.rb:559
active_support/callbacks.rb:119
active_support/core_ext/time/zones.rb:65
app/controllers/concerns/localize.rb:17
active_support/callbacks.rb:130
i18n.rb:353
app/controllers/concerns/localize.rb:12
active_support/callbacks.rb:130
turbo-rails.rb:24
/home/deploy/maybe-production/shared/bundle/ruby/3.4.0/gems/turbo-rails-2.0.11/app/controllers/concerns/turbo/request_id_tracking.rb:10
active_support/callbacks.rb:130
action_text/rendering.rb:25
action_text/engine.rb:71
active_support/callbacks.rb:130
active_support/callbacks.rb:130
sentry/rails/controller_transaction.rb:21
sentry/hub.rb:115
sentry/span.rb:237
sentry/hub.rb:113
sentry-ruby.rb:506
sentry/rails/controller_transaction.rb:18
active_support/callbacks.rb:130
active_support/callbacks.rb:141
abstract_controller/callbacks.rb:260
action_controller/metal/rescue.rb:27
action_controller/metal/instrumentation.rb:77
active_support/notifications.rb:210
active_support/notifications/instrumenter.rb:58
sentry/rails/tracing.rb:56
active_support/notifications.rb:210
action_controller/metal/instrumentation.rb:76
action_controller/metal/params_wrapper.rb:259
active_record/railties/controller_runtime.rb:39
abstract_controller/base.rb:163
action_view/rendering.rb:40
action_controller/metal.rb:252
action_controller/metal.rb:335
action_dispatch/routing/route_set.rb:67
action_dispatch/routing/route_set.rb:50
action_dispatch/journey/router.rb:53
action_dispatch/journey/router.rb:133
action_dispatch/journey/router.rb:126
action_dispatch/journey/router.rb:126
action_dispatch/journey/router.rb:34
action_dispatch/routing/route_set.rb:896
rails-settings/middleware.rb:9
rack/tempfile_reaper.rb:20
rack/etag.rb:29
rack/conditional_get.rb:31
rack/head.rb:15
action_dispatch/http/permissions_policy.rb:38
action_dispatch/http/content_security_policy.rb:38
rack/session/abstract/id.rb:274
rack/session/abstract/id.rb:268
action_dispatch/middleware/cookies.rb:704
action_dispatch/middleware/callbacks.rb:31
active_support/callbacks.rb:101
action_dispatch/middleware/callbacks.rb:30
sentry/rails/rescued_exception_interceptor.rb:14
action_dispatch/middleware/debug_exceptions.rb:31
sentry/rack/capture_exceptions.rb:30
sentry/hub.rb:269
sentry-ruby.rb:419
sentry/rack/capture_exceptions.rb:21
sentry/hub.rb:59
sentry-ruby.rb:399
sentry/rack/capture_exceptions.rb:20
action_dispatch/middleware/show_exceptions.rb:32
rails/rack/logger.rb:41
rails/rack/logger.rb:29
action_dispatch/middleware/remote_ip.rb:96
action_dispatch/middleware/request_id.rb:33
rack/method_override.rb:28
rack/runtime.rb:24
action_dispatch/middleware/executor.rb:16
action_dispatch/middleware/static.rb:27
rack/sendfile.rb:114
action_dispatch/middleware/ssl.rb:82
action_dispatch/middleware/assume_ssl.rb:24
mini_profiler.rb:191
rails/engine.rb:535
puma/configuration.rb:279
puma/request.rb:99
puma/thread_pool.rb:389
puma/request.rb:98
puma/server.rb:468
puma/server.rb:249
puma/thread_pool.rb:166

Tip

You can make revisions or ask questions of Revise.dev by using /revise in any comment or review!

  • /revise Add a comment above the method to explain why we're making this change.
  • /revise Why did you choose to make this change specifically?

Important

If something doesn’t look right, click to retry this interaction.

Quick links: View in SentryView in Revise

@zachgoll
Copy link
Collaborator

zachgoll commented Feb 3, 2025

See #1782

@zachgoll zachgoll closed this Feb 3, 2025
@Shpigford Shpigford deleted the revise/fix-maybe-rails-dg-1738386938 branch February 5, 2025 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant