Showing posts with label Web API. Show all posts
Showing posts with label Web API. Show all posts

Web API - Basic Authentication

Basic Authentication

As per RFC 2617, HTTP Authentication: Basic and Digest Access Authentication, Basic Authentication is defined as client must authenticate itself with a user-ID and a password for each realm. Basic authentication is performed within the context of a "realm." The server includes the name of the realm in the WWW-Authenticate header. The user's credentials are valid within that realm. Simply to authenticate using Basic Authentication, client shoud pass credentials for each request in "Authentication" header as "Basic BASE64(ASCIIEncoding/ISO-8859-1 encoding of 'USERNAME:PASSWORD')".

Pros

  • Internet standard.
  • Supported by all major browsers.
  • Relatively simple protocol.

Cons

  • User credentials are sent in the request.
  • Credentials are sent as plaintext.
  • Credentials are sent with every request.
  • No way to log out, except by ending the browser session.
  • Vulnerable to cross-site request forgery (CSRF); requires anti-CSRF measures.


Adding Basic Authentication to Web API

To add the Basic authentication to our API, we need to override the OnAuthorization() method,which performs all the validations, in AuthorizeAttribute class. In that we need to check whether the header is present or not and if present, we need to extract the username and password and need to verify those details.

public class BasicAuthenticationAttribute : AuthorizeAttribute
{
 public override void OnAuthorization(HttpActionContext actionContext)
 {
  if (actionContext.Request.Headers.Authorization == null)
  {
   actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
  }
  else
  {
   // Gets header parameters  
   string authenticationString = actionContext.Request.Headers.Authorization.Parameter;
   string decoded = ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(authenticationString));
   var credentials = decoded.Split(':');
   
   // encoded string is invalid
   if(credentials.Length<=2)
    actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);

   // Validate username and password  
   if (!Validator.ValidateUser(credentials[0], credentials[1]))
   {
    // returns unauthorized error  
    actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
   }
  }
 }
}
Here, Validator.ValidateUser is user function to validate the user details.

Passing Basic Authentication while calling Web API

In order to add Basic authentication header to a web api request we need to encode our credentials as below

