OAUTH 2.0 — Configuring Authentication on ASP.NET Core Applications

Rafael Araujo de Lima
4 min readSep 18, 2024

--

Imagine that you are accessing a website, and it prompts you for a username and password. You submit the credentials, and once authenticated, the protected pages become accessible. However, upon reviewing the authentication method, for each request from the frontend to the backend, a token is sent in the request header. This token is fixed and stored in an environment variable in the frontend and configured as environment settings in the backend. For each request, the backend checks if this token matches the one sent by the frontend and either authorizes or denies the execution of the endpoint.

Strange, right? But this was a real scenario I encountered in an application.
If this token is fixed in both the frontend and the backend, we have a few issues here:

Token exposure: The fixed token is exposed, and anyone can access it. If someone develops an application to consume the backend and includes the fixed token, without any other security parameter, they can authenticate and access the backend without any issues, potentially performing attacks that affect the application’s performance or even break it.
Token does not expire: The token is the same for everyone and does not expire. This is problematic due to the lack of authentication control. The login expiration control should be done by the backend. But in this case, it is being handled on the frontend.
Single token: The single token makes it harder to track changes in the system, requiring new measures for this.

We can solve this with OAUTH 2.0.

What is OAUTH 2.0?

It is an authorization protocol designed to allow an application or service to access resources from another service. It has several ways to perform authentication. We will use the method called Resource Owner Password Credentials Grant (ROPC). The user sends their access credentials (username and password) to the backend, which validates them and generates a token (usually called JSON Web Token (JWT)), returning this token to the frontend.

1. Add the necessary packages to the application

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package Microsoft.IdentityModel.Tokens

2. Configure the appsettings.json

Insert the following settings into your appsettings.json configuration file to be used for token generation.

“JwtOptions”: {
"Issuer": "IssuerServer",
"Audience": "AudienceServer",
"Key": “YOUR_SECURITY_KEY",
"ExpirationTime": 60
}

3. Configure your Program.cs or Startup.cs

builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration.GetSection("JwtOptions:Issuer").Value,
ValidAudience = builder.Configuration.GetSection("JwtOptions:Audience").Value,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration.GetSection("JwtOptions:Key").Value))
};
});

Here we add the JWT authentication method with its respective validations. Notice that in ValidIssuer, ValidAudience, and IssuerSigningKey, the information is fetched from appsettings.json.

4. Configure Claims and generate the token

Now, create a class responsible for generating the JWT and returning it. The token is a string.

private string GenerateJwtToken(string username)
{
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, username),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

var token = new JwtSecurityToken(
issuer: Configuration["JwtOptions:Issuer"],
audience: Configuration["JwtOptions:Audience"],
claims: claims,
expires: DateTime.Now.AddMinutes("JwtOptions:ExpirationTime"),
signingCredentials: creds);

return new JwtSecurityTokenHandler().WriteToken(token);
}

After this, simply return the token to the frontend and use a tool to read the token according to the language. The token contains the information that was inserted during its creation. Therefore, all this information is retrievable.

5. Protect your endpoints

At least, don’t forget to protect your endpoints. In the controllers that receive HTTP requests, use the [Authorize] attribute as shown below:

[Authorize]
[HttpGet]
[Route("/do-something-if-authorized")]
public async Task<IActionResult> MyProtectedController([FromHeader] HeaderInput header)
{
var handler = await doSomethingIfAuthorized(header);
return Ok(handler);
}

Don’t worry. The backend is responsible for validating whether the information in the JWT is authentic. Even though the information is accessible, only the backend can validate it due to the token’s signature. Only the backend has the encryption key.

This is why access validations for resources (pages, endpoints, etc.) must be done in the backend, not the frontend.

Conclusion

OAUTH 2.0 is a simple and secure way to authenticate the frontend with the backend, even protecting resources with Claims and Roles. We can also see how important it is to distinguish the responsibilities of each part of an application. The frontend is responsible for displaying the requested data, and the backend is responsible for filtering which data will be shown and if they can be accessed.

I hope this helps.
Best regards,
Rafael Lima
Senior Software Engineer

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Rafael Araujo de Lima
Rafael Araujo de Lima

Written by Rafael Araujo de Lima

A Senior Software Engineer with over 10 years of experience, specializing in software development with a focus on .NET Core, ASP.NET Core, C#.

No responses yet

Write a response