Reputation: 11
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?
Upvotes: 1
Views: 253
Reputation: 11097
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.
Upvotes: 0
Reputation: 987
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.
Upvotes: 1