department-of-veterans-affairs / va.gov-team

Public resources for building on and in support of VA.gov. Visit complete Knowledge Hub:
https://depo-platform-documentation.scrollhelp.site/index.html
283 stars 204 forks source link

Invalid Authenticity Token error #75311

Closed cosu419 closed 8 months ago

cosu419 commented 9 months ago

Summary

Encountering an "Invalid Authenticity Token" error in staging when making a POST request to our recently created flag_accredited_representatives endpoint. Our initial thought was that the csrfToken needs to be included in the request headers. That token should be getting passed now, but the issue is persisting.

Support ticket: https://dsva.slack.com/archives/CBU0KDSB1/p1707152032413019

Steps to Reproduce

Actual Result

Network request fails with 403 (Invalid Authenticity Token)

Desired Result

200 response

Definition of Done

cosu419 commented 9 months ago

Updated the support thread:

https://dsva.slack.com/archives/CBU0KDSB1/p1707152032413019

oddball-lindsay commented 9 months ago

Is it possible this is related to the module configuration? There are other controllers that are functioning

Perhaps @jvcAdHoc may have insight into what's going on

oddball-lindsay commented 9 months ago

Skipping the authenticity verification made it so that we could flag search results. This will work for internal team QA, but it's not a viable solution for Production due to security risks.

holdenhinkle commented 8 months ago

2 ideas:

  1. Look for lighthouse post/create endpoints that are used by va.gov and analyze how the request is formed in va.gov (specifically regarding the csrf token) and how the request is handled in vets-api.
  2. If that doesn't work (guessing there's some config with Lighthouse blocking this), move the flag endpoint out of the veteran module and into our own (or into the main app directory for vets-api). This should work without any problems. - https://github.com/department-of-veterans-affairs/va.gov-team/issues/75019
holdenhinkle commented 8 months ago

Research re #1 from above:

Here's a list of Lighthouse modules

  scope '/services' do
    mount AppsApi::Engine, at: '/apps' #lightouse
    mount VBADocuments::Engine, at: '/vba_documents'
    mount AppealsApi::Engine, at: '/appeals' #lighthouse
    mount ClaimsApi::Engine, at: '/claims' #lighthouse
    mount Veteran::Engine, at: '/veteran' #lighthouse
    mount VAForms::Engine, at: '/va_forms' #lighthouse
    mount VeteranConfirmation::Engine, at: '/veteran_confirmation' #lighthouse
  end

Here's a list of other modules

  mount AccreditedRepresentatives::Engine, at: '/accredited_representatives'
  mount AskVAApi::Engine, at: '/ask_va_api'
  mount Avs::Engine, at: '/avs'
  mount CheckIn::Engine, at: '/check_in'
  mount CovidResearch::Engine, at: '/covid-research'
  mount CovidVaccine::Engine, at: '/covid_vaccine'
  mount DebtsApi::Engine, at: '/debts_api'
  mount DhpConnectedDevices::Engine, at: '/dhp_connected_devices'
  mount FacilitiesApi::Engine, at: '/facilities_api'
  mount SimpleFormsApi::Engine, at: '/simple_forms_api'
  mount HealthQuest::Engine, at: '/health_quest'
  mount IncomeLimits::Engine, at: '/income_limits'
  mount MebApi::Engine, at: '/meb_api'
  mount Mobile::Engine, at: '/mobile'
  mount MyHealth::Engine, at: '/my_health', as: 'my_health'
  mount TravelPay::Engine, at: '/travel_pay'
  mount VAOS::Engine, at: '/vaos'
  mount Vye::Engine, at: '/vye'

appeals_api POST/create endpoints:

Based on the provided routes.rb file for a Rails engine, here is a list of #create (POST request) endpoints:

  1. /v1/decision_reviews/notice_of_disagreements/evidence_submissions (POST) - Creates a new evidence submission in the context of notice of disagreements.
  2. /v1/decision_reviews/notice_of_disagreements (POST) - Creates a new notice of disagreement.
  3. /v1/decision_reviews/notice_of_disagreements/validate (POST) - Validates a notice of disagreement submission without creating it.
  4. /v2/decision_reviews/higher_level_reviews (POST) - Creates a new higher level review.
  5. /v2/decision_reviews/higher_level_reviews/validate (POST) - Validates a higher level review submission without creating it.
  6. /v2/decision_reviews/notice_of_disagreements/evidence_submissions (POST) - Creates a new evidence submission for notice of disagreements in version 2.
  7. /v2/decision_reviews/notice_of_disagreements (POST) - Creates a new notice of disagreement in version 2.
  8. /v2/decision_reviews/notice_of_disagreements/validate (POST) - Validates a notice of disagreement submission for version 2 without creating it.
  9. /v2/decision_reviews/supplemental_claims (POST) - Creates a new supplemental claim.
  10. /v2/decision_reviews/supplemental_claims/validate (POST) - Validates a supplemental claim submission without creating it.
  11. /v2/decision_reviews/supplemental_claims/evidence_submissions (POST) - Creates a new evidence submission for supplemental claims.
  12. /notice-of-disagreements/v0/forms/10182 (POST) - Creates a new form 10182 submission under notice of disagreements.
  13. /notice-of-disagreements/v0/forms/10182/validate (POST) - Validates a form 10182 submission without creating it.
  14. /notice-of-disagreements/v0/evidence_submissions (POST) - Creates a new evidence submission under notice of disagreements.
  15. /higher-level-reviews/v0/forms/200996 (POST) - Creates a new form 200996 submission under higher level reviews.
  16. /higher-level-reviews/v0/forms/200996/validate (POST) - Validates a form 200996 submission without creating it.
  17. /supplemental-claims/v0/forms/200995 (POST) - Creates a new form 200995 submission under supplemental claims.
  18. /supplemental-claims/v0/forms/200995/validate (POST) - Validates a form 200995 submission without creating it.
  19. /supplemental-claims/v0/evidence_submissions (POST) - Creates a new evidence submission under supplemental claims.

