Saturday, 30 September 2023

Web API Versioning

What Is API Versioning?

API versioning is the process of iterating different versions of your API.

Why Is API Versioning Required?

While working on an existing application or creating a new one, we may create multiple APIs that may be consumed by many clients. When the business has started to grow and expand, new requirements arise. Due to this, we may need to provide more functionality in the existing APIs. However, existing Web API can be consumed by many clients so how to implement the new feature without impacting the existing consumers? We can solve this problem by versioning our API.

There are some common ways to version a REST API.

1. Versioning through URI

The most commonly used versioning is in which we can add a version to the API base URL.

Example:

http://api-demo.example.com/api/1/employee

This approach is easy to implement and understand, as clients can simply request the desired version of the API by specifying the corresponding URL. Here are the steps to implement URL-based versioning in ASP.NET Core:

Install the Microsoft.AspNetCore.Mvc.Versioning NuGet package in your ASP.NET Core project. You can do this using the Package Manager Console or the NuGet Package Manager in Visual Studio.

In the ConfigureServices method of your Startup.cs file, configure the API versioning options by adding the following code:

  services.AddApiVersioning(options =>
    {
        options.DefaultApiVersion = new ApiVersion(1, 0);
        options.AssumeDefaultVersionWhenUnspecified = true;
        options.ReportApiVersions = true;
        options.ApiVersionReader = new UrlSegmentApiVersionReader();
    });

This code configures the default API version to be 1.0, assumes the default version when not specified in the URL, reports the API versions in the response headers, and uses the URL segment as the versioning source.

In your controller, add the ApiVersion attribute to specify the supported API versions for each action method. For example:

  [ApiController]
  [Route("api/v{version:apiVersion}/[controller]")]
  [ApiVersion("1.0")]
  public class MyController : ControllerBase
  {
      [HttpGet]
      public IActionResult Get()
      {
          return Ok("Version 1.0");
      }
     
      [HttpGet, MapToApiVersion("2.0")]
      public IActionResult GetV2()
      {
          return Ok("Version 2.0");
      }
  }

This code specifies that the controller supports version 1.0 of the API, and that the GetV2 action method supports version 2.0. The [MapToApiVersion] attribute maps the action method to version 2.0.

Test the API by sending requests to the corresponding URLs. For example:

http://localhost:5000/api/v1.0/my -> returns "Version 1.0"

http://localhost:5000/api/v2.0/my -> returns "Version 2.0"

By using URL-based versioning in ASP.NET Core, you can easily manage different versions of your API and provide backward compatibility to existing clients.

2. Query String

Another option for versioning a REST API is to include the version number as a query parameter.

This is a straightforward way to version an API from an implementation point of view.

Example:

https://api-demo.example.com/api/employee/?api-version=2

Follow the same steps and code as mentioned above. change code for AddApiVersioning method. in this only  ApiVersionReader  property is changed.

  services.AddApiVersioning(options =>
    {
        options.DefaultApiVersion = new ApiVersion(1, 0);
        options.AssumeDefaultVersionWhenUnspecified = true;
        options.ReportApiVersions = true;
        options.ApiVersionReader = new QueryStringApiVersionReader("version");
    });

Test the API by sending requests with the "version" query parameter. For example:

http://localhost:5000/api/my?version=1.0 -> returns "Version 1.0"

http://localhost:5000/api/my?version=2.0 -> returns "Version 2.0"

By using query string-based versioning in ASP.NET Core, you can provide a flexible and convenient way for clients to specify the desired version of your API.

3. Custom headers

Define a new header that contains the version number in the request as part of the request header itself.

Example:

GET https://api-demo.example.com/api/employee
Accept-Version: 3

Follow the same steps and code as mentioned above. change code for AddApiVersioning method. in this only  ApiVersionReader  property is changed.

  services.AddApiVersioning(options =>
    {
        options.DefaultApiVersion = new ApiVersion(1, 0);
        options.AssumeDefaultVersionWhenUnspecified = true;
        options.ReportApiVersions = true;
        options.ApiVersionReader = new HeaderApiVersionReader("X-Version");
    });

