---
title: 'How to Secure .NET 10 APIs with Keycloak and OAuth 2.0'
source: 'https://youtube.com/watch?v=PLHmcXCljNg'
video_id: 'PLHmcXCljNg'
date: 2026-08-08
duration_sec: 900
---

# How to Secure .NET 10 APIs with Keycloak and OAuth 2.0

> Source: [How to Secure .NET 10 APIs with Keycloak and OAuth 2.0](https://youtube.com/watch?v=PLHmcXCljNg)

## Summary

This video provides a comprehensive, step-by-step guide to integrating Keycloak as an identity provider into a .NET 10 application. It covers setting up Keycloak locally with Docker Compose, configuring a realm and client, integrating Swagger UI for OAuth 2.0 authorization code flow, and validating JWT tokens in the backend.

### Key Points

- **Overview and Setup** [00:02] — The video demonstrates a complete setup for integrating Keycloak with .NET 10 applications, using Docker Compose for local orchestration.
- **Keycloak Docker Service** [00:27] — Define Keycloak as a service in docker-compose.yml using the image quay.io/keycloak/keycloak:26.5.2, with a startup command for development mode, environment variables for admin credentials (admin/admin), and health check enabled.
- **Volumes and Ports** [01:33] — Map a local folder to /opt/keycloak/data inside the container, expose port 8080 for the main UI and port 9000 for the health check endpoint. Optionally set the root user to avoid database creation issues in development.
- **Accessing Keycloak UI** [02:25] — After running docker compose, access the Keycloak UI at localhost:8080, log in with admin credentials, and create a realm (e.g., 'offdemo'). Enable user registration in realm settings to allow new users to sign up.
- **Creating a Public Client** [02:54] — Create a public client for the UI, set valid redirect URIs to localhost:5011 with a wildcard, and save the client configuration.
- **Integrating Swagger UI** [03:38] — Install the Swashbuckle.AspNetCore NuGet package to add Swagger UI and OpenAPI generator. Add middleware app.UseSwagger() and app.UseSwaggerUI(). Create an endpoint /users/me that returns claims from the access token, protected with [Authorize].
- **Configuring Swagger for OAuth2** [05:17] — Create an extension method AddSwaggerGenWithAuth that configures Swagger with an OAuth2 security scheme using the authorization code flow (with PKCE). Set authorization URL, token URL, and scopes (openid, profile).
- **Finding URLs via Well-Known Endpoint** [08:53] — Use Postman to GET the well-known OpenID Connect configuration at http://localhost:8080/realms/offdemo/.well-known/openid-configuration to retrieve the authorization and token URLs.
- **App Settings Configuration** [10:00] — In appsettings.json, set the authorization URL, token URL, metadata address (using 'keycloak' as hostname for container networking), valid issuer, and audience (account).
- **Adding JWT Bearer Authentication** [10:42] — Install Microsoft.AspNetCore.Authentication.JwtBearer (version 10.0.2). Add services: AddAuthorization(), AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer() with configuration for audience, metadata address, and valid issuer.
- **Middleware Order** [12:19] — Add app.UseAuthentication() before app.UseAuthorization() in the request pipeline.
- **Testing the Integration** [12:32] — Run the application, open Swagger UI, click Authorize, and complete the OAuth flow. Register a new user in Keycloak if needed. After obtaining an access token, call the /users/me endpoint to see the claims.
- **Verifying the JWT** [13:59] — Copy the access token and paste it into jwt.io to verify it's a valid JWT and that the claims match the API response.

### Conclusion

The video successfully demonstrates a complete integration of Keycloak with a .NET 10 API, covering all essential steps from setup to testing. It provides a solid foundation for implementing authentication and authorization in modern .NET applications.

## Transcript

provider in 2026. And in this video, I'm going to show you the complete setup from getting started with Keyclo to integrating it into your .NET applications to implement authentication and authorization support. I'll be
running a net 10 application that's using Docker Compose for local container orchestration. And the first thing we need to do is to get an instance of Keycloak up and running on our local machine. So to do that I'm going to
define keycloak as another service inside of our system and I'm already getting a completion from Visual Studio which I'm going to ignore. However, this is the image I want to use. It's quio keycloak/keycloak
and the latest version at the time of recording this video is 26.5.2. I will use the container name of keycloak and I also want to specify a startup command to start keycloak in development mode. This is just going to
use the local embedded database and it's going to make running heatlo locally easier. Alternatively, you could plug in your existing database. For example, it supports Postgress, SQL server and many other popular databases. So, you're not
only limited to the default key load database. Then, we have to pass in some environment variables to set up our admin account. And for development, using admin and admin is perfectly sufficient. And one more variable I'm
going to specify is the key health check. So I'll say KC health enabled and let's go ahead and set this to true. Then I want to map some volumes. This is actually just mapping a local folder to the internal folder in keyclo and the
the internal folder in keyclo and the internal folder name is opt/keyclo/ data. And then one more thing we want to expose is the ports where keycloak will be available on our local system. And the default keycloak port is 8080. But
I'm additionally going to specify the port 9,000 which is where the keylo health check endpoint is exposed. And then one more thing which could be helpful if you've run into problems with keyflow before when running it inside of
a container is specifying the root user. I've heard examples of keylo being unable to create the embedded database because of some access policies and specifying the root user in development mode usually fixes this. But let's make
sure to leave a comment that this is development only. So now when we run this using docker compose, it's going to spin up all of the services that we defined inside of our compose file locally and we'll be able to access them
through the available ports. If I go to localhost880, we're going to see the keycloak UI where we can enter our admin username and password and we're going to enter the keycloak realm. I'm going to quickly create my realm which I'm going
to call off demo. Let's go ahead and create it. One thing I want to configure on this realm, if I go to the realm settings and then login is enable user registration, which is going to allow us to easily create new users, assuming we
public client that we're going to use from our user interface to authenticate with key loop. I'm going to call this our public client just for ease of use. settings here. And then we can go ahead and click next. for the valid redirect
and click next. for the valid redirect URIs. I want to use port localhost 501. Then I'm going to specify a wild card using a star so that any URI with this address is a valid redirect URI. If you got a specific page that you only want
ahead and be granular and specify that page. Let's go ahead and save this. And now we can go into our net application and see how to integrate keylo as an identity provider step by step. I'm going to close down the docker compose
yaml file and I want to open up my program file. So right now I don't have some open telemetry setup which is going to come in handy later when I show you a couple of interesting things with the Aspire dashboard. But for now we have to
figure out how to connect keycloak with our application and integrate support for authenticating users but also enforcing authorization policies. So for my keycloak user interface, I'm going to use swagger and I need to install a
nougat package to be able to use it. So let's go ahead to browse and I'm going to look for swagger. And the base library is actually called swashbuckle espnet core. It encapsulates both the swagger UI and the swagger open API
generator. So that's what I'm going to install here. This will allow me to add two middleware to my setup. So I'll say app use swagger. This is going to add the generator and then app use swagger UI to expose our user interface. Then
we're going to need some sort of endpoint to be able to just validate that we've successfully authenticated. I like to call this endpoint users/me to represent the currently authenticated user. And one thing we can inject here
is a claims principle that we're going to parse from our access token. And the simplest way to test this is to say return claims principle claims and then turn them into a dictionary where I'm going to choose the claim type as the
key and then the claim value as the dictionary value. So let's go ahead and wrap that. And finally we want to add require authorization here to require an access token to be able to call this endpoint. Now the next thing is going to
be setting up our swagger integration. I've got an extensions folder here with a service collection extensions class that is currently empty. And here I want to add an extension method. I'm going to make this static returning an I service
collection. And let's call this add swagger gen with op support. And as I said, this is an extension method on the I service collection interface. But we're also going to need access to I configuration to be able to fetch some
values from our config. to make sure we satisfy the contract. Let's just return these services right away. And then what I want to do here is call add swagger gen where I'm going to specify a delegate that is going to encapsulate
essentially what we're going to do here is set up a couple of swagger specific things but also add an integration with our open ID connect provider which is keycloak. This is going to allow us to use the authorization code flow with
keycloak as the identity provider to give us the access token that we're going to then pass to our backend, our API to perform the authorization check. You'll see how this works when I show you some distributed traces. So, what do
we need to do to set this up? One thing I always like to do with swagger is have my custom scheme ids and then we need to add a security definition. I'm going to call this our keycloak security definition. And this requires a new open
API security scheme. Now the important parts here are setting the type which is going to be OOTH 2. And then we have to specify which flow we want to use which is going to be a new open API of flows. And this lets you set a couple of
different flows supported by OOTH 2. And the one that we want is the authorization code flow which is the most robust one and industry standard one. Or to be more precise, the industry standard currently is authorization code
with pixie which is proof key for code exchange. And here we just pass in an object representing our authentication flow where we can set a couple of things and these things are mostly standard and they represent the authorization URL
which is where you can kick off the authorization flow which triggers the the second one we're going to need is the token URL which is the swagger UI in this case can then exchange the
authorization code for the access token which will be represented as a JSON web configuration object comes in where I'm going to pull the value from our settings which is going to be keycloak and then authorization URL. I'll use a
null forgiving operator here and then let me copy this and pass it in to the token URL. And I'll just make sure that we use the correct setting name. Then we're going to pass in any scopes that we might need to pass with our
authorization request. I'm going to use two scopes which are pretty standard. They're going to be the open ID scope and the profile scope. So this is half of the story. We've added our security definition. We also need to add a
security requirement. And this requires a delegate accepting our document and returning an open API security requirement. And here we can just new up a new open API security requirement which internally accepts a dictionary of
open API security scheme references. And an easy way to pass this is by passing in a new open API security reference where the reference ID is the name of our open API security scheme that we defined above called keylo. So I'm going
to just use that and then we're going to also pass in our open API document. And for the second argument which represents the we can pass in an empty array using the collection expression syntax. So with this setup we've integrated our
swagger UI with our identity provider and we're going to be able to obtain an access token to pass along to our backend to authenticate on behalf of a user and access any resources that our server might expose. Now what about
these values here the authorization URL and the token URL? Let me jump into Postman to show you how you can find these. So, what I've got here is a get request on the port 9,000 to the health endpoint, which I'm going to send. And
you can see we get back a 200 okay request letting us know that keycloak is up and running. And I'm going to replace this with a request like this. It's going to target localhost 8080, which is where the core of keycloak is exposed.
And we want to specify realms. Then the name of our realm, which is off demo. And then this is a well-known open id connect route called well-known/open request like this, you will get back some useful info about your keycloak
instance. And the second and third responses here represent our responses here represent our authorization URL and the token URL. So I can go ahead and copy these and then use them inside of my app settings. So
if I go back to Visual Studio and open up my app settings, here is the authorization URL that I need to pass in. And then the second argument is going to be the token URL and the endpoint is just / token instead of
slash off. And while we are here, we can also fill in the metadata address, which is the value that I just used in the postman request, except I'm going to replace local host with keycloak, which is where my net app running in a
container can find the keyfl. I'll also specify the valid issuer using the value returned from the well-known endpoint. This is available on local host. And the audience for our public client is going to be the account value.
We'll also see this in the JSON web token that we get back from keylo. And one last thing that's left is to integrate support for validating JSON web tokens in our back end. So let me go ahead and look for a nougat package
called Microsoft ASP.NET Core Authentication JWT Bearer. I'll install the latest version which is 10.0.2. Remember that we are running this on net 10. And then we have to add a couple of services or service collection. I'll
call the extension method that we just defined for configuring swagger genen with authentication support. Then I have to say builder services add authorization first and after that I'm going to say builder services add
authentication where I'm going to specify my authentication scheme using the JWT bearer defaults constant which just specifies the authentication scheme as bearer. Then I'm going to chain a call to add JWT bearer. And here I'm
going to pass in a delegate to configure how we are actually going to validate our JSON web token. So I'm going to set require HTTPS metadata to false because I'm only running key with HTTP. Then we have to specify our audience which is
except the top level key is authentication. We're also going to do the same for the metadata address. I'll say builder configuration and then let's specify the key as authentication metadata address. And lastly, I'm going
to pass in some token validation parameters where I want to set the valid issuer. And this value we're also going to pick up from our app settings as authentication issuer. And one last thing you have to check before running
this is that you've got the respective middleware added to your request pipeline. And the correct order of adding them is calling use authentication and then finally use authorization. And now we should be good
to go. Let's go ahead and start the application. And this should open up the swagger UI with the one endpoint that we have. And if we send a request, we response, which is what is happening. So that's good. I'll click the authorize
button where you can see our authorization URL and the token URL with their respective values. We also have an option to specify the client ID which is the public client that we created in keycloak earlier and I'll select both of
authorize I'm going to open up the network tab in the developer tools. And now I'll click authorize and we'll get redirected to our keyfl. So because we don't have a user we also have an option to register as a new user. So I'll go
ahead and fill in some data here. Now I should be able to click register and we'll get redirected back to the swagger UI where you can see an additional request show up in the network tab which is the request to get the access token
payload you'll find the authorization code that we got from the authorization flow which redirected us to Keycloak where we either input our credentials or we register as a new user. So now that we've got our access token and now we
should be able to send a request to our back end and get back a valid response which contains all of the claims from the JSON web token that we got from keycloak and you can see the contents of this token here where you can copy this
value and paste it into something like jwtio where you can verify that this is indeed a valid JSON web token and also all the values here match the claims that we got back in the API response. So now we've got a fully integrated
identity provider that implements the authorization code flow for getting the access tokens. Your next step would probably be to integrate this with some single page application to serve as your UI. But for back-end development using
Swagger UI for this is efficient enough for our use cases. In a previous video, with Postman. So this kind of closes the loop of how to use Keello in 2026 with .NET 10 and all the latest changes that have happened in the space. If this was
a little fast-paced for you, I've got a fully beginnerfriendly Keyflow intro that you can check out here if you want to learn more about this. If you enjoyed this video, consider smashing the like button. Click the subscribe button to
see more videos like this one in the future. Thanks a lot for watching and future. Thanks a lot for watching and until next time, stay awesome.
