Tuesday, January 28, 2025

Built-in token authentication with ASP.NET Core 9.0 Minimal WebAPI

In this tutorial I will showcase the built-in WebApi token authentication. To keep it simple, we shall persist our data in the lightweight SQLite database.

Prerequisites

It is assumed that you have installed the following on your computer:
  • .NET 9.0
  • Visual Studio Code editor

Getting Started

In a suitable working directory, create a new WebApi application using the following terminal window command:

dotnet new webapi --name WebApiTokenAuth

Change directory with:

cd WebApiTokenAuth

We will need to add some packages. Also in the same terminal window, run the following commands:

dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore

dotnet add package Microsoft.EntityFrameworkCore.Sqlite

dotnet add package Microsoft.EntityFrameworkCore.Tools

dotnet add package Microsoft.EntityFrameworkCore.Design

dotnet add package Swashbuckle.AspNetCore

The above packages allow us to use SQLite and Entity Framework. The last package (Swashbuckle.AspNetCore) will be used to provide a default Swagger UI.

Make sure you have the dotnet-ef tool. If you do not, you can globally install it with:

dotnet tool install --global dotnet-ef

If you already have the dotnet-ef, update your version to the latest with:

dotnet tool update --global dotnet-ef

Let us first add Swagger UI to our WebAPI application so that we can easily test our API endpoints. Open your source code with Visual Studio Code by executing the following statement from a terminal window inside the root folder of the application:

code .

You can now add the following statement right under app.MapOpenApi():

app.UseSwaggerUI(options =>  {
    options.SwaggerEndpoint("/openapi/v1.json", "My WebAPI");
});

Edit file Properties/launchSettings.json. In both http and https blocks, change the value of launchBrowser to true.

Also, in both http & https blocks, add the following setting:

"launchUrl": "swagger"

Let us run our web app and see what it does. Run the web app with:

dotnet watch

This gets loaded into your default browser:



Click on GET >> Try it out >> Execute. This will produce the following output:


Database context class

Since we will be using Entity Framework to talk to the SQLite database, we will need a database context class. Add a folder named Data, then add to it a class named ApplicationDbContext that derives from IdentityDbContext<IdentityUser> with the following code:

public class ApplicationDbContext: IdentityDbContext<IdentityUser> {
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
    {}
}

Add the following connection string to appsettings.json:

"ConnectionStrings": {
  "DefaultConnection": "Data Source=webapi-auth.db;"
}

Next, we must register ApplicationDbContext with our app by adding the following code into Program.cs right before 'var app = builder.Build();':

// Configure identity database access via EF Core
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(connectionString));

Other required services

Add the following code right after the above code:

// Authorization
builder.Services.AddAuthorization();

// Activate identity APIs. By default, both cookies and proprietary tokens
// are activated. Cookies will be issued based on the 'useCookies' querystring
// parameter in the login endpoint
builder.Services.AddIdentityApiEndpoints<IdentityUser>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

We need to add authorization and authentication middleware with the following code right after 'app.UseHttpsRedirection();':

app.UseAuthentication(); 
app.UseAuthorization(); 

Let us secure the /weatherforecast endpoint by forcing authentication. Chain the following to the endpoint by adding this code right under '.WithOpenApi()':

.RequireAuthorization();

The full app.MapGet() code will look like this:

app.MapGet("/weatherforecast", () =>
{
    var forecast =  Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi()
.RequireAuthorization();

Adding Identity API endpoints

Add the identity endpoints to your app by calling MapIdentityApi<IdentityUser>(). Add the following code to Program.cs right before 'app.Run();':

app.MapIdentityApi<IdentityUser>();

Migrations

Since our app uses EF Core, we will create a migration in the Data folder and update the database. Run the following terminal commands:

dotnet ef migrations add M1 -o Data/Migrations

dotnet ef database update

You will notice that a SQLite database file is created named webapi-auth.db.

Try it out

Let us test our application to see whether or not we have indeed succeeded in securing our API endpoint. Start your app with:

dotnet watch

You will see a variety of identity related endpoints when the following page gets loaded into your default browser:


Try to hit the /weatherforecast endpoint and see the data. You will encounter a 401 (unauthorized) error:

Let us register a user. Click on the /register endpoint then click on the "Try it out" button. Update the JSON object so it looks like this:

{
  "email": "a@a.a",
  "password": "P@$$w0rd"
}

Click on the Execute button. You will get a Code 200 response representing success:


Next, let us login with the credentials we created. Click on the /login endpoint, then click on the "Try it out" button.


Choose true for useCookies and update the JSON object so it only has the credentials we had previously created. Thereafter, click on the Execute button. You should get a code 200 response:

Now let's try getting the data using the GET /weatherforecast endpoint. It should be a relief that we can now see the weather forecast information.

Conclusion

With ASP.NET Core 9.0 we need to follow these steps:
  • restore Swagger UI
  • configure our WebAPI application with the built in ,NET token authentication capability

Monday, January 20, 2025

Phi-3 Small Language Model (SLM) in a PHP app with Ollama and LLPhant framework

Overview

In this tutorial, we will see how easy it is to use the Phi-3 small language model in a PHP application. The best part is that it is free and runs entirely on your local device. Ollama is used to serve the Phi-3 small language model and LLPhant is the PHP framework for communicating with the AI model. 

Prerequisites

To proceed, you will need the following:

What is small language model (SLM)?

A small language model (SLM) is a machine learning model typically based on a large language model (LLM) but of greatly reduced size. An SLM retains much of the functionality of the LLM from which it is built but with far less complexity and computing resource demand.

What is Ollama?

Ollama is an application you can download onto your computer or server to run open-source generative AI small-language-models (SLMs) such as Meta's Llama 3 and Microsoft's Phi-3. You can see the many models available at https://www.ollama.com/library.

What is LLPhant

LLPhant is an open-source PHP Generative AI Framework at https://github.com/LLPhant/LLPhant

Getting Started

Download the Ollama installer from https://www.ollama.com/download.

Once you have installed Ollama, run these commands from a terminal window:

ollama pull phi3:latest
ollama list
ollama show phi3:latest

In a suitable working directory, create a folder named PhpAI with the following terminal window command:

mkdir PhpAI

Change into the newly created folder with:

cd PhpAI

Using Composer, install the theodo-group/llphant package by running this command:

composer require theodo-group/llphant

Let's get coding

Create a file named index.php with the following content:

<?php

require_once 'vendor/autoload.php';

use LLPhant\OllamaConfig;
use LLPhant\Chat\OllamaChat;  
 
$config = new OllamaConfig();
$config->model = 'phi3'; 
 
$chat = new OllamaChat($config); 
 
$chat->setSystemMessage('You are a helpful assistant who knows about world geography.'); 
 
$response = $chat->generateText('what is the capital of france?');  
 
echo $response;
?>

Running the app

To run the app, start the PHP web server to listen on port number 8888 with the following command in the PhpAI folder.

php -S localhost:8888

You can view the output by pointing your browser to the following URL:

http://localhost:8888/

This is what I experienced:

Conclusion

We can package our applications with a local SLM. This makes our applications cheaper, faster, connection-free, and self-contained.

Monday, January 13, 2025

Adding a UI to your WebAPI in ASP.NET 9.0

You may have noticed that when you create a WebAPI project in .NET 9.0, the default swagger UI is not there anymore by default. In this article, I will show you how to restore it back as the default UI. In addition, we will install an alternative UI to swagger named Scalar. The approach used applies to both minimal and controller-based WebAPI.

Companion Video: https://youtu.be/vsy-pIxKpYU
Source Code: https://github.com/medhatelmasry/WebApiDemo

Getting Started

Let us first create a minimal WebAPI project with the following terminal command:

dotnet new webapi -o WebApiDemo
cd WebApiDemo

Open the project in VS Code and note the following statements in Program.cs:

  • Around line 5 is this statement, which adds the OpenApi service:

builder.Services.AddOpenApi();

  • Also, around line 12 is this statement:

app.MapOpenApi();

The above statements produce the following JSON endpoint file describing your API when you run your app:

/openapi/v1.json

This displays a page like the following in your browser:

Restoring Swagger UI

Note that swagger UI is nowhere to be found. It is quite straight forward to add a Swagger UI to your .NET 9.0 WebAPI project. Start by adding the following package to your project:

dotnet add package Swashbuckle.AspNetCore

You can now add the following statement right under app.MapOpenApi():

app.UseSwaggerUI(options =>  {
    options.SwaggerEndpoint("/openapi/v1.json", "My WebAPI");
});

Now, run the project and go to endpoint /swagger in your browser. You should see this UI:

NOTE: If you want the Swagger UI to be accessed at the / (root) endpoint, then you can add this option:

options.RoutePrefix = "";

Scalar: alternative to Swagger

There is a much better alternative to swagger named Scalar. It offers you an enhanced UI and some additional features. Let us explore Scalar

To use Scalar in an ASP.NET 9.0 WebAPI application, you must add the following package:

dotnet add package Scalar.AspNetCore

Comment out the following code in Program.cs:

// app.UseSwaggerUI(options => 
// {
//     options.SwaggerEndpoint("/openapi/v1.json", "My WebAPI");
// });

Replace the above commented-out code with this:

app.MapScalarApiReference();

That's all you need to do. Let’s see how the Scalar UI looks like. Run the project and point your browser to this endpoint:

/scalar/v1

Explore this UI. One interesting feature is that you can view client code in a variety of languages. Here is what it looks like if you choose C#:


You can further customize the UI by enabling and disabling various options. For example, replace the statement app.MapScalarApiReference() with:

app.MapScalarApiReference(options => {
    options
        .WithTitle("My WebAPI")
        .WithTheme(ScalarTheme.Moon)
        .WithDefaultHttpClient(ScalarTarget.CSharp, ScalarClient.HttpClient);
});

This results in a less dark theme and a default client code of C#.

Making Scalar UI the default page

To make the Scalar UI the default page when launching your WebAPI page with “dotnet watch”, edit the /Properties/launchSettings.json file and make the following changes:

1. In both http and https blocks, add this item:

"launchUrl": "scalar/v1"

2. Also, in both http and https blocks, change the value of launchBrowser to true.

Now when you restart your webAPI web app with “dotnet watch”, the Scalar UI is automatically loaded in your default browser.

Happy Coding!