Friday, December 24, 2021

ASP.NET Core WebAPI secured using OAuth2 Client Credentials

Authentication means verifying the user who is accessing the system. We have available different types of authentication in .NET programming like Windows Authentication, Forms Authentication, Claim Based Authentication, Token-Based Authentication, etc.


Token-based Authentication

In token-based authentication, you pass your credentials [user name and password], to the server, which verifies your credentials and if it is a valid user, then it will return a signed token to the client system, which has an expiration time. The client can store this token locally using any mechanism like local storage, session storage, etc. and if the client makes any other call to the server for data, then it does not need to pass its credentials every time. The client can directly pass the token to the server, which will be validated by the server and if the token is valid, then you will able to access your data.
(Open Authorization) is an open standard for token-based authentication and authorization on the Internet.
OAuth versions
There are two versions of OAuth authorization OAuth 1 (using HMAC-SHA signature strings) and OAuth 2 (using tokens over HTTPS).

OAuth Tokens

There are two types of tokens involved in OAuth 2,
Access Token
The access token is used to for authentication and authorization to get access to the resources from the resource server.
Refresh Token
The refresh token normally is sent together with the access token.
The refresh token is used to get a new access token when the old one expires. Instead of the normal grant type, the client provides the refresh token and receives a new access token.
Token Types
Access tokens have a type, which defines how they are constructed.
  • Bearer Tokens
    The bearer tokens use HTTPS security, and the request is not signed or encrypted. Possession of the bearer token is considered authentication.

  • MAC Tokens
    More secure than bearer tokens, MAC tokens are similar to signatures, in that they provide a way to have (partial) cryptographic verification of the request.

which shows how to create an Authorization Server that can issue Tokens following the OAuth2 Authorization framework.

It  is possible, anyway, to use ANY Authorization server to obtain the token and validate it without substantial changes in the secured Web API. This extension is, at the moment, not covered in the article.

Step-by-step creation of the secured WebAPI service

Creation of the empty WebAPI project

For this WebAPI we are going to use Visual Studio 2017, together with .NET Core 1.1.
We start opening VS2017 and selecting File -> New -> New Project. We select then a .NET Core project as in the following:

Give to the project the name you prefer. I'm using here ProtectedWebAPI.

After pressing OK, in the next screen be sure that you are using .NET Core 1.1. Select the template WebAPI and press OK again.

Add an open (non-secured) welcome page to your WebAPI service

This is not a necessary step. But personally I like when I press "Play" in the debugger and something happens, it gives me the feeling that my code is working.

For this reason in this section I'm adding a "non secured" welcome page to our WebAPI. For this page we won't need any token and it will be the default page when accessing our WebAPI service using a browser.

In order to do so, I need to add a controller, a view, and the MVC libraries. I will detail the necessary steps, for those that are not familiar with the ASP.NET MVC framework.

Add a MVC controller

  • In the folder Controllers add a new controller named HomeController.
  • Adding the new controller, VS will ask what dependencies to add to the project. You can choose Minimal Dependencies for now.
  • At the time I'm writing, after adding the dependencies, I need to add the controller again. I think it is a little bug of the Visual Studio UI....
  • Now, adding the controller, VS asks which scaffold to use. Choose MVC Controller - Empty.
  • Finally, choose the name HomeController.  A basic controller that can manage an Index.cshtml page is now created.

Add a MVC View

  • Again, in VS2017, right click on the project and select Add new folder.
  • Name it Views (don't change it! It's a default option for MVC!).
  • Now, inside this Views folder, add another folder named Home.
  • Right click now on the folder Home and select Add -> New item ->  MVC View Page (ASP.NET Core).
  • By default the name of the view is Index.cshtml which is what we want.  Press the button Add to add the new view.

Write the HTML content of the View

Change the code in the Index.cshtml with the code below, just to create a welcome message:

<title>Protected WebAPI. Welcome page.</title>
<h1>Protected WebAPI. Welcome page.</h1> 

Configure the Startup class