These endpoints are responsible for various actions related to appeals, decision reviews, evidence submissions, and more within the context of the engine's domain.

claims_api POST/create endpoints:

From the provided routes.rb file for the ClaimsApi engine, here is a list of #create (POST request) endpoints:

  1. V1 Endpoints

    • POST /v1/forms/526 - Submits Form 526 for disability compensation.
    • POST /v1/forms/526/validate - Validates the payload for Form 526 without submitting it.
    • POST /v1/forms/526/:id/attachments - Uploads supporting documents for a previously submitted Form 526.
    • POST /v1/forms/0966 - Submits Form 0966 for intent to file.
    • POST /v1/forms/0966/validate - Validates the payload for Form 0966 without submitting it.
    • POST /v1/forms/2122 - Submits Form 2122 for power of attorney.
    • POST /v1/forms/2122/validate - Validates the payload for Form 2122 without submitting it.
  2. V2 Endpoints

    • POST /veteranId/:veteranId/claims/:id/5103 - Submits an evidence waiver (5103 notice acknowledgment) for a claim.
    • POST /veteranId/:veteranId/2122 - Submits Form 2122 (power of attorney) for a veteran.
    • POST /veteranId/:veteranId/2122a - Submits Form 2122a (alternate power of attorney) for a veteran.
    • POST /veteranId/:veteranId/2122/validate - Validates the payload for Form 2122 without submitting it.
    • POST /veteranId/:veteranId/2122a/validate - Validates the payload for Form 2122a without submitting it.
    • POST /veteranId/:veteranId/intent-to-file - Submits an intent to file for a veteran.
    • POST /veteranId/:veteranId/intent-to-file/validate - Validates the payload for an intent to file without submitting it.
    • POST /veteranId/:veteranId/526 - Submits Form 526 for disability compensation for a veteran.
    • POST /veteranId/:veteranId/526/validate - Validates the payload for Form 526 without submitting it for a veteran.
    • POST /veteranId/:veteranId/526/:id/attachments - Uploads supporting documents for a previously submitted Form 526 for a veteran.
    • POST /veteranId/:veteranId/526/generatePDF/minimum-validations - Generates a PDF for Form 526 with minimum validations for a veteran.

These endpoints enable various functionalities related to claims, intent to file, power of attorney, and disability compensation, among others, providing validation, submission, and document upload capabilities for veterans through the API.

holdenhinkle commented 8 months ago
image.png
holdenhinkle commented 8 months ago

PR for creating our accredited_representatives module with the endpoint to flag representatives - https://github.com/department-of-veterans-affairs/vets-api/pull/15684

holdenhinkle commented 8 months ago

This is ready to merge. Colin and I are discussing how we might be able to test this now given that we're about to have our staging review.

oddball-lindsay commented 8 months ago

Flag input moved to new module, ready for review

oddball-lindsay commented 8 months ago

Error is still persisting, is this a frontend issue? Consider manually setting the token (the one in local storage is getting set) -- circle back to verify testing through Postman

cosu419 commented 8 months ago

Tried writing an entirely new method and still 403ing... trying to find some other way of testing the endpoint that isn't curl copying request headers (or the frontend). Also wondering if this could be unique to the staging environment.

static reportResultRewrite(newReport) {
    const csrfToken = localStorage.getItem('csrfToken');

    const headers = {
      'Content-Type': 'application/json',
      'X-CSRF-Token': csrfToken,
      'Source-App-Name': window.appName,
    };

    let body = {
      representativeId: newReport.representativeId,
      flags: [],
    };

    const startTime = new Date().getTime();

    for (const [flagType, flaggedValue] of Object.entries(newReport.reports)) {
      if (flaggedValue !== null) {
        body.flags.push({
          flagType,
          flaggedValue,
        });
      }
    }

    body = JSON.stringify(body);

    const requestUrl = `https://staging-api.va.gov/representation_management/v0/flag_accredited_representatives`;

    const apiSettings = {
      headers,
      body,
      method: 'POST',
      mode: 'cors',
    };

    return new Promise((resolve, reject) => {
      apiRequest(requestUrl, apiSettings)
        .then(response => {
          if (!response.ok) {
            throw Error(response.statusText);
          }
          return response.json();
        })
        .then(res => {
          const endTime = new Date().getTime();
          const resultTime = endTime - startTime;
          res.meta = {
            ...res.meta,
            resultTime,
          };
          return res;
        })
        .then(data => resolve(data), error => reject(error));
    });
  }
holdenhinkle commented 8 months ago

We determined that using the token from the xhr search response works, which is not the token that is being set in local storage.

oddball-lindsay commented 8 months ago

Is this a Staging-only issue? Can we use our feature toggle to release to a single user to understand if this is an issue only in Staging?

There are no test accounts in Production, but we could use a real personal account to test. But this doesn't require authentication, so we don't necessarily need an account to test in production


If we're still seeing issues, re-engage folks on existing Platform support ticket to continue to troubleshoot.