Error: error:1E08010C:DECODER routines::unsupported with Google auth library
Asked Answered
A

10

44

I've recently ran into this error with the google cloud storage SDK on Node.js. I know for a fact that this worked in the past without any changes, but I haven't touched the code in a while and might be wrong.

Here's the error itself:

Error: error:1E08010C:DECODER routines::unsupported
    at Sign.sign (node:internal/crypto/sig:131:29)
    at Object.sign (node_modules/jwa/index.js:152:45)
    at Object.jwsSign [as sign] (node_modules/jws/lib/sign-stream.js:32:24)
    at GoogleToken.requestToken (node_modules/gtoken/build/src/index.js:232:31)
    at GoogleToken.getTokenAsyncInner (node_modules/gtoken/build/src/index.js:166:21)
    at GoogleToken.getTokenAsync (node_modules/gtoken/build/src/index.js:145:55)
    at GoogleToken.getToken (node_modules/gtoken/build/src/index.js:97:21)
    at JWT.refreshTokenNoCache (node_modules/google-auth-library/build/src/auth/jwtclient.js:172:36)
    at JWT.refreshToken (node_modules/google-auth-library/build/src/auth/oauth2client.js:153:24)
    at JWT.getRequestMetadataAsync (node_modules/google-auth-library/build/src/auth/oauth2client.js:298:28) {
  library: 'DECODER routines',
  reason: 'unsupported',
  code: 'ERR_OSSL_UNSUPPORTED'
}

The code that throws this error is the following:

const credentials = {
    type: process.env.TYPE,
    project_id: process.env.PROJECT_ID,
    private_key_id: process.env.PRIVATE_KEY_ID,
    private_key: process.env.PRIVATE_KEY,
    client_email: process.env.CLIENT_EMAIL,
    client_id: process.env.CLIENT_ID,
    auth_uri: process.env.AUTH_URI,
    token_uri: process.env.TOKEN_URI,
    auth_provider_x509_cert_url: process.env.AUTH_PROVIDER_X509_CERT_URL,
    client_x509_cert_url: process.env.CLIENT_X509_CERT_URL,
  };

  const storage = new Storage({
    credentials,
  });
  if (!req.file) {
    logger('POST /profile_image', logLevels.error, 'No file uploaded!');
    ResponseError.badRequest(res);
  }
  const bucketName = process.env.BUCKET_NAME;
  const bucket = storage.bucket(bucketName);
  const fileName = `profile_pics/${req.user}/${req.file.originalname}`;
  const file = bucket.file(fileName);
  const stream = file.createWriteStream({
    metadata: {
      contentType: req.file.mimetype,
    },
  });
  stream.on('error', (err) => {
    console.error('Error pushing the picture: ', err); <--- error
    throw err;
  });
  stream.on('finish', () => {
    return file.makePublic().then(async () => {
       ...
      })
  });
  stream.end(req.file.buffer);

The process.env contains all the right values, I've made sure to try with a new private key but same error. Has anyone seen this one before?

TIA!

Alkylation answered 19/10, 2022 at 20:35 Comment(4)
1) Do not store service accounts in environment variables. 2) If you do, do not break the service account into pieces. Base64 encode the entire service account, store it in a variable, and then Base64 decode it when required. 3) Your code is failing because the client is being set up with bad credentials. Most likely a corrupted private key.Brittaneybrittani
Was the issue a corrupted private key?Brittaneybrittani
I cannot say. I encoded as you advised me to and the problem seemed to have disappeared. I'm beginning to think that maybe the breaking down into pieces part may have corrupted the individual keys.Alkylation
I am fairly confident you corrupted the private_key field based on the stack trace.Brittaneybrittani
P
25

Answering this as community wiki. As mentioned above in comments by John Hanley

  1. Do not store service accounts in environment variables.
  2. If you do, do not break the service account into pieces. Base64 encode the entire service account, store it in a variable, and then Base64 decode it when required.
  3. Your code is failing because the client is being set up with bad credentials. Most likely a corrupted private key.
Platitudinous answered 19/10, 2022 at 20:36 Comment(2)
informative, but not helpfulCheckroom
This is the way. See for example: github.com/orgs/vercel/discussions/219#discussioncomment-128702Rustin
L
65

I got same issue and fixed it by replacing raw \n character with the newline character. Probably you get the key as raw data from your environment and \n character in the raw is not treated as a newline character. You can try this:

    private_key: process.env.PRIVATE_KEY.split(String.raw`\n`).join('\n'),

Leandraleandre answered 3/12, 2022 at 15:20 Comment(4)
In local i was able to use the .env normally, but when i deployed to cloud run it failed. This worked for me in local and in cloud run, but why this happend? Can you explain it to me please? I tried to see what it does by printing it in console, but i cant see differenceSuperconductivity
I had to downgrade to node 16.16.0 and implement this: process.env.PRIVATE_KEY.split(String.raw\n).join('\n'), both changes were necessary in my caseEveevection
or .replace(/\\n/g, '\n')Dosimeter
@Superconductivity - realizing this because for example I store this env variable in secret manager - there are new line segments that get added in (I presume) - depending how your code editor is set up it could be replicated, but yes the code above worked for both environments as without it, it was only working locallyGlendaglenden
P
25