This code configures the default API version to be 1.0, assumes the default version when not specified in the header, reports the API versions in the response headers, and uses the "X-Version" header as the versioning source.

Test the API by sending requests with the "X-Version" header. For example:

http://localhost:5000/api/my

X-Version: 1.0 -> returns "Version 1.0"

X-Version: 2.0 -> returns "Version 2.0"

By using header-based versioning in ASP.NET Core, you can provide a flexible and non-intrusive way for clients to specify the desired version of your API.

Learn More: https://codelikeadev.com/https://www.c-sharpcorner.com/
                        https://www.dotnettricks.com/https://blog.devart.com/


Continue Reading →

Wednesday, 2 August 2023

Dotnet Core Versions

.NET Core is a cross-platform, open-source framework developed by Microsoft for building modern, scalable, and high-performance applications. It has since been unified with .NET Framework into a single product under the name ".NET" (starting with version 5), which is a continuation of .NET Core.

Here’s a summary of the evolution and versions of .NET Core:

  1. .NET Core 1.0 - Released in June 2016.
  2. .NET Core 1.1 - Released in November 2016.
  3. .NET Core 2.0 - Released in August 2017.
  4. .NET Core 2.1 - Released in May 2018 (LTS).
  5. .NET Core 2.2 - Released in December 2018.
  6. .NET Core 3.0 - Released in September 2019.
  7. .NET Core 3.1 - Released in December 2019 (LTS).

After .NET Core 3.1, the versioning transitioned to .NET 5:

  1. .NET 5 - Released in November 2020 (marks the unification of .NET Core and .NET Framework).
  2. .NET 6 - Released in November 2021 (LTS).
  3. .NET 7 - Released in November 2022.
  4. .NET 8 - Released in November 2023 (LTS).

The versioning structure now focuses on just ".NET", where .NET Core versions are no longer distinct, and the term ".NET Core" has been replaced by ".NET". .NET 5 and onwards represent the unified platform that evolved from .NET Core.

To check the version of .NET (whether .NET Core or the latest .NET versions), you can use the command:

dotnet --version

Continue Reading →

Monday, 10 July 2023

Use of Dynamic in C#

 Dynamic type has been added to C# since C# 4.0 (.NET 4.5) and its main purpose is to bypass the static type checks and add more flexibility to the language. 

Static vs Dynamic Languages

As you might be aware, the software development languages are divided into two major categories: static languages and dynamic languages. The main difference between a static and a dynamic language is how it handles its types (or doesn’t).

in the static languages variables are resolved during “compile time” and in the dynamic in the “runtime”.

What does this really mean though?

In a static language, a variable is assigned its type when the project is compiled.
In a dynamic language, a variable can change it’s type several times while the application is already running.

Some examples of static and dynamic languages:

Static: C , C# , F# , C++ , Java , Go

Dynamic: Javascript , Python , Ruby , PHP , Perl , Objective-C

Advantages of Static and Dynamic Languages

Static languages are generally considered to be faster because they resolve their types during the compilation phase. This helps improve the application performance and optimization. Excluding machine language and Assembly, fastest high-level languages are probably C and C++. No other languages can still match the speed of these two because of their memory management capabilities.

Besides being fast, static languages are also being fast to fail. You’ll find a lot of bugs even before the application has started because of the compiler checks. This means fewer bugs once the application is up and running.

On the other hand dynamic languages, while being slower, are much easier to write. And you can write them faster without having to think about which type to use or how to initialize it.

What is Dynamic Type in C#

So we already mentioned that C# is a statically typed language. So what does a dynamic type has to do with C#?

