Publishing .NET Core Web API (FIDO2 WebAuthn Passwordless) to Azure

In the previous post, we created a FIDO2 and WebAuthn .NET Core WebApi as a separate project (back end) and a separate NextJs project as a front end app in order to log in with no password. The previous two projects ran on localhost. They can be found in this blog post:

In this blog post, we will prepare, and publish the .NET Core part project to Azure.

First of all, we have to store our MongoDb connection string in Azure Vault. We will need to create the following resources in Azure first, and in the following sequence as well. KeyVault will store the secret and the rest is also needed to publish the API and host it in Azure:

  • Resource Group
  • AppService Plan
  • Web App
  • KeyVault

Create Resource Group:

az group create --name yourchosennamerg --location "EastUs

Create an App Service plan

az appservice plan create --name yourchosenserviceplanname --resource-group yourchosennamerg  --sku FREE

Create a Web App

az webapp create --resource-group yourchosennamerg --plan yourchosenserviceplanname --name webappname

Create AzureKeyVault

az keyvault create --name "yourchosenkeyvaultname" --resource-group "yourchosennamerg " --location "EastUs"

Create managed identity

az webapp identity assign --name "yourwebappname" --resource-group "yourchosennamerg "

From the above commands, you will see the following returned:

{
 "principalId": "990e548b-a928-4f51-8c7e-9k75648h",
  "tenantId": "3a91548b-8c7e-a928-9ca5-3a91548b",
  "type": "SystemAssigned",
  "userAssignedIdentities": null
}

Grab the principalId and use it to assign the managed identity in order to give your web app permission to do get and list operations on your key vault, pass the principalId to the az keyvault set-policy command:

Assign Managed Identity

az keyvault set-policy --name "yourkeyvaultname" --object-id "990e548b-a928-4f51-8c7e-9k75648h" --secret-permissions get list

Now either from the code or inside Azure Portal, navigate to newly created KeyVault and add the MongoDb connection string as key value pair:

Alternatively, we can use PowerShell to create all the needed resources above right from command line. Copy the code below all of it into powershell and all the needed resources will be created:

#Connect to your Azure subscription if you are not already connected
Connect-AzAccount

# Create a resource group
New-AzResourceGroup -Name "rgpasswordless" -Location "EastUs"

# Create an App Service plan
New-AzAppServicePlan -Name "passwordlessserviceplan" -ResourceGroupName "rgpasswordless" -Location "EastUs" -Tier Free

# Create a web app
New-AzWebApp -ResourceGroupName "rgpasswordless" -AppServicePlan "passwordlessserviceplan" -Name "passwordlessapicorenext"

# Create a key vault
New-AzKeyVault -Name "PasswordlessKeyVault" -ResourceGroupName "rgpasswordless" -Location "EastUs"

# Assign a managed identity to the web app
Set-AzWebApp -AssignIdentity $true -Name "passwordlessapicorenext" -ResourceGroupName "rgpasswordless"

#Get PrincipalID
$principalId = (az webapp identity show --name "passwordlessapicorenext" --resource-group "rgpasswordless" | ConvertFrom-Json).principalId

#Set keyvaule access policy
Set-AzKeyVaultAccessPolicy -VaultName "PasswordlessKeyVault" -ObjectId $principalId -PermissionsToSecrets get,list

#Set the required secret in keyvault
$secretValue = ConvertTo-SecureString -String "YOURMONGODBCONNECTIONSTRING" -AsPlainText -Force
Set-AzKeyVaultSecret -VaultName "PasswordlessKeyVault" -Name "MongoDbConnString2" -SecretValue $secretValue

In the solution itself, and in terminal, bash or powershell, run the following commands to add the references to the API project in order to use KeyVault itself:

dotnet add package Azure.Identity
dotnet add package Azure.Security.KeyVault.Secrets

Then at the top of RegisterController, add using statements

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Azure.Core;

After this we can use the following code block to replace the MongoDb connection string with Azure Key Vault secret, which is considered as a global variable in Azure. We can also write a helper method or database access layer in our API and add this code once. For the purpose of this demo, I put all the code in a single file.

SecretClientOptions options = new SecretClientOptions()
    {
        Retry =
        {
            Delay= TimeSpan.FromSeconds(2),
            MaxDelay = TimeSpan.FromSeconds(16),
            MaxRetries = 5,
            Mode = RetryMode.Exponential
         }
    };
var client = new SecretClient(new Uri("https://PasswordlessKeyVault.vault.azure.net/"), new DefaultAzureCredential(),options);

KeyVaultSecret secret = client.GetSecret("MongoDbConnString2");

string secretValue = secret.Value;

The next step is to switch to our terminal inside VSCode and publish our API locally:

dotnet publish -c Release -o ./publish

This will create a publish directory inside our API. Then, right click on the publish folder and navigate to Deploy To Web App

In the output tab of bottm panel in VSCode you will see these lines at the end of deployment:

9:44:08 PM passwordlessapicorenext: Copying file: 'publish\publish\web.config'
9:44:08 PM passwordlessapicorenext: Deleting app_offline.htm
9:44:08 PM passwordlessapicorenext: Finished successfully.
9:44:08 PM passwordlessapicorenext: Running post deployment command(s)...
9:44:08 PM passwordlessapicorenext: Triggering recycle (preview mode disabled).
9:44:09 PM passwordlessapicorenext: Deployment successful.
9:44:17 PM: Deployment to "passwordlessapicorenext" completed.

Then, navigate to your Azure Portal, and to your subscription ofcourse, then click on your WebApp and copy the Default Domain value. In my case it is: passwordlessapicorenext.azurewebsites.net

