Reputation: 463
I want to secure some Google Cloud Platform HTTP Functions. I've been following along here: Secure Google Cloud Functions HTTP Trigger With Auth
I've successfully followed the instructions and was able to set up the scheduler job it mentions, using the Add OIDC token
option for the Auth Header, and the service account I've set up for calling these HTTP functions. The function is called successfully from the Scheduler.
(The process for adding the IAM Member was slightly different, I followed these instructions)
I am able to call the function successfully from within GCP via the Testing feature, and the function is called successfully from the Scheduler. Calling the function w/o any authentication results in this message so I'm fairly sure the authentication is set up correctly:
Error: Forbidden Your client does not have permission to get URL /myAuthenticatdeFunction from this server.
Now I've written a c# application that retrieves an OIDC token and makes an http request per the instructions here.
public async Task<HttpResponseMessage> InvokeRequestAsync(
string iapClientId, string uri, CancellationToken cancellationToken = default)
{
// Get the OidcToken.
// You only need to do this once in your application
// as long as you can keep a reference to the returned OidcToken.
OidcToken oidcToken = await GetOidcTokenAsync(iapClientId, cancellationToken);
// Before making an HTTP request, always obtain the string token from the OIDC token,
// the OIDC token will refresh the string token if it expires.
string token = await oidcToken.GetAccessTokenAsync(cancellationToken);
// Include the OIDC token in an Authorization: Bearer header to
// IAP-secured resource
// Note: Normally you would use an HttpClientFactory to build the httpClient.
// For simplicity we are building the HttpClient directly.
using HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
return await httpClient.GetAsync(uri, cancellationToken);
}
/// <summary>
/// Obtains an OIDC token for authentication an IAP request.
/// </summary>
/// <param name="iapClientId">The client ID observed on
/// https://console.cloud.google.com/apis/credentials. </param>
/// <param name="cancellationToken">The token to propagate operation cancel notifications.</param>
/// <returns>The HTTP response message.</returns>
public async Task<OidcToken> GetOidcTokenAsync(string iapClientId, CancellationToken cancellationToken)
{
// Obtain the application default credentials.
//GoogleCredential credential = await GoogleCredential.GetApplicationDefaultAsync(cancellationToken);
string filepath = @"<path to json file for service account>";
GoogleCredential credential = await GoogleCredential.FromFileAsync(filepath, cancellationToken);
// Request an OIDC token for the Cloud IAP-secured client ID.
return await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience(iapClientId), cancellationToken);
}
When I run that, this is what I get back:
<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>/myAuthenticatdeFunction</code>.</h2>
<h2></h2>
</body></html>
What am I missing? Why does it not authenticate?
Upvotes: 0
Views: 707
Reputation: 75930
In your code, you use the IapClientId that works only for App Engine protected by IAP. If you use IAM protected Cloud Functions (same thing for IAM protected Cloud Run) you need to use the base URL of the service as audience value
https://<region>.<projectID>.cloudfunctions.net/<functionname>
Upvotes: 3