string username = "Your username";
string password = "Your password";
string credentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes($"{username}:{password}));
request.Headers.Add("Authorization", "Basic " + credentials);

Keep Web API JSON Object names same as Class property - ASP.NET Core

.NET Core by default, converts the class property names to Camel case when we serialize the JSON object.
e.g. I have defined my class as below









when we serialize this class, the web API will return as following

So in order to make it as the property names as same as the class property name like below







we need to override the ContractResolver in JSON serialization settings.
services
    .AddMvc()
    .AddJsonOptions(options =>
    {
        options.SerializerSettings.ContractResolver
            = new Newtonsoft.Json.Serialization.DefaultContractResolver();
    });
Note: AddJsonOptions method will be available in Microsoft.Extensions.DependencyInjection.MvcJsonMvcBuilderExtensions class

Swagger Integration - Including the XML documentation from Sub Projects to ASP.NET Core Web API

While integrating Swagger in ASP.NET core Web API, if you enable the XML documentation for Web API and if you are using Sub projects(Ex: Model Project), then Swagger UI recognizes only the Web API documentation. It will not fetch the XML comments from the Sub Project. Using the following steps we can include the Sub Projects documentation also in the Swagger.

Using Visual Studio for Windows

  1. Enable XML documentation for the Sub project.
    • In Visual Studio, Right-click the project in Solution Explorer and select Properties
    • Check the XML documentation file box under the Output section of the Build tab
    • Remove the "bin\Debug" from the path, to get the xml file directly in the Solution folder
  2. Add the Generated XML file in the Web API as Link
    • Right-click on Project -> ADD -> Existing Item 
    • Browse and Select the file -> Click on dropdown arrow next to ADD button -> Select "Add as Link" (Adding the file as Link, will not copy the file to the project. Instead it will create a link to the Original file and you can see the changes immediately if you modify the original file)
  3. Open the file properties and Set Copy To Output Directory as "Copy Always"
  4. Add the following to the services.AddSwaggerGen method under ConfigService method in Startup.cs file
    var dir = new DirectoryInfo(AppContext.BaseDirectory);
    foreach (var fi in dir.EnumerateFiles("*.xml"))
    {
        c.IncludeXmlComments(fi.FullName);
    }
    
    Or you can specify all the files manually as
        // Adding the xml documentation of the Main project
        var xmlFile = $"{Assembly.GetEntryAssembly().GetName().Name}.xml";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
        c.IncludeXmlComments(xmlPath);
    
        // Adding the xml documentation of the Sub project
        xmlPath = Path.Combine(AppContext.BaseDirectory, "Scheduling.Model.xml");
        c.IncludeXmlComments(xmlPath);
    

Using Visual Studio Code

  1. Enable XML documentation for the Subproject by adding the following to .csproj file
    
      $(TargetFramework)\$(MSBuildProjectName).xml
    
  2. Add the Generated XML file in the Web API as Link and change it's property to Copy Always by adding the following to the Main project .csproj file
    
      
        Always
      
     
    
  3. Add the following to the services.AddSwaggerGen method under ConfigService method in Startup.cs file
    var dir = new DirectoryInfo(AppContext.BaseDirectory);
    foreach (var fi in dir.EnumerateFiles("*.xml"))
    {
        c.IncludeXmlComments(fi.FullName);
    }
    
    Or you can specify all the files manually as
        // Adding the xml documentation of the Main project
        var xmlFile = $"{Assembly.GetEntryAssembly().GetName().Name}.xml";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
        c.IncludeXmlComments(xmlPath);
    
        // Adding the xml documentation of the Sub project
        xmlPath = Path.Combine(AppContext.BaseDirectory, "Scheduling.Model.xml");
        c.IncludeXmlComments(xmlPath);
    
Happy Coding 😊

Integrating Swagger in ASP.NET Core Web API using Swashbuckle

When consuming a Web API, understanding its various methods can be challenging for a developer. Swagger, also known as Open API, solves the problem of generating useful documentation and help pages for Web APIs. It provides benefits such as interactive documentation, client SDK generation, and API discoverability.

Swagger

Swagger is a language-agnostic specification for describing REST APIs. The Swagger project was donated to the OpenAPI Initiative, where it's now referred to as Open API. Swagger is useful
  1.  To minimize the amount of work needed to connect disassociated services. 
  2.  To reduce the amount of time needed to accurately document a service.

Swagger specification (swagger.json)

The core to the Swagger flow is the Swagger specification—by default, a document named swagger.json. It's generated by the Swagger tool chain (or third-party implementations of it) based on your service. It describes the capabilities of your API and how to access it with HTTP. It drives the Swagger UI and is used by the tool chain to enable discovery and client code generation

Example

{
   "swagger": "2.0",
   "info": {
       "version": "v1",
       "title": "API V1"
   },
   "basePath": "/",
   "paths": {
       "/api/Todo": {
           "get": {
               "tags": [
                   "Todo"
               ],
               "operationId": "ApiTodoGet",
               "consumes": [],
               "produces": [
                   "text/plain",
                   "application/json",
                   "text/json"
               ],
               "responses": {
                   "200": {
                       "description": "Success",
                       "schema": {
                           "type": "array",
                           "items": {
                               "$ref": "#/definitions/TodoItem"
                           }
                       }
                   }
                }
           },
           "post": {
               ...
           }
       },
       "/api/Todo/{id}": {
           "get": {
               ...
           },
           "put": {
               ...
           },
           "delete": {
               ...
   },
   "definitions": {
       "TodoItem": {
           "type": "object",
            "properties": {
                "id": {
                    "format": "int64",
                    "type": "integer"
                },
                "name": {
                    "type": "string"
                },
                "isComplete": {
                    "default": false,
                    "type": "boolean"
                }
            }
       }
   },
   "securityDefinitions": {}
}

Swagger UI

Swagger UI offers a web-based UI that provides information about the service, using the generated Swagger specification.Swashbuckle include an embedded version of Swagger UI, so that it can be hosted in your ASP.NET Core app using a middleware registration call

Integrating Swagger using Swashbuckle

We can integrate the Swagger in our application using Swashbuckle with the following steps
  • Add package Swashbuckle.AspNetCore to the application
  • Add the Swagger generator to the services collection in the Startup.ConfigureServices method
using Swashbuckle.AspNetCore.Swagger;
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList"));
    services.AddMvc();

    // Register the Swagger generator, defining one or more Swagger documents
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
    });
}
  • In the Startup.Configure method, enable the middleware for serving the generated JSON document and the Swagger UI
// Enable middleware to serve generated Swagger as a JSON endpoint. 
    app.UseSwagger();

    // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), specifying the Swagger JSON endpoint.
    app.UseSwaggerUI(c =>
    {
        c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
    });
  • This will enable the basic integration of the swagger. You can check the generated swagger docuement describing the endpoints in [BASE-URL]/swagger/v1/swagger.json and Swagger UI can be found in [BASE-URL]/swagger

Customization:

  • To get the Swagger at APP root directly, set the RoutePrefix property to an empty string
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
    c.RoutePrefix = string.Empty;
});
  • The configuration action passed to the AddSwaggerGen method adds information such as the author, license, and description
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new Info
    {
        Version = "v1",
        Title = "ToDo API",
        Description = "A simple example ASP.NET Core Web API",
        TermsOfService = "None",
        Contact = new Contact
        {
            Name = "Contact name",
            Email = "Test@test.com",
            Url = "Web site URL"
        },
        License = new License
        {
            Name = "Use under LICX",
            Url = "Licence terms page url"
        }
    });
});
  • We can show the xml comments added to the methods and properties in the Swagger UI. For that we need to enable the XML documentation File for the project.
    • Enable XML documentation for the project
      • In Visual Studio, Right-click the project in Solution Explorer and select Properties
      • Check the XML documentation file box under the Output section of the Build tab
                     Note: If you are using Visual Studio Code, add the following in .csproj file

  bin\Debug\$(TargetFramework)\$(MSBuildProjectName).xml
 
    • Configure in ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext(opt => opt.UseInMemoryDatabase("TodoList"));
    services.AddMvc();

    // Register the Swagger generator, defining one or more Swagger documents
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
  
  // Set the comments path for the Swagger JSON and UI.
        var xmlFile = $"{Assembly.GetEntryAssembly().GetName().Name}.xml";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
        c.IncludeXmlComments(xmlPath);
    });
}

Happy Coding 😊
You can find more from here and here