Add https://, and add swagger at the end of URL, so it becomes like this: https://passwordlessapicorenext.azurewebsites.net/swagger

Click enter and you should be able to see the swagger page with available API endpoints:

If you get 500.30 In-Process Startup Failure error open console inside your WebApp as below:

When the console opens, type:

dotnet dotnetcore-passwordless.dll

The name of the dll you can find it in publish directory locally when we published the API locally:

If everything is ok, you should see turning circle that never stops. Most of the startup errors should appear here in console, very detailed:

Another way to deploy this API would be by packaging everything to Acure Container Registry and adding our image to Azure Container Instance with the help of Docker.

Thank you.

Build a passwordless app with FIDO2, WebAuthn, .NET Core API, NextJs, and MongoDB

In this blog post, we will discuss how to add passwordless functionality to your web app, existing or new. We will use FIDO2 protocol and standard, including WebAuthn protocol – specification, which, due to its adoption by all modern browsers, allows the app, and the app developers to get the public key credentials from an Authenticator, be it a usb fido2 hardware key, your phone face or biometric authentication, or , for example windows hello feature.

Once we are done adding FIDO2 , including it’s WebAuthn protocols and authentication functionality to our app, we will firstly and mostly create a more secure and more adoptable sign in and authentication mechanism for our users to be able to sign in with no passwords at all.

By doing so, we will improve our security for our app because FIDO2 and WebAuthn use public/private keys technology, where private key is only stored in hardware Authenticator of a user that he or she takes with him while sharing public key with FIDO2 enabled app .

I will use asp.net core WebApi for the back end, and NextJs for the front end.

Notes on Passwordless:

  • Passwordless is a way to sign in and authenticate without a password.
  • The user credential (secret) is not shared with the website or app
  • With passwordless, an authenticator is required. It can be USB Security key, iPhone, Android Phone, WIndows Hello Feature etc …
  • FIDO2 is a protocol and standard developed by Fido Alliance https://fidoalliance.org/
  • Passkeys, also, is simply a new implementation of WebAuthn https://www.w3.org/TR/webauthn-2/
  • Some big companies already added Passkeys to serve their clients. The following website lists all who did https://passkeys.directory/
  • Passwordless authentication helps secure one’s identity online.

For coding part, I will be using the following stack:

For passwordless with FIDO2 and WebAuthn project I purchased a USB Security key. Here is how it looks:

I did not need to configure it. I started using it to log in to our localhost passwordless small app. Just unpack it and plug it in into your PC or whatever machine you are using to browse the web. This one needs USB-C port.

The area in the middle with three umbrella like arcs lights up when it want you to touch it to authenticate. That is all to it.

Here is the security key in action:

This is the part where you touch it, and the website or app authenticates you. This key, stores its private key and never shares it with the world. What is shares is public key. It shares it with WebAuthn protocol, and FIDO2 protocol. Ofcourse this functionality has to be set up by developer of an app that will support passwordless authentication using FIDO2 and WebAuthn.

On the software part, I have created a UML sequence diagram that our small passwordless app uses. Here is the image:

There are two parts to this app: Register, and SignIn.

For registration, please look at the first part of the above UML diagram. The steps to commnunicate with FIDO2 protocol are sequential. First we call fetchMakeCredentialOptions on front end, it sends a request to our API to generate Fido2.CredentialCreateOptions. Here is how credentialoptions generated by FIDO2 look like:

Once the client gets back those options, we assemble , so to speak, a public key, which is found here https://www.w3.org/TR/webauthn-2/#sctn-sample-registration and call navigator.credentials.create to trigger our USB Security key (our chosen authenticator for this example) shown above, with the help of browser and WebAutn.

We press OK, and we get second image from our key now:

The above image asks for our USB security key pin, which you configured while setting up your key after buying it. With biometric authenticators, and face recognition on iphones, this process is different.

We enter the PIN and press OK. We see this:

The key asks us to touch it. We touch that three umbrella area which lights up. Just touch it, no fingerprints are collected. This is not a fingerprint scanner.

After we touch it, the front end calls registerNewCredential, then it also calls registerCredentialWithServer (front end) and then we call our dotnetcore API SaveCredential method. This method calls fido2.MakeNewCredentialAsync which generates PublicKey, which we can store in our MongoDb. After we store this public key, in addition to First Name, Last Name and an email (username) in our database, we can log in then only with email, and no password required.

For this example, I store this info in database:

Upon successful registration, we are redirected automatically to SignIn NextJs page:

The sign in process, from above UML Sequence diagram is almost the same. We only use the email address, no password. In the Login method in our API, we ask FIDO2 for assertion options, in order to present them to our authenticator, located right where we are: fido2.GetAssertionOptions.

After we get the assertion options from fido, we call await navigator.credentials.get to trigger our authenticator.

The first window we get is this:

We enter our pin for USB Security key, then it asks us to touch it:

We touch it, and the request goes to MakeAssertion method in our API, but, this time also with our authenticator’s public key. FIDO2 makes its verification, with its internal algorythms ( var result1 = await fido2.MakeAssertionAsync()) and we get a response from the server. This is how response looks like:

We check the status, it should have the value “ok”. This is from FIDO. If “ok”, we put our user in the NextJs state using useState() hook, and show him or her accordingly the info that they are authorized to see.

The source code is on GitHub: https://github.com/jinan-kordab/passwordless-dotnetcoreapi-nextjs

A video showing FIDO2 and WebAuthn passwordless registration and sign in. Back End: .NET Core Web API, Front End: NextJs.

Thank you.