The dynamic type has been added to C# since version 4 as because of the need to improve interoperability with COM (Component Object Model) and other dynamic languages. While that can be achieved with reflection, dynamic provides a natural and more intuitive way to implement the same code.

Dynamic type in C# is instantiated by using the dynamic keyword and it can be assigned any other type.

Why Should We Use the Dynamic Type

By now, you probably have some ideas on where you can use dynamic type. But let’s go through some common scenarios in which dynamic could potentially improve our applications and make our lives as developers a bit easier.

First of all, let’s make it clear that dynamic is not a silver bullet. We shouldn’t use it just because we can.

While it has its benefits, dynamic objects are harder to work with while writing code, since we don’t have and Intelligence for them due to the nature of dynamic type. On the other hand, if have a need to implement dynamic type everywhere, we are probably using a wrong type of language. Dynamic languages are better suited for those kinds of cases.

So what are the common cases to apply dynamic to:

  1. Communicating with other dynamic languages
  2. Simplifying responses from API calls when we don’t know what type of object to expect (or we don’t care)
  3. Creating libraries that can be used between languages
  4. Making generic solutions when speed isn’t the main concern
  5. Replacing and simplifying reflection code

Why we shouldn’t use dynamic all the time because:

  1. It’s slower than statically typed code
  2. Increases a chance to get runtime exceptions
  3. Decreases code readability in some cases, and working with it is a bit harder due to the lack of IntelliSense

Reference: https://www.linkedin.com

Continue Reading →

Friday, 24 February 2023

View encapsulation in Angular

 In Angular, a component's styles can be encapsulated within the component's host element so that they don't affect the rest of the application.

The Component decorator provides the encapsulation option which can be used to control how the encapsulation is applied on a per component basis.

Choose from the following modes:

ViewEncapsulation.ShadowDom: Angular uses the browser's built-in Shadow DOM API to enclose the component's view inside a ShadowRoot, used as the component's host element, and apply the provided styles in an isolated manner.

ViewEncapsulation.ShadowDom only works on browsers that have built-in support for the shadow DOM (see Can I use - Shadow DOM v1). Not all browsers support it, which is why the ViewEncapsulation.Emulated is the recommended and default mode.                             

ViewEncapsulation.Emulated: Angular modifies the component's CSS selectors so that they are only applied to the component's view and do not affect other elements in the application, emulating Shadow DOM behavior. For more details, see Inspecting generated CSS.

ViewEncapsulation.None: Angular does not apply any sort of view encapsulation meaning that any styles specified for the component are actually globally applied and can affect any HTML element present within the application. This mode is essentially the same as including the styles into the HTML itself.

Reference: https://angular.io/

Continue Reading →

Monday, 20 February 2023

Building Microservices with ASP.NET Core

 This tutorials only for beginner level developers. In this I will let you know a simple Asp.net Core WebApi Project interacting with OCELOT opensource API Gateway.

Microservices, also known as Microservices Architecture, is basically an SDLC approach in which large applications are built as a collection of small functional modules. It is one of the most widely adopted architectural concepts within software development. In addition to helping in easy maintenance, this architecture also makes development faster.



See the above picture of a Simple Microservice Architecture.

Now We will learn Microservice By creating a simple application.

 Create a Asp.net core WebApi Project in Visual studio 2019.

Delete pre defined WeatherForecast Controller and model and Create UserController and User Model as per below screenshot.

Code are given below.
namespace UserService.Database.Entities
{
    public class User
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public string Contact { get; set; }
    }
}

We need to install Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.SQLServer, Microsoft.EntityFrameworkCore.Tools. version should be as per DotnetCore version. here I am using 3.1 version.

using Microsoft.EntityFrameworkCore;
using UserService.Database.Entities;

namespace UserService.Database
{
    public class DatabaseContext : DbContext
    {
        public DbSet<User> Users { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"data source=SURAJKUMAR-PC/SKM;
                    initial catalog=EntityFrameworkCoreDB;persist security info=True;
                    user id=sa;password=1234;");
        }
    }
}


