diff --git a/README.md b/README.md
index e7f4db1..78649d3 100644
--- a/README.md
+++ b/README.md
@@ -101,7 +101,7 @@ For a complete implementation of GitHub App authentication strategies, see [`@oc
string
- Required. Content of the *.pem file you downloaded from the app’s about page. You can generate a new private key if needed. Make sure to preserve the line breaks.
+ Required. Content of the *.pem file you downloaded from the app’s about page. You can generate a new private key if needed. Make sure to preserve the line breaks. If your private key contains escaped newlines (`\\n`), they will be automatically replaced with actual newlines.
|
diff --git a/index.js b/index.js
index eb45a22..c0dcc07 100644
--- a/index.js
+++ b/index.js
@@ -12,6 +12,10 @@ export default async function githubAppJwt({
privateKey,
now = Math.floor(Date.now() / 1000),
}) {
+ // Private keys are often times configured as environment variables, in which case line breaks are escaped using `\\n`.
+ // Replace these here for convenience.
+ const privateKeyWithNewlines = privateKey.replace(/\\n/g, '\n');
+
// When creating a JSON Web Token, it sets the "issued at time" (iat) to 30s
// in the past as we have seen people running situations where the GitHub API
// claimed the iat would be in future. It turned out the clocks on the
@@ -26,7 +30,7 @@ export default async function githubAppJwt({
};
const token = await getToken({
- privateKey,
+ privateKey: privateKeyWithNewlines,
payload,
});
diff --git a/test/node.test.js b/test/node.test.js
index 5f6c13b..18a5d34 100644
--- a/test/node.test.js
+++ b/test/node.test.js
@@ -162,3 +162,18 @@ test("Include the time difference in the expiration and issued_at field", async
t.is(resultPayload.exp, 580);
t.is(resultPayload.iat, -20);
});
+
+test("Replace escaped line breaks with actual linebreaks", async (t) => {
+ MockDate.set(0);
+
+ const result = await githubAppJwt({
+ id: APP_ID,
+ privateKey: PRIVATE_KEY_PKCS8.replace(/\n/g, "\\n"),
+ });
+
+ t.deepEqual(result, {
+ appId: APP_ID,
+ expiration: 570,
+ token: BEARER,
+ });
+});