'Creating JWT for Epic backend authentication
I am attempting to connect to the Epic sandbox environment via a backend app. I have been following this guide but I think I am running into an issue with my JWT signature. Here is the code I am using to generate the token
class CreateJwt
{
public static string? Token { get; set; }
public static void Jwt()
{
try
{
// reading the content of a private key PEM file
string privateKeyPem = File.ReadAllText("./private_epic_backend_key.pem");
// keeping only the payload of the key
privateKeyPem = privateKeyPem.Replace("-----BEGIN PRIVATE KEY-----", "");
privateKeyPem = privateKeyPem.Replace("-----END PRIVATE KEY-----", "");
byte[] privateKeyRaw = Convert.FromBase64String(privateKeyPem);
// creating the RSA key
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.ImportPkcs8PrivateKey(new ReadOnlySpan<byte>(privateKeyRaw), out _);
RsaSecurityKey rsaSecurityKey = new RsaSecurityKey(provider);
// Generating the token
var now = DateTime.UtcNow;
var claims = new[] {
new Claim(JwtRegisteredClaimNames.Iss, "1a467f07-8a84-4e25-a493-4ba9d5ef9054"),
new Claim(JwtRegisteredClaimNames.Sub, "1a467f07-8a84-4e25-a493-4ba9d5ef9054")
};
var handler = new JwtSecurityTokenHandler();
var token = new JwtSecurityToken
(
"1a467f07-8a84-4e25-a493-4ba9d5ef9054",
"https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token",
claims,
now.AddMilliseconds(-30),
now.AddMinutes(4),
new SigningCredentials(rsaSecurityKey, SecurityAlgorithms.RsaSha384)
);
// handler.WriteToken(token) returns the token ready to send
Token = handler.WriteToken(token);
Console.WriteLine(Token);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Console.WriteLine(
new System.Diagnostics.StackTrace().ToString()
);
}
}
}
The reason I think the issue is with the signature is because when I load the token into JWT.IO I get an "invalid signature" response. Then here is the code where I am sending it.
class GetBearerToken
{
private static readonly HttpClient client = new HttpClient();
public static string? Bearer { get; set; }
public async static Task Authorize()
{
try
{
var values = new Dictionary<string, string>
{
{ "grant_type", "client_credentials" },
{ "client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" },
{ "client_assertion", CreateJwt.Token }
};
var content = new FormUrlEncodedContent(values);
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
var requeststring = await content.ReadAsStringAsync();
Console.WriteLine(requeststring);
var response = await client.PostAsync("https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token", content);
var responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine("response from post");
Console.WriteLine(responseString);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
Console.WriteLine(
new System.Diagnostics.StackTrace().ToString()
);
}
}
}
This looks exactly like what they are expecting according to the documentation Epic provides, but I am getting a return that states
"error": "invalid_client", "error_description": null
Epic provides a troubleshooting document that goes over this particular error, but it seems to be more of a catchall error. I have gone through the troubleshooting steps twice now and I am still not getting past this error.
Any help would be greatly appreciated.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