using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using UserService.Database;
using UserService.Database.Entities;

namespace UserService.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        DatabaseContext db;
        public UserController()
        {
            db = new DatabaseContext();
        }
        // GET: api/<UserController>
        [HttpGet]
        public IEnumerable<User> Get()
        {
            return db.Users.ToList();
        }

        // GET api/<UserController>/5
        [HttpGet("{id}")]
        public User Get(int id)
        {
            return db.Users.Find(id);
        }

        // POST api/<UserController>
        [HttpPost]
        public IActionResult Post([FromBody] User user)
        {
            try
            {
                db.Users.Add(user);
                db.SaveChanges();
                return StatusCode(StatusCodes.Status201Created);
            }
            catch (Exception)
            {
                return StatusCode(StatusCodes.Status500InternalServerError);
            }
        }
    }
}

Now Save everything and lets create database table. Open Package manager Console in Visual Studio and execute the below highlighted command for migration.

This will genrate migration script and update the things in Sql server. Now lets checkout our SQL server DB.

See, Users table has been created. Now lets add one record in table for API testing.

Id Name Address Contact
1 suraj delhi 987643222

Run the application and execute below API url. You will see the response. 

Our API is ready now.

Creating OCELOT API Gateway.

Now Add one more project (ASP.NET Core WebApp blank project) inside same solution named APIGateway.
- Add Ocelot Package from Nuget pckg manager.
- Add ocelot.json file.


Add Routes data inside ocelot.json file as per below code.

{
    "Routes": [
      {
        "DownstreamPathTemplate": "/api/user",
        "DownstreamScheme": "http",
        "DownstreamHostAndPorts": [
          {
            "Host": "localhost",
            "Port": "30935"
          }
        ],
        "UpstreamHttpMethod": [ "GET" ],
        "UpstreamPathTemplate": "/user"
      },
      {
        "DownstreamPathTemplate": "/api/user/{id}",
        "DownstreamScheme": "http",
        "DownstreamHostAndPorts": [
          {
            "Host": "localhost",
            "Port": "30935"
          }
        ],
        "UpstreamHttpMethod": [ "GET" ],
        "UpstreamPathTemplate": "/user/{id}"
      }
    ]
  }

Add the above json file in Program.cs class as per below screenshot.

Add Ocelot service and middleware in StartUp class as pr below screenshot.



Now Run Both the application and see results.


Use the url as per below screenshot for testing.


From Ocelot API Gateway, we are able to access microservice.

Reference: https://www.youtube.com/

Microservice Interview Questions and Answers : https://www.guru99.com/

Continue Reading →

Sunday, 29 January 2023

Angular authentication

Here I am providing only code snippet, required for angular authentication. If you are angular guy then you will understand the code easily and use in your application.

I have a User Model. Below is the code.

1- Creating user model

export class User {
    isAuth = false;
    userId: string;
    email: string;
    password: string;
    name: string;
    address: string;
    role: string;
    roles = [];
    token: string;
    contact: string;
    createdDate: any;
    updatedDate: any;
    costructor() { }
}


Environment.ts file code snippet.

export const environment = {
  production: false,
  apiAddress: 'http://localhost:1300/api',
}



2- Creating AuthService

First we will create a Auth service in Angular. Below is the code for AuthService.

import { Injectable } from '@angular/core';
import { Http, Headers } from '@angular/http';
import { UserLogin } from '../public/models/userLogin';
import { Observable } from 'rxjs/Rx';

import { User } from '../models/user';
import { environment as env } from '../../environments/environment';

declare const localStorage: any;

