Skip to main content

Sensitive information in source code - API Key

Need

Secure storage and retrieval of sensitive information such as API keys

Context

  • Usage of C# for building robust and scalable applications
  • Usage of Microsoft.AspNetCore.Authentication.JwtBearer for JWT-based authentication in ASP.NET Core
  • Usage of Microsoft.IdentityModel.Tokens for implementing token-based authentication and authorization

Description

Non compliant code

public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "http://localhost:5000",
ValidAudience = "http://localhost:5000",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("ThisIsASecretKeyForAuthentication"))
};
});
}
}

The above code is an example of a vulnerable code where a secret key is stored in plain text in the source code. The secret key is used for authentication in a JWT bearer token setup in an ASP.NET Core application.

The IssuerSigningKey parameter of the TokenValidationParameters object is set to a new instance of SymmetricSecurityKey where the key is a plain text string - "ThisIsASecretKeyForAuthentication". This key is used to validate the tokens issued by the authentication server.

Having this key in plain text in the source code is a security vulnerability because anyone who can access the source code can see the key. This can lead to unauthorized access to the system, as they can generate valid tokens and impersonate any user.

Also, if the key is compromised, it cannot be changed without modifying the source code and redeploying the application, which is not a good practice and can lead to service disruption.

Steps

  • Remove the hard-coded API key from the source code.
  • Store the API key in a secure configuration file or environment variable.
  • Update the code to retrieve the API key from the secure configuration file or environment variable.
  • Ensure that the secure configuration file or environment variable is not accessible to unauthorized users.
  • Consider using a key management service or secure vault to store and retrieve the API key.

Compliant code

public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
var secretKey = Configuration["SecretKey"];
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "http://localhost:5000",
ValidAudience = "http://localhost:5000",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey))
};
});
}
}

The above code has been modified to remove the hard-coded API key and instead retrieve it from a secure configuration file or environment variable. The Configuration["SecretKey"] line retrieves the secret key from the configuration file or environment variable named "SecretKey".

To ensure the security of the API key, the configuration file or environment variable should be secured and not accessible to unauthorized users.

In a production environment, it is recommended to use a key management service or secure vault to store and retrieve the API key. This provides an additional layer of security by ensuring that the API key is not stored in plain text and is only accessible to authorized services.

Remember to never store sensitive information such as API keys, passwords, or other secrets in your source code. This is a common security vulnerability that can lead to unauthorized access and potential data breaches.

References