Authentication with OpenID Connect (Without OAuth2) in .NET Core with an Item API
Identity for your application.
OpenID Connect (OIDC) is an identity layer built on top of OAuth2. While OAuth2 is primarily focused on authorization, OIDC provides authentication, allowing clients to verify the identity of a user. It's important to note that OIDC is inherently tied to OAuth2 as it uses OAuth2 for the authorization part of its flow. However, you can use OIDC specifically for authentication without focusing on the broader OAuth2 authorization scenarios.
In this blog, we'll explore how to implement OIDC in a .NET Core application with an Item API, focusing on the authentication aspect.
What is OpenID Connect (OIDC)?
OpenID Connect is a simple identity layer on top of the OAuth2 protocol, which allows clients to verify the identity of the end-user based on the authentication performed by an authorization server. It also provides basic profile information about the user in the form of an ID token.
Implementing OIDC in a .NET Core Application
Let's walk through how to implement OpenID Connect in a .NET Core application using an Item API as an example. In this scenario, we'll use OIDC for authentication, ensuring that only authenticated users can access the API.
1. Setting Up an OpenID Connect Provider
Before implementing OIDC in your .NET Core application, you need an OIDC provider. This provider is responsible for authenticating users and issuing ID tokens. Common OIDC providers include Azure AD, Google, and Auth0.
2. Configuring OIDC in .NET Core
Once you have your OIDC provider set up, you need to configure your .NET Core application to use OIDC for authentication.
Install the Required Packages
Ensure you have the necessary NuGet packages:
dotnet add package Microsoft.AspNetCore.Authentication.OpenIdConnect
dotnet add package Microsoft.IdentityModel.Protocols.OpenIdConnect
Configure Services in Startup.cs
Next, configure the authentication services in your Startup.cs
file:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie("Cookies")
.AddOpenIdConnect(options =>
{
options.Authority = "https://YOUR_OIDC_AUTHORITY_URL"; // e.g., https://login.microsoftonline.com/{tenant}
options.ClientId = "YOUR_CLIENT_ID";
options.ClientSecret = "YOUR_CLIENT_SECRET";
options.ResponseType = OpenIdConnectResponseType.Code;
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
In this configuration:
DefaultScheme
is set to "Cookies," indicating that the authentication state will be stored in cookies.DefaultChallengeScheme
is set toOpenIdConnectDefaults.AuthenticationScheme
, which triggers the OIDC flow when authentication is required.Authority
is the URL of your OIDC provider.ClientId
andClientSecret
are credentials obtained from your OIDC provider.ResponseType
is set tocode
, which is the authorization code flow that OIDC uses for authentication.
3. Securing the Item API with OIDC
With OIDC configured, you can secure your Item API by adding the [Authorize]
attribute to your controller or specific actions.
Securing the Controller
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
namespace ItemApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ItemsController : ControllerBase
{
private static List<Item> Items = new List<Item>
{
new Item { Id = 1, Name = "Item1", Description = "First item" },
new Item { Id = 2, Name = "Item2", Description = "Second item" },
};
[HttpGet]
public ActionResult<IEnumerable<Item>> GetItems()
{
return Ok(Items);
}
[HttpGet("{id}")]
public ActionResult<Item> GetItem(int id)
{
var item = Items.FirstOrDefault(i => i.Id == id);
if (item == null)
{
return NotFound();
}
return Ok(item);
}
// Other CRUD actions...
}
}
The [Authorize]
attribute ensures that only authenticated users can access the API. If a user is not authenticated, they will be redirected to the OIDC provider's login page.
4. Testing the OIDC Authentication Flow
To test the OIDC authentication flow:
Initiate the OIDC Flow: When a user tries to access a secured endpoint, they are redirected to the OIDC provider's login page.
Authenticate the User: The user logs in with their credentials.
Receive the ID Token: After successful authentication, the OIDC provider issues an ID token, which is validated by your application.
Access the API: The user is now authenticated and can access the secured endpoints.
Example request flow:
User navigates to
/api/items
.The app redirects the user to the OIDC provider.
The user logs in, and the OIDC provider redirects back to the app with an ID token.
The app processes the ID token, stores the authentication state in cookies, and allows access to the
/api/items
endpoint.
Conclusion
OpenID Connect (OIDC) is a powerful protocol for adding user authentication to your web applications. By following the steps outlined in this blog, you can implement OIDC in your .NET Core applications to ensure that only authenticated users can access your APIs.
This example demonstrated how to configure OIDC in a .NET Core application, secure an Item API, and handle the authentication flow. Whether you're building a small API or a large-scale application, OIDC provides a robust solution for managing user authentication.