@Injectable()
export class AuthService {
    headers: Headers;
    user: User;
    constructor(private http: Http) {
        this.headers = new Headers({ 'content-type': 'application/json' });
        this.loadAuthUser();
    }
    loadAuthUser() {
      if (localStorage['authInfo'] !== undefined && localStorage['authInfo'] !== null) {
            this.user = JSON.parse(localStorage['authInfo']);
      }
    }
    SignOut() {
        localStorage.removeItem('authInfo');
        this.user = undefined;
    }
    setAuthUser(user: User) {
        localStorage['authInfo'] = JSON.stringify(user);
        this.user = user;
    }
    ValidateUser(user: UserLogin): Observable<User> {
        return this.http.post(env.apiAddress + '/auth', JSON.stringify(user),
            { headers: this.headers }).map((res) => {
                return res.json();
            }).catch((err) => Observable.throw(err));
    }
}


3- Creating LoginComponent code

Then We will call Login function for user authentication and token storage. Below is the code for Login Component.

import { Component, OnInit } from '@angular/core';
import { UserLogin } from '../models/userLogin';
import { AuthService } from '../../services/auth.service';
import { User } from '../../models/user';
import { Router, ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styles: []
})
export class LoginComponent implements OnInit {
  user: UserLogin;
  ref = '';
  constructor(private authService: AuthService, private router: Router,
                                                    private route: ActivatedRoute) {
    this.user = new UserLogin();
  }

  ngOnInit() {  
    this.route.queryParams.subscribe((params) => {
      this.ref = params.ref;
    });
  }
  Login() {
    this.authService.ValidateUser(this.user).subscribe((res) => {
      const authObj: User = res;
      if (authObj.email !== '') {
        authObj.isAuth = true;
        this.authService.setAuthUser(authObj);
        if (this.ref !== undefined && this.ref !== '') {
          this.router.navigate([this.ref]);
        }
        else {
          if (authObj.roles.indexOf('Admin') > -1) {
            this.router.navigate(['admin']);
          } else {
            this.router.navigate(['user']);
          }
        }
      }
    });
  }
}


4- Creating AppRouting file 

Below is the Code of app.routing.ts file.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdminAuthGuard, UserAuthGuard } from './services/auth.guard';

const routes: Routes = [
    { path: '', loadChildren: 'app/public/public.module#PublicModule' },
    { path: 'user', loadChildren: 'app/user/user.module#UserModule',
                                                    canActivate:[UserAuthGuard] },
    { path: 'admin', loadChildren: 'app/admin/admin.module#AdminModule',
                                                    canActivate: [AdminAuthGuard] }
];

@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule],
})
export class AppRoutingModule { }


5- Creating Route Guard file 

Below is the code of auth.guard.ts file.

import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AuthService } from './auth.service';

@Injectable()
export class AdminAuthGuard implements CanActivate {
  constructor(private authService: AuthService, private router: Router) { }
  canActivate() {
    if (!(this.authService.user != null && this.authService.user.isAuth)) {
      this.router.navigate(['login']);
      return false;
    } else if (this.authService.user.roles.indexOf('Admin') > -1) {
      return true;
    } else {
      this.router.navigate(['unauthorize']);
      return false;
    }
  }
}

@Injectable()
export class UserAuthGuard implements CanActivate {
  constructor(private authService: AuthService, private router: Router) { }
  canActivate() {
    if (!(this.authService.user != null && this.authService.user.isAuth)) {
      this.router.navigate(['login']);
      return false;
    } else if (this.authService.user.roles.indexOf('User') > -1) {
      return true;
    } else {
      this.router.navigate(['unauthorize']);
      return false;
    }
  }
}

Creating Sign-out feature 

Below is the code snippet from a component.

  ...
    <ul class="nav navbar-nav pull-right" *ngIf="authService.user!=undefined">
      <li style="padding: 15px;">
        Welcome : {{authService.user.name}}
      </li>
      <li>
        <a href="javascript:void(0)" (click)="signout()">SignOut</a>
      </li>
    </ul> ...


  ...       constructor(public authService: AuthService, private router: Router) { }
      signout() {
        this.authService.SignOut();
        this.router.navigate(['/login']);
      }     ...