Setup the propert route in the Startup.cs to be able to browse the website:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

            app.UseMvc(routes =>
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");

Now browse the file in ProtectedWebAPI -> Properties -> LaunchSettings.json and remove the line containing the property launchUrl from every section visible in the file.  

"profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "api/values",  //REMOVE THIS ONE
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
    "ProtectedWebAPI": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "api/values",  //REMOVE THIS ONE
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      "applicationUrl": "http://localhost:56087"

Without this property, Visual Studio will launch the home page following the default path, and will point automatically to the web page that we just created.

Launch the project to check that it works...

...and to enjoy the achievement of a first step!

Warning: some people reported some issues in VS2017 related to launching a WebAPI project using IISExpress. In case you are one of those, you can change the profile next to the button "Start project" switching from IISExpress to ProtectedWebAPI as shown in the following picture:

Image 3

Secure the WebAPI endpoint

Now that we have our project all set up and we also have a nice welcome page, we can create an endpoint and then secure it, so that it won't accept any request if a proper OAuth2 token is missing! 

First, create an open endpoint that returns some values

This is an easy step to achieve, the VS WebAPI template has already created a basic open endpoint for us! You can browse the project to  ProtectedWebAPI -> Controllers -> ValuesController.  Here the code that you will find:

namespace ProtectedWebAPI.Controllers
    public class ValuesController : Controller
        // GET api/values
        public IEnumerable<string> Get()
            return new string[] { "value1", "value2" };

        // GET api/values/5
        public string Get(int id)
            return "value";

        // POST api/values
        public void Post([FromBody]string value)

        // PUT api/values/5
        public void Put(int id, [FromBody]string value)

        // DELETE api/values/5
        public void Delete(int id)

This code provides an endpoint that

  • answer at the address http://localhost:56087/api/values (ok, the port actually depends from the applicationUrl property in LaunchSettings.json)
  • can be browsed with a browser and returns a list of string
  • can accept other requests, using different HTTP Verbs (POST, PUT, DELETE) but these are out of the scope of this article for now.

If we try to browse the address http://localhost:56087/api/values we will see that (depending on the browser) we can receive back a file called values.json containing a list of values.

This means that your endpoint is currently answering to every anonymous request. It's an open endpoint. 

Of course we can change the type of values that we are providing back to the user request, but this is not the point of this article. Our sample endpoint returns a list of strings, but it could be anything.

Add the Middleware needed to manage the validation of the token

Using the Nuget package manager (or whatever you like), add the packages

  • IdentityServer4.AccessTokenValidation 

to the project:

Now include the configuration call to UseIdentityServerAuthentication(..) needed in the Configure() method, in the Startup.cs file.
Remember to always ensure that the code app.UseMvc(...) is the last line in the Configure method:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
            //more code....

            //add this configuration for the middleware needed to validate the tokens
            app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
                Authority = "http://localhost:50151",
                RequireHttpsMetadata = false,
                ApiName = "scope.readaccess"

            //more code....and especially app.UseMvc(...)

Secure this endpoint to not accept  anonymous requests

Before securing the endpoint in this example, it is useful to configure our WebApi to show the error code when something goes wrong. It will help us to better understand the example.

Add the instruction app.UseStatusCodePages() in the Startup.Cs:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    //more code...

    //add this line to show the ERROR STATUS CODES

    //more code...

And now add the [Authorize] attribute to the class ValuesController.cs
This is the key step to activate the security features embedded in ASP.NET MVC.

namespace ProtectedWebAPI.Controllers
    public class ValuesController : Controller
       //some code that I cut in this snippet

If you want to know more, I found very useful this article that explaines clearly the basics of the JWT Authentication Middleware in .NET Core. 

Add a basic Scope validation in our secured WebAPI

In the previous article, when we created the Authorization server, we also created two different scopes: "scope.readaccess" and "scope.fullaccess". Now, in this article, while we are accessing our Protected API we are passing the scope "scope.readaccess". Validating the right scope is beyond this article. There are many techniques to inspect the token, analyze the scope and react properly in the API we are protecting.

As usual the guys from the IdentityServer project gave us already some good hints on how to do that. In this article, Dominick Bayer provides various techniques.

In this article, however, just for completeness, I'm providing one possible way to check the scope. The code snippet is the one that you will put  in the ValuesController class, inside the public IEnumerable<string> Get() method. The method will look like this:

 // GET api/values
        public IEnumerable<string> Get()
            //this is a basic code snippet to validate the scope inside the API
            bool userHasRightScope = User.HasClaim("scope", "scope.readaccess");
            if (userHasRightScope == false)
                throw new Exception("Invalid scope");
            return new string[] { "value1", "value2" };

Test the secure endpoint

The test is really straightforward. Launch again your WebAPI project: the welcome page shows up.
But now try again to access the link http://localhost:56087/api/values. Before we were receiving back a JSON file containing the values  returned from the API Call.....but now the answer is a clear:

Our WebAPI is now secured. It can't be anonymously accessed anymore.

Create a client that can access our WebApi

Now that we have our secured WebAPI, how do we access it? In this section we are going to create a client that can

  • request an access token from an OAuth2 Authorization Server;
  • call our WebAPI endpoint using the token and being authorized;

Put together the Authorization Server credentials

Before we start writing our client, we need to know which authorization server are we going to use. In this article I'm creating a Web API secured against the authorization server that I built in a previous article.

Therefore I'm going to use the credentials parameters that were configured in that article for this specific client. These credentials are:

  • Urlhttp://localhost:50151/connect/token (The Authorization Server runs locally on my same machine answering at this specific port)
  • ClientIdClientIdThatCanOnlyRead
  • ClientSecretsecret1
  • Scopescope.readaccess

Keep in mind these parameters. You will find them hardcoded in the Client code, and now you know where they are coming from.

Add a Console project

As a test client we don't need anything special in this tutorial. Therefore I'm just adding a Console client which will request the token and then access our WebAPI showing the results in the console window.

So, let's take our solution containing the WebAPI project and add, next to it a new File-> Add ->New project-> Console App (.NET Core). Choose the name ConsoleTestClient and press OK to add it.

Add the IdentityModel Nuget packages

To allow our client to handle with the request and make our life easier, add the following packages to the Console project:

  • System.IdentityModel.Tokens.Jwt

When adding this package, a few others will be pulled in from Visual Studio. Accept everything as they are needed references.

Request the JWT Token

Now it's time to write some code. My console client is just a Program.cs file. The first part of the code makes a request to the Authorization Server previously built in this article. In this example I'm assuming that this server is running locally on the same machine!

Here the snippet of Program.cs to request the token. Don't forget to add the using that will be suggested from Visual Studio:

        static void Main(string[] args)
            //authorization server parameters owned from the client
            //this values are issued from the authorization server to the client through a separate process (registration, etc...)
            Uri authorizationServerTokenIssuerUri = new Uri("http://localhost:50151/connect/token");
            string clientId = "ClientIdThatCanOnlyRead";    
            string clientSecret = "secret1";
            string scope = "scope.readaccess";

            //access token request
            string rawJwtToken = RequestTokenToAuthorizationServer(

            //...some more code

The important part is in the method RequestTokenToAuthorizationServer. As you can see, it contains a simple POST request submitting the client credentials assigned to us from the AuthorizationServer:

        private static async Task<string> RequestTokenToAuthorizationServer(Uri uriAuthorizationServer, string clientId, string scope, string clientSecret)
            HttpResponseMessage responseMessage;
            using (HttpClient client = new HttpClient())
                HttpRequestMessage tokenRequest = new HttpRequestMessage(HttpMethod.Post, uriAuthorizationServer);
                HttpContent httpContent = new FormUrlEncodedContent(
                    new KeyValuePair<string, string>("grant_type", "client_credentials"),
                    new KeyValuePair<string, string>("client_id", clientId),
                    new KeyValuePair<string, string>("scope", scope),
                    new KeyValuePair<string, string>("client_secret", clientSecret)
                tokenRequest.Content = httpContent;
                responseMessage = await client.SendAsync(tokenRequest);
            return await responseMessage.Content.ReadAsStringAsync();
About the specified ClientId, ClientSecret and Scope

The ClientId, ClientSecret and Scope are normally known to the caller. You, as a user of the API, are supposed to know your ClientId, ClientSecret and which scope is associated to these credentials. If you try to get a token for a different scope than the one connected to these credentials, you will get an error as this is exactly what the Authorization Server is supposed to check before issuing the token, to avoid giving you a wrong authorization.

Call the secured WebAPI providing the JWT token

Now that we have the token, we can use it to perform a request to the WebAPI. Here the easy piece of code that does the work. This method is also called in the Program.Cs, in the main file:

 private static async Task<string> RequestValuesToSecuredWebApi(AuthorizationServerAnswer authorizationServerToken)
            HttpResponseMessage responseMessage;
            using (HttpClient httpClient = new HttpClient())
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authorizationServerToken.access_token);
                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:56087/api/values");
                responseMessage = await httpClient.SendAsync(request);

            return await responseMessage.Content.ReadAsStringAsync();

The only important difference with a generic HttpRequest is that we added an AuthorizationHeader. This authorization header carries the token and is inspected from the authorization middleware (in our case IdentityServer4) configured in the Web API server. 

Run everything together

We are almost at the end. It's time to run all these pieces together. To make the example working you will have to download and launch also the Authorization Server that I built in this article.

If you have everything ready, here what to run in which order. While you are getting familiar with the various pieces, it could be easier if you launch every project from a separate instance of VS2017:

  • Launch the Authorization Server first.
  • Launch then the ProtectedWebAPI Server.
  • Finally launch the ConsoleTestClient. Check in the console output that you read the answer from the WebApi server.

Enjoy the result of all this hard work.


 This article is meant to be just an introductory tutorial to the client credentials authentication following the OAuth2 framework.  We touched many different aspects: HttpRequest/Responses and WebAPIs in .NET Core, the Identity Server middleware, JWT Tokens, etc.... Much more can be done, configured, explored.

Once again, my goal is just to share with other readers my understanding about these concepts and some possible approaches for an implementation, not necessarily the best one. As usual, any comment or feedback or question will be very much appreciated, in the spirit of a community where we can all learn from each other. 

Code on GITHub

As usual, attached to this article there is a downloadable version of the code, but if for some reason you prefer github, here is the public repository.

What is OAuth

It’s important to understand how a program, website, or app might authenticate you as a user – do they have the right permissions? Have you granted them some sort of way of verifying who you are – and accessing data on your behalf? OAuth helps streamline this process: but even with automation, always be aware of how a person or company uses (or stores) your data.

What is OAuth?

OAuth is an open-standard authorization protocol or framework that provides applications the ability for “secure designated access.” For example, you can tell Facebook that it’s OK for to access your profile or post updates to your timeline without having to give ESPN your Facebook password. This minimizes risk in a major way: In the event ESPN suffers a breach, your Facebook password remains safe.

OAuth doesn’t share password data but instead uses authorization tokens to prove an identity between consumers and service providers. OAuth is an authentication protocol that allows you to approve one application interacting with another on your behalf without giving away your password.

SAML vs. OAuth

SAML (Security Assertion Markup Language) is an alternative federated authentication standard that many enterprises use for Single-Sign On (SSO). SAML enables enterprises to monitor who has access to corporate resources.

There are many differences between SAML and OAuth. SAML uses XML to pass messages, and OAuth uses JSON. OAuth provides a simpler mobile experience, while SAML is geared towards enterprise security. That last point is a key differentiator: OAuth uses API calls extensively, which is why mobile applications, modern web applications, game consoles, and Internet of Things (IoT) devices find OAuth a better experience for the user. SAML, on the other hand, drops a session cookie in a browser that allows a user to access certain web pages – great for short-lived work days, but not so great when have to log into your thermostat every day.

OAuth Examples

The simplest example of OAuth in action is one website saying “hey, do you want to log into our website with other website’s login?” In this scenario, the only thing the first website – let’s refer to that website as the consumer – wants to know is that the user is the same user on both websites and has logged in successfully to the service provider – which is the site the user initially logged into, not the consumer.

Facebook apps are a good OAuth use case example. Say you’re using an app on Facebook, and it asks you to share your profile and pictures. Facebook is, in this case, the service provider: it has your login data and your pictures. The app is the consumer, and as the user, you want to use the app to do something with your pictures. You specifically gave this app access to your pictures, which OAuth is managing in the background.

Your smart home devices – toaster, thermostat, security system, etc. – probably use some kind of login data to sync with each other and allow you to administer them from a browser or client device. These devices use what OAuth calls confidential authorization. That means they hold onto the secret key information, so you don’t have to log in over and over again.


OAuth Explained

OAuth is about authorization and not authentication. Authorization is asking for permission to do stuff. Authentication is about proving you are the correct person because you know things. OAuth doesn’t pass authentication data between consumers and service providers – but instead acts as an authorization token of sorts.

The common analogy I’ve seen used while researching OAuth is the valet key to your car. The valet key allows the valet to start and move the car but doesn’t give them access to the trunk or the glove box.

OAuth Explained
An OAuth token is like that valet key. As a user, you get to tell the consumers what they can use and what they can’t use from each service provider. You can give each consumer a different valet key. They never have the full key or any of the private data that gives them access to the full key.


How OAuth Works

There are 3 main players in an OAuth transaction: the user, the consumer, and the service provider.  This triumvirate has been affectionately deemed the OAuth Love Triangle.

In our example, Joe is the user, Bitly is the consumer, and Twitter is the service provided who controls Joe’s secure resource (his Twitter stream).  Joe would like Bitly to be able to post shortened links to his stream.  Here’s how it works:

Step 1 – The User Shows Intent

·       Joe (User): “Hey, Bitly, I would like you to be able to post links directly to my Twitter stream.”

·       Bitly (Consumer): “Great! Let me go ask for permission.”

Step 2 – The Consumer Gets Permission

·       Bitly: “I have a user that would like me to post to his stream. Can I have a request token?”

·       Twitter (Service Provider): “Sure.  Here’s a token and a secret.”

The secret is used to prevent request forgery.  The consumer uses the secret to sign each request so that the service provider can verify it is actually coming from the consumer application.

Step 3 – The User Is Redirected to the Service Provider

·       Bitly: “OK, Joe.  I’m sending you over to Twitter so you can approve.  Take this token with you.”

·       Joe: “OK!”

<Bitly directs Joe to Twitter for authorization>

This is the scary part. If Bitly were super-shady Evil Co. it could pop up a window that looked like Twitter but was really phishing for your username and password.  Always be sure to verify that the URL you’re directed to is actually the service provider (Twitter, in this case).

Step 4 – The User Gives Permission

·       Joe: “Twitter, I’d like to authorize this request token that Bitly gave me.”

·       Twitter: “OK, just to be sure, you want to authorize Bitly to do X, Y, and Z with your Twitter account?”

·       Joe: “Yes!”

·       Twitter: “OK, you can go back to Bitly and tell them they have permission to use their request token.”

Twitter marks the request token as “good-to-go,” so when the consumer requests access, it will be accepted (so long as it’s signed using their shared secret).

Step 5 – The Consumer Obtains an Access Token

·       Bitly: “Twitter, can I exchange this request token for an access token?”

·       Twitter: “Sure.  Here’s your access token and secret.”

Step 6 – The Consumer Accesses the Protected Resource

·       Bitly: “I’d like to post this link to Joe’s stream.  Here’s my access token!”

·       Twitter: “Done!”

In our scenario, Joe never had to share his Twitter credentials with Bitly.  He simply delegated access using OAuth in a secure manner.  At any time, Joe can login to Twitter and review the access he has granted and revoke tokens for specific applications without affecting others.  OAuth also allows for granular permission levels.  You can give Bitly the right to post to your Twitter account, but restrict LinkedIn to read-only access.

OAuth 1.0 vs. OAuth 2.0

OAuth 2.0 is a complete redesign from OAuth 1.0, and the two are not compatible. If you create a new application today, use OAuth 2.0. This blog only applies to OAuth 2.0, since OAuth 1.0 is deprecated.

OAuth 2.0 is faster and easier to implement. OAuth 1.0 used complicated cryptographic requirements, only supported three flows, and did not scale.

OAuth 2.0, on the other hand, has six flows for different types of applications and requirements, and enables signed secrets over HTTPS. OAuth tokens no longer need to be encrypted on the endpoints in 2.0 since they are encrypted in transit.

Other Resources

Hopefully this was a good primer to get you familiar with OAuth so the next time you see “Sign-in with Twitter” or similar delegated identity verification, you’ll have a good idea of what is going on.

If you want to dive deeper in into the mechanics of OAuth, here are some helpful links:







Popular Posts