Ooto
Ooto

Reputation: 1247

Google Cloud Platform: Cloud Functions and Cloud Tasks doesn't work with authorized service account email

I created a service account email and added cloudfunctions.invoker role to the email so I can make sure only cloud tasks can trigger cloud functions, and I removed AllUsers role. But when cloud tasks tried to run cloud function, the status code is UNAUTHENTICATED(16): HTTP status code 401 and execution failed.

My current code and console is like this.

index.ts

export const addTasks = functions.https.onCall((data, context) => {
  if (!context.auth) {
    throw new functions.https.HttpsError('failed-precondition', 'You are not authenticated.')
  }

  const client = new tasks.CloudTasksClient()

  const projectId = functions.config().project.id
  const queue = 'queue'
  const location = functions.config().project.location
  const parent = client.queuePath(projectId, location, queue)
  const url = `https://${location}-${projectId}.cloudfunctions.net/executeSomething`
  const serviceAccountEmail = functions.config().project.email

  const task: tasks.protos.google.cloud.tasks.v2.ITask = {
    httpRequest: {
      httpMethod: 'POST',
      url: url,
      oidcToken: {
        serviceAccountEmail: serviceAccountEmail,
      },
    },
    scheduleTime: {
      seconds: ...,
    },
  }

  const request: tasks.protos.google.cloud.tasks.v2.ICreateTaskRequest = {
    parent: parent,
    task: task,
  }

  return client.createTask(request)
}

My cloud function's console

enter image description here

I added the cloud functions invoker role to the service account email.

My firebase project environment variables

enter image description here

When I added AllUsers role to cloud functions, it works as expected so I am sure I made a mistake when resrticting access. What am I missing?

Update:

My cloud tasks console

enter image description here enter image description here

Upvotes: 5

Views: 1809

Answers (3)

davidbilla
davidbilla

Reputation: 2222

Adding audience did the trick for me. Here is how my task object look like -

    const task = {
      httpRequest: {
        httpMethod: 'POST',
        url,
        headers: { 'Content-Type': 'application/json' },
        oidcToken: { 
          serviceAccountEmail: sa, 
          audience: aud 
        },
      },
    };

nodejs doc

Upvotes: 0

GorvGoyl
GorvGoyl

Reputation: 49150

for me removing audience: new URL(url).origin, from oidcToken object inside task resolved the UNAUTHENTICATED(16): HTTP status code 401 issue.

const task = {
    httpRequest: {
      httpMethod: 'POST',
      url,
      oidcToken: {
        serviceAccountEmail: email,
        //audience: new URL(url).origin, 
      },
      headers: {
        'Content-Type': 'application/json',
      },
      body,
    },
  };

Upvotes: 2

guillaume blaquiere
guillaume blaquiere

Reputation: 75715

Your OIDC token seems broken against the specification

Simply provide the email, without the attribute name like in this example, or use the snake_case like described in the spec

Upvotes: 0

Related Questions