Sending token value in Request header- 

1- Using Http-Interceptors

2- Using RequestOptions (below is example code snippet)

@Injectable()
export class ProductService {
  private baseUrl = '';
  private headers: any;
  private options;
  constructor(private http: Http, private authService: AuthService) {
    this.options = new RequestOptions({     headers: new Headers({                           'authorization': this.authService.user.token,
                          'Content-Type': 'application/json'
                         })
    });
    this.baseUrl = env.apiAddress;
  }

  getAll(): Observable<Product[]> {
    return this.http.get(`${this.baseUrl}/product`, this.options)
      .map((res: Response) => res.json())
      .catch((error: any) => Observable.throw(error.json().error || 'Server error'));
  }
  add(product: Product): Observable<Response> {
    return this.http
      .post(`${this.baseUrl}/product`, JSON.stringify(product), this.options)
      .catch((error: any) => Observable.throw('Server error'));
  }
    .......         ......


Continue Reading →

Sunday, 22 January 2023

JWT authentication in ASP.NET Core WebAPI

Using JWT (JSON Web Tokens) in a Web API is a common approach for handling authentication and authorization. Here's a concise guide on how to implement JWT in a Web API, typically using a framework like ASP.NET Core, but the principles apply to other frameworks as well.

Step 1: Install Necessary Packages

For ASP.NET Core, you'll need to install the following NuGet packages:

  1. Microsoft.AspNetCore.Authentication.JwtBearer
  2. System.IdentityModel.Tokens.Jwt

Step 2: Configure JWT in Startup

In your Startup.cs file, configure JWT authentication in the ConfigureServices method:

public void ConfigureServices(IServiceCollection services)
{
    // Other service configurations...

    var key = Encoding.ASCII.GetBytes("your_secret_key_here"); // Use a strong secret key
    services.AddAuthentication(x =>
    {
        x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(x =>
    {
        x.RequireHttpsMetadata = false; // Set to true in production
        x.SaveToken = true;
        x.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(key),
            ValidateIssuer = false,
            ValidateAudience = false
        };
    });

    services.AddControllers();
}

Step 3: Create a JWT Token

You'll need a method to generate the JWT. This typically occurs during login:

  public string GenerateJwtToken(string username)
  {
// Define JWT claims
      var claims = new[]
      {
          new Claim(JwtRegisteredClaimNames.Sub, userid), // Registered Claims
new Claim(JwtRegisteredClaimNames.Name, username), // Registered Claims
          new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim("role", "admin"), // Custom Claims
new Claim("email", "johndoe@example.com") // Custom Claims
      };
 
// Define the security key
string secretKey = "your_secret_key_here";
      var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));

// Define the signing credentials (HMACSHA256 algorithm)
      var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
 
      var token = new JwtSecurityToken(
          issuer: "your-issuer", // Can be your app name
          audience: "your-audience", // Can be a target application or service
          claims: claims,
          expires: DateTime.Now.AddMinutes(30),
          signingCredentials: creds);
 
       // Serialize the token to a string
       var tokenHandler = new JwtSecurityTokenHandler();
       string jwtToken = tokenHandler.WriteToken(token);

      return jwtToken ;
  }

Step 4: Secure Your API Endpoints

Use the [Authorize] attribute to protect your API endpoints:

  [Authorize]
  [ApiController]
  [Route("[controller]")]
  public class WeatherForecastController : ControllerBase
  {
      [HttpGet]
      public IActionResult Get()
      {
          return Ok(new { Message = "This is a protected endpoint!" });
      }
  }

Step 5: Handling User Login

Create a login endpoint to authenticate users and return a JWT:

  [HttpPost("login")]
  public IActionResult Login([FromBody] LoginModel login)
  {
      // Validate user credentials (this is just an example)
      if (login.Username == "test" && login.Password == "password") // Replace with actual validation
      {
          var token = GenerateJwtToken(login.Username);
          return Ok(new { Token = token });
      }
 
      return Unauthorized();
  }

