1

I am requesting an access token from FHIR sandbox for a standalone web app (no client secret). On my redirect page I collect code and state from URL, and then fetch access token.

export default function Redirect() {
  // const router = useRouter();

  const searchParams = useSearchParams();

  useEffect(() => {
    const code = searchParams.get("code");
    const state = searchParams.get("state");

    const clientId = "ea9b08eb-030c-41e5-b24b-e4b95ce068e5";
    const redirectUri = "http://localhost:3000/redirect";

    if (code) {
      console.log("code: ", code);
    }

    if (state) {
      console.log("state: ", state);
    }

    if (code && state) {
      const body = `grant_type=${encodeURIComponent(
        "authorization_code"
      )}&code=${encodeURIComponent(code)}&redirect_uri=${encodeURIComponent(
        redirectUri
      )}&client_id=${encodeURIComponent(clientId)}`;

      fetch("https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token", {
        method: "POST",
        headers: {
          "Content-Type": "application/x-www-form-urlencoded",
        },
        body: body,
      })
        .then((response) => {
          response.json().then((data) => {
            if (!response.ok) {
              console.error("Response Error Data: ", data);
              throw new Error(`HTTP error! Status: ${response.status}`);
            }
            console.log("Access Token Data: ", data);
          });
        })
        .catch((error) => {
          console.error("Error:", error);
        });
    }
  }, [searchParams]);

I get access token in console.log, but error of invalid_grant

I was expecting access token which I receive...

{
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ1cm46b2lkOmZoaXIiLCJjbGllbnRfaWQiOiJlYTliMDhlYi0wMzBjLTQxZTUtYjI0Yi1lNGI5NWNlMDY4ZTUiLCJlcGljLmVjaSI6InVybjplcGljOk9wZW4uRXBpYy1jdXJyZW50IiwiZXBpYy5tZXRhZGF0YSI6InRiTjlBMk1iT090OXlaZXM5S2ZZY3ZfdFB4XzFNRWQwaktTRlU4YXhnUEdrX2owRzVvV0xibmlOWVg0TFNHT090YnN4OENUVl95d1NSeDhQckNyd2Z0WlZvb0d6cEhIWElfTVU5LUl2bEdoNldzNnhYVXE3RmFIZEEwSXVodDdmIiwiZXBpYy50b2tlbnR5cGUiOiJhY2Nlc3MiLCJleHAiOjE3MjAwNDE2NDcsImlhdCI6MTcyMDAzODA0NywiaXNzIjoidXJuOm9pZDpmaGlyIiwianRpIjoiMmY0M2U2NDItMTc0OS00YjM4LWJlOGQtMjYxOGY4OGMwODgxIiwibmJmIjoxNzIwMDM4MDQ3LCJzdWIiOiJlM01CWENPbWNvTEtsN2F5TEQ1MUFXQTMifQ.OLeMi-B9QWR30fMLHJlZblEUKKYZe5UEnUgvD98Gmzq2B50m1Fofpz_ecVoS0sIGba75eFLw2JX6frEbhN1IPnQAybG0PV8aT1gM7RUSmERVRaw_ZOKJ3e6m8QtiBVbD8yjUH_UIRcMBhXJi3XHNf0KS0YqC1NcYFV8zfJ_xaUvYf4XrgUVAg-5CTNeElocYJ5cH67gn6TMxFOyxSgNEqBECNX-cMAHKAsSTLeUZLaiTOxOHLrWArSW__OuuxK5FGrlS6tHP0qKz1qX2SZUGnfoYDlR5BwDkx87W425aK_15r_7ZcMhxXCsom69gJvp46qAo8X8a1VYVP6ANKOetpg",
    "token_type": "Bearer",
    "expires_in": 3600,
    "scope": "system/DynamicClient.register user/Binary.read user/CarePlan.read user/CareTeam.read user/Communication.read user/Condition.read",
    "state": "abc123"
}

But I also get...

{
    "error": "invalid_grant",
    "error_description": null
}

Can somebody please hep me understand?

2
  • While this is for connecting to a sandbox, it's generally best to avoid posting access tokens, client IDs, and other values that would allow someone to make API calls, potentially maliciously, using your app. Commented Jul 4, 2024 at 4:28
  • Thanks. I thought it was OK bc of being in sandbox. I get the point. -lance Commented Jul 4, 2024 at 6:27

2 Answers 2

1

At first glance, it appears your app is set up for dynamic client registration. Your code doesn't depict that full process, however. The code shows obtaining the initial access token with the pre-assigned client ID, but this access token is for one-time use only in order to register the dynamic client and obtain the correct client ID (and eventually, access token). If you do want this to be a dynamic client, the details for the remaining steps are here.

Sign up to request clarification or add additional context in comments.

Comments

0

Try checking if there are any optional parameters as well, like code_verifier or similar. I faced a similar issue but later tried adding the optional parameter, which worked for me.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.