5
votes

I have a Private Google Cloud Function. So I want to Authenticate to the Cloud Function with Authorization: Bearer token Header. But I'm getting 401 Unauthorized as the response.

I created the private Cloud Function using:

gcloud beta functions deploy MyFunction --runtime go111 --trigger-http --memory 128 --region us-central1 --source gs://bucketname/code.zip

I created a service account and assigned it permission to access the cloud function:

gcloud beta functions add-iam-policy-binding MyFunction --member=serviceAccount:[email protected] --role=roles/cloudfunctions.admin

Output:

bindings:
- members:
  - serviceAccount:[email protected]
  role: roles/cloudfunctions.admin
etag: BwWOGyVdpDg=
version: 1

Now, I downloaded the service account json file.

So now in order to access the Cloud Function, I will need to add the Authorization Header with Bearer token. For generating the bearer token, I use following java code:

String fileName = "path/service-account.json";
FileInputStream keyFileInputStream = new FileInputStream(fileName);
GoogleCredential credential = GoogleCredential.fromStream(keyFileInputStream).createScoped(Collections.singleton(ContainerScopes.CLOUD_PLATFORM));    
credential.refreshToken();
String token = credential.getAccessToken();

I use this token in the Authorization Header.

URL-

us-central1-[project].cloudfunctions.net/MyFunction

Header-

Authorization: Bearer ya29.c.YpN3bEGV-H4WyTeLQn9kxxFq1Js7mcMtoESW1C-5HstmEgdaXR_gY_stxnlpJna8IL25VvnpwTg5tFL5OorcfBT2_Qtld7FViTbzHas4AiUUEme7mffXRtZOn29

I use Postman to send the request. For this request, I get the output:

<html>
    <head>
        <meta http-equiv="content-type" content="text/html;charset=utf-8">
        <title>401 Unauthorized</title>
    </head>
    <body text=#000000 bgcolor=#ffffff>
        <h1>Error: Unauthorized</h1>
        <h2>Your client does not have permission to the requested URL 
            <code>/MyFunction</code>.
        </h2>
        <h2></h2>
    </body>
</html>

What could be wrong? Is the token generation logic something different?

2

2 Answers

2
votes

There are three types of OAuth tokens. Refresh Token, Access Token, Identity Token.

You are trying to use an OAuth Access Token instead of an OAuth Identity Token.

For Authorization, Google Cloud Functions uses an OAuth Identity Token in the authorization: bearer HTTP header.

In your question, you do not show setting up IAM member access to the Cloud Function. That means no matter what Identity Token you use, all will be denied.

0
votes

Here is my solution:

    Private Shared Async Function GetAccessToken(pCredentialJson As String, pFunctionPath As String) As Task(Of String)
        Try
            Dim scopes = New String() {"https://www.googleapis.com/auth/indexing"}
            Dim credential As ServiceAccountCredential = TryCast(GoogleCredential.FromJson(pCredentialJson).CreateScoped(scopes).UnderlyingCredential, ServiceAccountCredential)
            Dim oidcToken = Await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience(pFunctionPath))
            Return Await oidcToken.GetAccessTokenAsync()
        Catch ex As Exception
            Throw
        End Try
    End Function

Put the value returned in header Authorization Bearer ....