Step 6: Testing

Use a tool like Postman to test your endpoints:

  1. Call the login endpoint with valid credentials to receive a JWT.
  2. Use the received token in the Authorization header (Bearer <token>) when accessing protected endpoints.

Where jwt tokens are stored on on server

JWT (JSON Web Tokens) are typically not stored on the server in the same way as session data. Instead, they are often used in a stateless manner, meaning the server does not maintain a session for each user. Here’s how it generally works:

  1. Client-Side Storage: After authentication, the server sends the JWT to the client, which usually stores it in local storage or cookies.

  2. Stateless Authentication: Each time the client makes a request, it sends the JWT along (typically in the Authorization header). The server validates the token without needing to store any session data.

  3. Optional Revocation: If you need to implement token revocation or blacklisting, you might maintain a list of revoked tokens on the server, but this is an additional layer of complexity that somewhat counters the stateless principle.

  4. Expiry: JWTs usually have an expiration time, after which they are considered invalid. This reduces the need for server-side storage since expired tokens can be discarded.

In summary, JWTs are mainly stored client-side, while the server verifies them as needed.

How server verifies jwt token on server

To verify a JWT (JSON Web Token) on the server, the following steps are typically followed:

  1. Extract the Token: The server retrieves the JWT from the request, usually from the Authorization header as a Bearer token.

  2. Decode the Token: The server decodes the JWT to access its header and payload. This step does not require validation and can be done using a base64 decoding method.

  3. Verify the Signature: The most critical part of the verification process is to check the signature of the token:

    • The server uses the algorithm specified in the JWT header (e.g., HS256, RS256) and the secret key (for symmetric algorithms) or the public key (for asymmetric algorithms) that was used to sign the token.
    • It re-generates the signature using the header and payload and compares it with the signature part of the received token.
  4. Check Claims: The server validates the claims in the payload:

    • Expiration: Check the exp claim to see if the token is still valid.
    • Audience: Verify the aud claim to ensure the token was intended for your server.
    • Issuer: Check the iss claim to confirm it was issued by a trusted source.
    • Not Before: Optionally, check the nbf claim to see if the token is being used before its valid time.
  5. Process the Request: If the token is valid and all claims check out, the server processes the request. If not, it responds with an appropriate error (e.g., 401 Unauthorized).

Access token vs Refresh Token:

  1. Access Token (short-lived): This token is used for authenticating requests and is typically valid for a short duration (e.g., 15 minutes).
  2. Refresh Token (long-lived): This token is used to get a new access token when the old one expires. It typically has a longer expiry time (e.g., 7 days or more). 
What information JWT token contains

JWT Token Generation Code in C#
Click here

Claim in jwt authentication token
Click here

By following these steps, the server ensures that the JWT is valid, has not been tampered with, and is still active.


Reference: https://medium.com/https://www.c-sharpcorner.com/https://javascript.plainenglish.io/

Continue Reading →

Topics

ADFS (1) ADO .Net (1) Ajax (1) Angular (47) Angular Js (15) ASP .Net (14) Authentication (4) Azure (3) Breeze.js (1) C# (55) CD (1) CI (2) CloudComputing (2) Coding (10) CQRS (1) CSS (2) Design_Pattern (7) DevOps (4) DI (3) Dotnet (10) DotnetCore (20) Entity Framework (5) ExpressJS (4) Html (4) IIS (1) Javascript (17) Jquery (8) jwtToken (4) Lamda (3) Linq (10) microservice (4) Mongodb (1) MVC (46) NodeJS (8) React (10) SDLC (1) Sql Server (32) SSIS (3) SSO (1) TypeScript (3) UI (1) UnitTest (2) WCF (14) Web Api (16) Web Service (1) XMl (1)

Dotnet Guru Archives