Answering this as community wiki. As mentioned above in comments by John Hanley

  1. Do not store service accounts in environment variables.
  2. If you do, do not break the service account into pieces. Base64 encode the entire service account, store it in a variable, and then Base64 decode it when required.
  3. Your code is failing because the client is being set up with bad credentials. Most likely a corrupted private key.
Platitudinous answered 19/10, 2022 at 20:36 Comment(2)
informative, but not helpfulCheckroom
This is the way. See for example: github.com/orgs/vercel/discussions/219#discussioncomment-128702Rustin
A
9

you can base64 encode the entire service account JSON and store it in an environment variable. Here's how you can adjust your code accordingly:

  1. Base64 Encode the Service Account JSON using any online tools ex. https://www.base64encode.org/

  2. Store the Base64-encoded String in Environment Variable

    BASE64_ENCODED_SERVICE_ACCOUNT=your-base64-encoded-service-account

  3. Decode it in your code and use it like that

const base64EncodedServiceAccount = process.env.BASE64_ENCODED_SERVICE_ACCOUNT;
const decodedServiceAccount = Buffer.from(base64EncodedServiceAccount, 'base64').toString('utf-8');
const credentials = JSON.parse(decodedServiceAccount);
Atomics answered 15/1, 2024 at 9:28 Comment(2)
This solution worked for me, all the others failed for context I am using Nextjs other solution worked locally but not when deployed on Vercel except this oneLifeless
Thanks for the solution. I can see many answers who suggest updating the key using regex but that's not the right way.Bulldoze
C
6

I think you need to check the .env file and make sure you don't have any extra characters added to the private key for example a comma "," at the end. that's the reason i was getting this error for me .

Contraception answered 29/6, 2023 at 1:13 Comment(2)
Yep, for me there was an extra apostrophe at the beginning of the key value.Handoff
You just saved me hours, I never would have spotted that.Hejira
D
5

make both keys in .env to be one line only (the only way that worked for me)

PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\n<PUBLIC KEY>\n-----END PUBLIC KEY-----"
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n<PRIVATE KEY>\n-----END RSA PRIVATE KEY-----"
Despite answered 19/12, 2023 at 2:8 Comment(1)
in my case it was about missing quotation marksBrasilein
S
2

The following was the only solution that worked for me

private_key: process.env.PRIVATE_KEY.replace(/\\n/gm, "\n"),
Sismondi answered 19/1, 2024 at 9:54 Comment(0)
D
1

If you have recently upgraded your openssl to version 3, you may have to enable legacy certs in the /etc/ssl/openssl.cnf file:

   openssl_conf = openssl_init
   
   [openssl_init]
   providers = provider_sect
   
   [provider_sect]
   default = default_sect
   legacy = legacy_sect
   
   [default_sect]
   activate = 1
   
   [legacy_sect]
   activate = 1

This information is from the OpenSSL WIKI

Delciedelcina answered 12/11, 2022 at 20:59 Comment(0)
T
0

On your local env you should have it in on one line and with "": PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\n your key \n-----END PUBLIC KEY-----"

And on deployed env you should have it without "": PUBLIC_KEY=-----BEGIN PUBLIC KEY-----\n your key \n-----END PUBLIC KEY-----

Also, on public key variable put: .replace(/\\n/g,"\n")

This worked for me.

Trill answered 26/2, 2024 at 11:31 Comment(0)
D
0

This will solve the issue:

While reading the env variable do it this way.

const credential = JSON.parse(
  (process.env.GOOGLE_PRIVATE_KEY as string).toString().replace(/\n/g,"")
);

key: credential.private_key,

The private key must be

GOOGLE_PRIVATE_KEY='{"---"}' // in .env.local

But while putting the key to some hosting platform (vercel in my case) make it

GOOGLE_PRIVATE_KEY={"---"} // in vercel environment variable value
Dia answered 19/4, 2024 at 12:47 Comment(0)
P
0

For me, the issue was that pasting this key inside of the AWS Lamda env variable removed the formatting. I added this logic to re-create the formatting:

const privateKey = process.env.GITHUB_PRIVATE_KEY.replace(/\s/g, '')
    .replace(
      /-----BEGINRSAPRIVATEKEY-----/,
      '-----BEGIN RSA PRIVATE KEY-----\n'
    )
    .replace(/-----ENDRSAPRIVATEKEY-----/, '\n-----END RSA PRIVATE KEY-----')
    .replace(/(.{64})/g, '$1\n') 
Protoplast answered 25/6, 2024 at 21:24 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.