Enable Google Cloud IAP Authentication (OIDC) using ASP.NET Core
In this article, we will see how to Enable Google Cloud IAP Authentication – OIDC using ASP.NET Core and add an Identity-Aware Proxy to access Google Cloud-hosted protected resources and applications.
We shall see using a service account to authenticate when allowing accessing an application to access your IAP-secured resources.
Today in this article, we will cover below aspects,
We shall be using HTTPClientFactory to call the API/Services after obtaining the OIDC Token programmatically.
Approaches to Authenticate a service account using OIDC Token,
- Using ClientID
- Using Secured Service Account File
- IAM credentials API
Today in this article, We shall follow an approach of using client ID to Authenticate a service account
Getting started
Please create an ASP.NET Core 3.1 or .NET 5 application,
Kindly add below “Google.Apis.Auth” NuGet package. This NuGet package gives a runtime client for working with Google services.
PM> Install-Package Google.Apis.Auth -Version 1.50.0
How to obtain ClientID in Google Cloud
- Go to the IAP page:
https://console.cloud.google.com/apis/credentials
- Copy the Client ID as below,
Please enable IAP if it is not already enabled.
Obtain an OIDC token for authentication – IAP request
You can obtain the OIDC token for authentication of an IAP request using the below-simplified class IAPClient.
public class IAPClient
{
/// <summary>
/// Makes a request to a IAP secured applicatio
public async Task<string> InvokeRequestAsync(
string iapClientId, CancellationToken cancellationToken = default)
{
OidcToken oidcToken = await GetOidcTokenAsync(iapClientId, cancellationToken);
string token = await oidcToken.GetAccessTokenAsync(cancellationToken);
return token;
}
/// <summary>
///
/// </summary>
/// <param name="iapClientId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public async Task<OidcToken> GetOidcTokenAsync(string iapClientId, CancellationToken cancellationToken)
{
GoogleCredential credential = await GoogleCredential.GetApplicationDefaultAsync(cancellationToken);
// Request an OIDC token for the Cloud IAP-secured client ID.
return await credential.GetOidcTokenAsync(OidcTokenOptions.FromTargetAudience(iapClientId), cancellationToken);
}
}
Below is a simplified Controller method for understanding purposes. Here we get the OpenID token and call the actual API.
[HttpGet]
public async Task<IActionResult> GetAsync()
{
IAPClient clientIAP = new IAPClient();
var token = await clientIAP.InvokeRequestAsync(_clientID);
var client = _httpClientFactory.CreateClient();
client.DefaultRequestHeaders.Add("Authorization",$"Bearer {token}");
var response = await client.GetAsync(_clientURL);
var output = response.Content.ReadAsStringAsync().Result;
WeatherForecast forcast = JsonSerializer.Deserialize<WeatherForecast>(output);
return Ok(forcast);
}
In the above code, we kept the logic simplified for demonstration purposes.
Ideally, tokens can be created once and re-used with the given session as per the use cases.
Above using OIDC, now you can access the secured resources, and API endpoints available in Google Cloud.
How to debug on LocalHost
If you already have Service Account created then it applies to an application instead of an individual user. You need to authenticate a service account when while accessing your IAP-secured resources.
Please make sure to set Environment Variable GOOGLE_APPLICATION_CREDENTIALS with the secured key JSON file path.
Example:
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", "secured-key.json");
After adding the above user can debug locally from their machine and access or verify restricted or secured resources.
Your sample secured JSON will look like as below,
{
"type": "service_account",
"project_id": "***",
"private_key_id": "3efae6*******",
"private_key": "-----BEGIN PRIVATE KEY-----\n***************\n-----END PRIVATE KEY-----\n",
"client_email": "*************gserviceaccount.com",
"client_id": "******",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/*********"
}
Note: Do not store secrets related to authentication in the source code.
References :
Do you have any comments or ideas or any better suggestions to share?
Please sound off your comments below.
Happy Coding !!
Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.
How can you implement this in the startup.cs so it available throughout.
Also, how could you the retrieve user roles?
Hi Danny- You could try Typed or Named HttpClient and inject the token class within startup using technique discussed in the below article Initialize the Instances within ConfigServices in Startup .NET
Other references : Typed HTTPClient using HttpClientFactory in ASP.NET Core -Part2
Hi there,
I’m following your instruction to implement the code, at the end I got Error:”invalid_grant”, Description:”Invalid JWT Signature.”, Uri:””.
Do you have any idea of it?
Hey Calvin- thanks for the query. There could be multiple reasons for this error. A few checks you can do are 1. the base64 encoding used in the code..? 2. Activate the service account before using it 3. Verify encryption/decrpyiron are using a correct algorithm if any.