{"id":2370,"date":"2018-07-09T07:00:21","date_gmt":"2018-07-09T06:00:21","guid":{"rendered":"https:\/\/code-maze.com\/?p=2370"},"modified":"2025-02-25T10:40:42","modified_gmt":"2025-02-25T09:40:42","slug":"authentication-aspnetcore-jwt-1","status":"publish","type":"post","link":"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/","title":{"rendered":"JWT Authentication in ASP.NET Core Web API"},"content":{"rendered":"<p>Securing a web application is one of the most important jobs to do and usually one of the hardest things to pull off. In this series, we are going to<span style=\"color: #ff6600;\">\u00a0<\/span>learn how to implement JWT authentication in ASP.Net Core Web API on the server-side and Angular on the client side.<\/p>\n<p>We are also going to learn how<span style=\"color: #ff6600;\">\u00a0<\/span>authentication works in general and how to utilize JSON web tokens to securely transmit the user\u2019s credentials from the<span style=\"color: #ff6600;\">\u00a0<\/span>server to the client and vice versa.<\/p>\n<hr \/>\r\n<p style=\"text-align: center;\"><strong>VIDEO<\/strong>: ASP.NET Core Authentication with JWT and Angular - Part 1.<\/p>\r\n<p style=\"text-align: center;\"><iframe width=\"560\" height=\"315\" src=https:\/\/www.youtube.com\/embed\/vlRqxCpCKGU frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen=\"allowfullscreen\"><\/iframe><\/p>\r\n<hr \/>\n<p><span style=\"color: #ff6600;\"><span style=\"color: #000000;\">Therefore, we are going to divide this series into three parts.<\/span><\/span><span style=\"color: #000000;\">\u00a0<strong>In<\/strong><\/span><strong>\u00a0the first part<\/strong>, we\u00a0<span style=\"color: #ff6600;\"><span style=\"color: #000000;\">are going to<\/span><\/span> implement a JWT authentication in ASP.NET Core Web API and see how the integration process works between Web API and JWT (JSON web token). In <a href=\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-2\/\" target=\"_blank\" rel=\"noopener noreferrer\">the second part<\/a>, we are going to implement front-end features like<span style=\"color: #ff6600;\">\u00a0<\/span>login, logout, securing routes, and role-based authorization with Angular. Finally, in <a href=\"https:\/\/code-maze.com\/using-refresh-tokens-in-asp-net-core-authentication\/\" target=\"_blank\" rel=\"noopener noreferrer\">the third part of the series<\/a>, we are going to learn about refresh tokens and their use in modern web applications.<\/p>\n<ul id=\"series_parts\" style=\"display: none;\">\n<li><a href=\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-2\/\" target=\"_blank\" rel=\"noopener noreferrer\">ASP.NET Core Authentication with JWT and Angular &#8211; Part 2<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/net-core-series\/\" target=\"_blank\" rel=\"noopener noreferrer\">.NET Core Tutorial<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/different-ways-consume-restful-api-csharp\/\" target=\"_blank\" rel=\"noopener noreferrer\">Consume Restful API in C#<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/enabling-cors-in-asp-net-core\/\" target=\"_blank\" rel=\"noopener noreferrer\">Enabling CORS in ASP.NET Core Web API<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/upload-files-dot-net-core-angular\/\" target=\"_blank\" rel=\"noopener noreferrer\">Uploading Files with .NET Core and Angular<\/a><\/li>\n<\/ul>\n<div style=\"padding: 20px; border-left: 5px #dc2323 solid; display: block; margin-bottom: 20px; box-shadow: 1px 1px 5px 0px lightgrey;\">To download the source code for this article, you can visit our <a href=\"https:\/\/github.com\/CodeMazeBlog\/aspnetcore-jwt-auth\" target=\"_blank\" rel=\"nofollow noopener\">GitHub repository<\/a>.<\/div>\n<p>So, let&#8217;s start.<\/p>\n<h2 id=\"sec1\">The Big Picture of JWT Authentication<\/h2>\n<p>Before we get into the implementation of authentication and authorization, let\u2019s have a quick look at the JWT authentication big picture. There is an application that has a login form. A user enters<span style=\"color: #ff6600;\">\u00a0<\/span>their username, and password and presses the login button. After pressing the login button, a client (eg web browser) sends the user\u2019s data to the server&#8217;s <strong>API<\/strong> endpoint:<a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/picture_1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-2169 size-full alignnone\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/picture_1-e1650647612114.png\" alt=\"web authentication big picture\" width=\"824\" height=\"189\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/picture_1-e1650647612114.png 824w, https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/picture_1-e1650647612114-300x69.png 300w, https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/picture_1-e1650647612114-768x176.png 768w\" sizes=\"auto, (max-width: 824px) 100vw, 824px\" \/><\/a><\/p>\n<p>When the server validates<span style=\"color: #ff6600;\">\u00a0<\/span>the user\u2019s credentials and confirms that the user is valid, it&#8217;s going to send an encoded JWT to the client. JSON web token is basically a JavaScript object that can contain some attributes of the logged-in user. It can contain a username, user subject, user roles, or some other useful information.<\/p>\n<p>On the client-side, we store the JWT in the browser\u2019s storage to remember the user\u2019s login session. We may also use the information from the JWT to enhance the security of our application as well.<\/p>\n<h2 id=\"sec2\">What is JWT (JSON Web Token)<\/h2>\n<p>JSON web tokens enable a secure way to transmit data between two parties in the form of a JSON object. It\u2019s an open standard and it&#8217;s a popular\u00a0mechanism for web authentication. In our case, we are going to use JSON web tokens to securely transfer a user\u2019s data between the client and the server.<\/p>\n<p>JSON web tokens consist of<span style=\"color: #ff6600;\">\u00a0<\/span>three basic parts: the header, payload, and signature.<\/p>\n<p>One real example of a JSON web token:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-2371 size-full alignnone\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/2.png\" alt=\"JWT example\" width=\"527\" height=\"137\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/2.png 527w, https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/2-300x78.png 300w\" sizes=\"auto, (max-width: 527px) 100vw, 527px\" \/><\/p>\n<p>Different token parts are shown with different colors:<\/p>\n<h3><strong>Header<\/strong><\/h3>\n<p>The first part of\u00a0JWT is the Header, <strong>which is a JSON object encoded in the base64 format<\/strong>. The header is a standard part of JWT and we don\u2019t have to worry about it. It contains information like the<span style=\"color: #ff6600;\">\u00a0<\/span>type of token and the name of the algorithm:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">{ \r\n    \"alg\": \"HS256\", \r\n    \"typ\": \"JWT\" \r\n}<\/pre>\n<h3><strong>Payload<\/strong><\/h3>\n<p>After the Header, we have a Payload which is also a JavaScript object encoded in the base64 format. The payload contains some attributes about the logged-in user. For example, it can contain the user id, user subject, and information about whether a user is an admin user or not. <strong>JSON web tokens are not encrypted<\/strong> and can be decoded with any base64 decoder so we should <strong>never include sensitive information in the Payload:<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">{ \r\n    \"sub\": \"1234567890\", \r\n    \"name\": \"John Doe\", \r\n    \"iat\": 1516239022 \r\n}<\/pre>\n<h3><strong>Signature<\/strong><\/h3>\n<p>Finally, we have the Signature part. Usually, the server uses the signature part to verify whether the token contains valid information &#8211; the information the server is issuing. It is a digital signature that gets generated by combining the header and the payload together. Moreover, it&#8217;s based on a secret key that only the server knows:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-2372 size-full alignnone\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/3.png\" alt=\"JWT signature composition\" width=\"321\" height=\"154\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/3.png 321w, https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/3-300x144.png 300w\" sizes=\"auto, (max-width: 321px) 100vw, 321px\" \/><\/p>\n<p>So,\u00a0if malicious users try to modify<span style=\"color: #ff6600;\">\u00a0<\/span>the values in the payload, they have to recreate the signature and for that purpose, they need the secret key that only the server knows about. On the server side, we can easily verify if the values are original or not by comparing the original signature with a new signature computed from the values coming from the client.<\/p>\n<p>So, we can easily verify the integrity of our data just by comparing the digital signatures. This is the reason why we use JWT.<\/p>\n<h2 id=\"sec3\">Creating ASP.NET Core Web API Project<\/h2>\n<p>Now let\u2019s create a brand new ASP.NET Core Web API project. We can create a new Web API project with .NET Core CLI or we can use Visual Studio. For this article, let&#8217;s use Visual Studio.<\/p>\n<p>We can open the <code>launchSettings.json<\/code> file and modify the applicationUrl property:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">\"applicationUrl\": \"https:\/\/localhost:5001;http:\/\/localhost:5000\"<\/code><\/p>\n<p>Now, we can start our project.<\/p>\n<p>As a result, we will see our application hosted at <code>https:\/\/localhost:5001<\/code> and the browser automatically sends a GET request to <code>\/weatherforecast<\/code>.<\/p>\n<p>So far so good.<\/p>\n<p>In the next step, we are going to configure JWT authentication in our application.<\/p>\n<h2 id=\"sec4\">Configuring JWT Authentication<\/h2>\n<p>To configure JWT authentication in .NET Core, we need to modify <code>Program.cs<\/code>file. <strong>If you are using .NET Core version 5, you have to add the modifications in the<\/strong> <code>Startup.cs<\/code><strong> file inside the<\/strong> <code>ConfigureServices<\/code><strong> method<\/strong>.<\/p>\n<p>For the sake of simplicity, we are going to add all the code inside the <code>Program<\/code> class. But the better practice is to use <a href=\"https:\/\/code-maze.com\/csharp-static-members-constants-extension-methods\/\" target=\"_blank\" rel=\"noopener\">Extension methods<\/a> so we could free our class from extra code lines. If you want to learn how to do that, and to learn more about configuring the .NET Core Web API project, check out: <a href=\"https:\/\/code-maze.com\/net-core-web-development-part2\/\" target=\"_blank\" rel=\"noopener noreferrer\">.NET Core Service Configuration.<\/a><\/p>\n<p>First, let&#8217;s install the <code>Microsoft.AspNetCore.Authentication.JwtBearer<\/code> NuGet package that we require to work with JWT in the ASP.NET Core app:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">Install-Package Microsoft.AspNetCore.Authentication.JwtBearer<\/code><\/p>\n<p>Next, let&#8217;s add the code to configure JWT right above the <code>builder.Services.AddControllers()<\/code> line:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">builder.Services.AddAuthentication(opt =&gt; {\r\n    opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;\r\n    opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;\r\n})\r\n    .AddJwtBearer(options =&gt;\r\n    {\r\n        options.TokenValidationParameters = new TokenValidationParameters\r\n        {\r\n            ValidateIssuer = true,\r\n            ValidateAudience = true,\r\n            ValidateLifetime = true,\r\n            ValidateIssuerSigningKey = true,\r\n            ValidIssuer = \"https:\/\/localhost:5001\",\r\n            ValidAudience = \"https:\/\/localhost:5001\",\r\n            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(\"superSecretKey@345\"))\r\n        };\r\n    });<\/pre>\n<p>In order for this to work, we have to add a few using directives:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">using Microsoft.AspNetCore.Authentication.JwtBearer;\r\nusing Microsoft.IdentityModel.Tokens;\r\nusing System.Text;<\/pre>\n<h3>JWT Configuration Explanation<\/h3>\n<p>Firstly, we register the JWT authentication middleware by calling the <code>AddAuthentication<\/code> method. Next, we specify the default authentication scheme <code>JwtBearerDefaults.AuthenticationScheme<\/code> as well as <code>DefaultChallengeScheme<\/code>.<\/p>\n<p>By calling the AddJwtBearer method, we enable the JWT authenticating using the default scheme, and we pass a parameter, which we use to set up JWT bearer options:<\/p>\n<ul>\n<li>The issuer is the actual server that created\u00a0the token <strong>(ValidateIssuer=true)<\/strong><\/li>\n<li>The receiver of the token is a valid recipient <strong>(ValidateAudience=true)<\/strong><\/li>\n<li>The token has not expired <strong>(ValidateLifetime=true)<\/strong><\/li>\n<li>The signing key is valid and is trusted by the server <strong>(ValidateIssuerSigningKey=true)<\/strong><\/li>\n<\/ul>\n<p>Additionally, we are providing values for the issuer, audience, and the secret key that the server uses to generate the signature for JWT.<\/p>\n<p>We are going to hardcode both username and password for the sake of simplicity. But, the best practice is to put the credentials in a database or a configuration file or to store the secret key in the environment variable.<\/p>\n<p>There is one more step we need to do to make our authentication middleware available to the application:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-highlight=\"3\">app.UseHttpsRedirection();\r\n\r\napp.UseAuthentication();\r\napp.UseAuthorization();\r\n\r\napp.MapControllers();\r\n\r\napp.Run();<\/pre>\n<p>And that\u2019s all we need to configure the JWT authentication in ASP.NET Core. <strong>This is something we would do in the <\/strong><code>Configure<\/code><strong> method inside the <\/strong><code>Startup<\/code><strong> class if we were using the .NET 5 app.<\/strong><\/p>\n<h2 id=\"sec5\">Securing API Endpoints<\/h2>\n<p>We already have an API endpoint <code>\/weatherforecast<\/code> to get some example weather information and that endpoint is not secure. Anyone can send a request to <code>https:\/\/localhost:5001\/weatherforecast<\/code> to fetch the values. So, in this section, we are going to add a new <strong>api\/customers <\/strong>endpoint to serve a list of the customers. This endpoint is going to be secure from anonymous users and only logged-in users will be able to consume it.<\/p>\n<p>Now, let&#8217;s add an empty <code>CustomersController<\/code> in the <code>Controllers<\/code> folders. Inside the controller, we are going to add a <code>Get<\/code> action method that is going to return an array of customers. More importantly, we are going to add an extra security layer by decorating the action method with the<code>[Authorize]<\/code> attribute so only logged-in users can access the route:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">[Route(\"api\/[controller]\")]\r\n[ApiController]\r\npublic class CustomersController : ControllerBase\r\n{\r\n    [HttpGet, Authorize]\r\n    public IEnumerable&lt;string&gt; Get()\r\n    {\r\n        return new string[] { \"John Doe\", \"Jane Doe\" };\r\n    }\r\n}<\/pre>\n<p>To be able to use the Authorize attribute we have to add a new using directive inside the file:<\/p>\n<p><code class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">using Microsoft.AspNetCore.Authorization;<\/code><\/p>\n<p><code>Authorize<\/code> attribute on top of the <strong>GET\u00a0<\/strong>method restricts access to only authorized users. Only users who are logged in can fetch the list of customers. Therefore, this time if we make a request to <code>https:\/\/localhost:5001\/api\/customers<\/code> from the browser\u2019s address bar, instead of getting a list of customers, we are going to get a <code>401 Not Authorized<\/code> response:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-2374 size-full alignnone\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/5.png\" alt=\"HTTP 401 Not Authorized response\" width=\"448\" height=\"126\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/5.png 448w, https:\/\/code-maze.com\/wp-content\/uploads\/2018\/04\/5-300x84.png 300w\" sizes=\"auto, (max-width: 448px) 100vw, 448px\" \/><\/p>\n<h2 id=\"sec6\">Adding Login Endpoint<\/h2>\n<p>To authenticate anonymous users, we have to provide a login endpoint so the users can log in and access protected resources. A user is going to provide a username and password, and if the credentials are valid we are going to issue a JSON web token for the requesting client.<\/p>\n<p>In addition, before we start implementing the authentication controller, we need to add a <code>LoginModel<\/code> to hold user\u2019s credentials on the server. <code>LoginModel<\/code>\u00a0is a simple class that contains two properties:\u00a0<code>UserName<\/code> and <code>Password<\/code>.\u00a0 We are going to create a <code>Models<\/code> folder in the root directory and inside it a\u00a0<code>LoginModel<\/code>\u00a0class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class LoginModel\r\n{\r\n    public string? UserName { get; set; }\r\n    public string? Password { get; set; }\r\n}<\/pre>\n<p>Also, let&#8217;s create one more class inside the same Models folder:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public class AuthenticatedResponse\r\n{\r\n    public string? Token { get; set; }\r\n}<\/pre>\n<p>We will see in a minute why we need this class.<\/p>\n<p>Now let\u2019s create the\u00a0<code>AuthController<\/code> inside the <code>Controllers<\/code> folder.<\/p>\n<p>Inside the\u00a0<code>AuthController<\/code>we are going to add the <code>Login<\/code> action to validate the user\u2019s credentials. If the credentials are valid, we are going to issue a JSON web token. For this demo, we are going to hardcode the username and password to implement a fake user. After validating the user\u2019s credentials we are going to generate a JWT with a secret key. JWT uses the secret key to generate the signature.<\/p>\n<p>So, let&#8217;s implement the <code>AuthController<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">[Route(\"api\/[controller]\")]\r\n[ApiController]\r\npublic class AuthController : ControllerBase\r\n{\r\n    [HttpPost(\"login\")]\r\n    public IActionResult Login([FromBody] LoginModel user)\r\n    {\r\n        if (user is null)\r\n        {\r\n            return BadRequest(\"Invalid client request\");\r\n        }\r\n\r\n        if (user.UserName == \"johndoe\" &amp;&amp; user.Password == \"def@123\")\r\n        {\r\n            var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(\"superSecretKey@345\"));\r\n            var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);\r\n            var tokeOptions = new JwtSecurityToken(\r\n                issuer: \"https:\/\/localhost:5001\",\r\n                audience: \"https:\/\/localhost:5001\",\r\n                claims: new List&lt;Claim&gt;(),\r\n                expires: DateTime.Now.AddMinutes(5),\r\n                signingCredentials: signinCredentials\r\n            );\r\n\r\n            var tokenString = new JwtSecurityTokenHandler().WriteToken(tokeOptions);\r\n\r\n            return Ok(new AuthenticatedResponse { Token = tokenString });\r\n        }\r\n\r\n        return Unauthorized();\r\n    }\r\n}<\/pre>\n<h3>Login Action Explanation<\/h3>\n<p>We decorate our <code>Login<\/code> action with the <code>HttpPost<\/code> attribute. Inside the login method, we create the <code>SymmetricSecretKey<\/code>\u00a0with\u00a0the secret key value <strong>superSecretKey@345.\u00a0<\/strong>Then, we create the <code>SigningCredentials<\/code> object and as arguments, we provide a secret key and the<span style=\"color: #ff6600;\">\u00a0<\/span>name of the algorithm that we are going to use to encode the token.<\/p>\n<p>Here comes the interesting part.<\/p>\n<p>The first two steps are the standard steps that we don\u2019t need to worry about. The third step is the one that we are interested in. In the third step, we create the <code>JwtSecurityToken<\/code> object with\u00a0some important parameters:<\/p>\n<ul>\n<li><strong>Issuer: <\/strong>The first parameter is a simple <code>string<\/code> representing the name of the webserver that issues the token<\/li>\n<li><strong>Audience:<\/strong>\u00a0The second parameter is a <code>string<\/code> value representing valid recipients<\/li>\n<li><strong>Claims: <\/strong>The third argument is a list of user roles, for example, the user can be an admin, manager, or author (we are going to add roles in <a href=\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-2\/\" target=\"_blank\" rel=\"noopener\">the next post<\/a>)<\/li>\n<li><strong>Expires:<\/strong> The fourth argument is the <code>DateTime<\/code> object that represents the date and time after which the token expires<\/li>\n<\/ul>\n<p>Then, we create a string representation of JWT by calling the <code>WriteToken<\/code> method on\u00a0<code>JwtSecurityTokenHandler<\/code><strong>. <\/strong>Finally, we return JWT in a response. As a response, we create the <code>AuthenticatedResponse<\/code> object that contains only the <code>Token<\/code> property.<\/p>\n<h2 id=\"sec7\">Testing the JWT Authentication<\/h2>\n<p>Now, let&#8217;s start our application. Also, we are going to use Postman to send requests.<\/p>\n<p>That said, let&#8217;s send a POST request to <code>https:\/\/localhost:5001\/api\/auth\/login<\/code> and provide a request body:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"json\">{ \r\n    \"UserName\":\"johndoe\", \r\n    \"Password\": \"def@123\" \r\n}<\/pre>\n<p>In the response section, we are going to see a<code> 200 OK<\/code> response with the JWT string in the response body:<a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2019\/11\/02-Postam-Jwt-Response.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-49397 size-full\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2019\/11\/02-Postam-Jwt-Response.png\" alt=\"Postam Jwt Response\" width=\"825\" height=\"164\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2019\/11\/02-Postam-Jwt-Response.png 825w, https:\/\/code-maze.com\/wp-content\/uploads\/2019\/11\/02-Postam-Jwt-Response-300x60.png 300w, https:\/\/code-maze.com\/wp-content\/uploads\/2019\/11\/02-Postam-Jwt-Response-768x153.png 768w\" sizes=\"auto, (max-width: 825px) 100vw, 825px\" \/><\/a><\/p>\n<div style=\"padding: 20px; border-left: 5px #dc2323 solid; display: block; margin-bottom: 20px; box-shadow: 1px 1px 5px 0px lightgrey;\">In the articles to come, we are going to learn how <a href=\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-2\/\" target=\"_blank\" rel=\"noopener noreferrer\">to consume this token in an Angular application<\/a> and additionally <a href=\"https:\/\/code-maze.com\/using-refresh-tokens-in-asp-net-core-authentication\/\" target=\"_blank\" rel=\"noopener noreferrer\">how to refresh a token in a web application<\/a>.<\/div>\n<h2 id=\"sec8\">Conclusion<\/h2>\n<p>In this post, we have learned more about security and how it is a crucial part of web application development. We talked about what JWT is and how it fits in the implementation of web security. Additionally, we&#8217;ve seen how to use the <code>Authorize<\/code> attribute to protect our action, and how to implement a Login action that issues a new JWT if a login is successful.<\/p>\n<p><a href=\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-2\/\" target=\"_blank\" rel=\"noopener noreferrer\">In the next part<\/a>, we are going to implement a front-end side of our application with Angular.<span style=\"color: #ff6600;\">\u00a0<\/span>We are going to implement <a href=\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-2\/\" target=\"_blank\" rel=\"noopener noreferrer\">login, logout, authorization, secure the routes<\/a>, and much more.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Securing a web application is one of the most important jobs to do and usually one of the hardest things to pull off. In this series, we are going to\u00a0learn how to implement JWT authentication in ASP.Net Core Web API on the server-side and Angular on the client side. We are also going to learn [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":53270,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"categories":[12,2079],"tags":[22,23,29,28,80,79,73,74,76,75,72,45],"class_list":["post-2370","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-csharp","category-web-api","tag-net-core","tag-angular","tag-angular2","tag-angular4","tag-asp","tag-asp-net-core","tag-authentication","tag-authorization","tag-json-web-tokens","tag-jwt","tag-security","tag-web-development","et-has-post-format-content","et_post_format-et-post-format-standard"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>ASP.NET Core Web API JWT Authentication<\/title>\n<meta name=\"description\" content=\"In this article, we are going to learn how to provide a JWT authentication to secure our ASP.NET Core Web API app.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"ASP.NET Core Web API JWT Authentication\" \/>\n<meta property=\"og:description\" content=\"In this article, we are going to learn how to provide a JWT authentication to secure our ASP.NET Core Web API app.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/\" \/>\n<meta property=\"og:site_name\" content=\"Code Maze\" \/>\n<meta property=\"article:published_time\" content=\"2018-07-09T06:00:21+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-02-25T09:40:42+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/Jwt-Part1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1100\" \/>\n\t<meta property=\"og:image:height\" content=\"620\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Marinko Spasojevi\u0107\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/CodeMazeBlog\" \/>\n<meta name=\"twitter:site\" content=\"@CodeMazeBlog\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Marinko Spasojevi\u0107\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/\"},\"author\":{\"name\":\"Marinko Spasojevi\u0107\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/d6fa06e66820968d19b39fb63cff2533\"},\"headline\":\"JWT Authentication in ASP.NET Core Web API\",\"datePublished\":\"2018-07-09T06:00:21+00:00\",\"dateModified\":\"2025-02-25T09:40:42+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/\"},\"wordCount\":2028,\"commentCount\":62,\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/Jwt-Part1.png\",\"keywords\":[\".NET CORE\",\"Angular\",\"angular2\",\"angular4\",\"asp\",\"asp.net core\",\"authentication\",\"authorization\",\"json web tokens\",\"jwt\",\"security\",\"web development\"],\"articleSection\":[\"C#\",\"Web API\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/\",\"url\":\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/\",\"name\":\"ASP.NET Core Web API JWT Authentication\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/Jwt-Part1.png\",\"datePublished\":\"2018-07-09T06:00:21+00:00\",\"dateModified\":\"2025-02-25T09:40:42+00:00\",\"description\":\"In this article, we are going to learn how to provide a JWT authentication to secure our ASP.NET Core Web API app.\",\"breadcrumb\":{\"@id\":\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#primaryimage\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/Jwt-Part1.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/Jwt-Part1.png\",\"width\":1100,\"height\":620,\"caption\":\"JWT with ASP.NET Core and Angular Cover\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/code-maze.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"JWT Authentication in ASP.NET Core Web API\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/code-maze.com\/#website\",\"url\":\"https:\/\/code-maze.com\/\",\"name\":\"Code Maze\",\"description\":\"Learn. Code. Succeed.\",\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/code-maze.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/code-maze.com\/#organization\",\"name\":\"Code Maze\",\"url\":\"https:\/\/code-maze.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"width\":3511,\"height\":3510,\"caption\":\"Code Maze\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/CodeMazeBlog\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/d6fa06e66820968d19b39fb63cff2533\",\"name\":\"Marinko Spasojevi\u0107\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg\",\"caption\":\"Marinko Spasojevi\u0107\"},\"description\":\"Hi, my name is Marinko Spasojevic. Currently, I work as a full-time .NET developer and my passion is web application development. Just getting something to work is not enough for me. To make it just how I like it, it must be readable, reusable, and easy to maintain. Prior to being an author on the CodeMaze blog, I had been working as a professor of Computer Science for several years. So, sharing knowledge while working as a full-time developer comes naturally to me.\",\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/marinko-spasojevic\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog\"],\"url\":\"https:\/\/code-maze.com\/author\/marinko\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"ASP.NET Core Web API JWT Authentication","description":"In this article, we are going to learn how to provide a JWT authentication to secure our ASP.NET Core Web API app.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/","og_locale":"en_US","og_type":"article","og_title":"ASP.NET Core Web API JWT Authentication","og_description":"In this article, we are going to learn how to provide a JWT authentication to secure our ASP.NET Core Web API app.","og_url":"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/","og_site_name":"Code Maze","article_published_time":"2018-07-09T06:00:21+00:00","article_modified_time":"2025-02-25T09:40:42+00:00","og_image":[{"width":1100,"height":620,"url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/Jwt-Part1.png","type":"image\/png"}],"author":"Marinko Spasojevi\u0107","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/CodeMazeBlog","twitter_site":"@CodeMazeBlog","twitter_misc":{"Written by":"Marinko Spasojevi\u0107","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#article","isPartOf":{"@id":"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/"},"author":{"name":"Marinko Spasojevi\u0107","@id":"https:\/\/code-maze.com\/#\/schema\/person\/d6fa06e66820968d19b39fb63cff2533"},"headline":"JWT Authentication in ASP.NET Core Web API","datePublished":"2018-07-09T06:00:21+00:00","dateModified":"2025-02-25T09:40:42+00:00","mainEntityOfPage":{"@id":"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/"},"wordCount":2028,"commentCount":62,"publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"image":{"@id":"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/Jwt-Part1.png","keywords":[".NET CORE","Angular","angular2","angular4","asp","asp.net core","authentication","authorization","json web tokens","jwt","security","web development"],"articleSection":["C#","Web API"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/","url":"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/","name":"ASP.NET Core Web API JWT Authentication","isPartOf":{"@id":"https:\/\/code-maze.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#primaryimage"},"image":{"@id":"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/Jwt-Part1.png","datePublished":"2018-07-09T06:00:21+00:00","dateModified":"2025-02-25T09:40:42+00:00","description":"In this article, we are going to learn how to provide a JWT authentication to secure our ASP.NET Core Web API app.","breadcrumb":{"@id":"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#primaryimage","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/Jwt-Part1.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/07\/Jwt-Part1.png","width":1100,"height":620,"caption":"JWT with ASP.NET Core and Angular Cover"},{"@type":"BreadcrumbList","@id":"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/code-maze.com\/"},{"@type":"ListItem","position":2,"name":"JWT Authentication in ASP.NET Core Web API"}]},{"@type":"WebSite","@id":"https:\/\/code-maze.com\/#website","url":"https:\/\/code-maze.com\/","name":"Code Maze","description":"Learn. Code. Succeed.","publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/code-maze.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/code-maze.com\/#organization","name":"Code Maze","url":"https:\/\/code-maze.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","width":3511,"height":3510,"caption":"Code Maze"},"image":{"@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/CodeMazeBlog"]},{"@type":"Person","@id":"https:\/\/code-maze.com\/#\/schema\/person\/d6fa06e66820968d19b39fb63cff2533","name":"Marinko Spasojevi\u0107","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/person\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg","caption":"Marinko Spasojevi\u0107"},"description":"Hi, my name is Marinko Spasojevic. Currently, I work as a full-time .NET developer and my passion is web application development. Just getting something to work is not enough for me. To make it just how I like it, it must be readable, reusable, and easy to maintain. Prior to being an author on the CodeMaze blog, I had been working as a professor of Computer Science for several years. So, sharing knowledge while working as a full-time developer comes naturally to me.","sameAs":["https:\/\/www.linkedin.com\/in\/marinko-spasojevic\/","https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog"],"url":"https:\/\/code-maze.com\/author\/marinko\/"}]}},"_links":{"self":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/2370","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/comments?post=2370"}],"version-history":[{"count":2,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/2370\/revisions"}],"predecessor-version":[{"id":69630,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/2370\/revisions\/69630"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media\/53270"}],"wp:attachment":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media?parent=2370"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/categories?post=2370"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/tags?post=2370"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}