Login Without a Password
There are tons of new apps launching every day, so you’ll want to make yours stand out. It should have unique features, and it should be easy and convenient to use.
One of the major pain points for many apps is that they require a username and a password to login. I personally have to remember 10–15 passwords for apps like Gmail, Facebook, Instagram, and more. You get the idea.
In this article we are going to create a solution for your APIs that will allow your users to login without a password.
How to go password-less
In order to omit the need for a password, your app should generate some type of token for the user.
This token then gets sent to the user where only they can access it — for example in their email or via their phone. Here is an overview of the flow.
.NET Identity is a package which provides ways to manage users, passwords, profile data, roles, claims, tokens, and more.
In addition, Identity provides ways to generate tokens for email confirmation or for changing the user’s email or phone. We will be using the tokens generated by Identity to verify our users.
There are two main token providers available:
TotpSecurityStampBasedTokenProvider(Time-based One Time Password).
This token provider generates time-based tokens which are valid for around 3 minutes (you can reference the source code here). Based on the token provider, the tokens are generated from the email, phone number, or user id as well as the user’s security stamp.
Dotnet Identity provides the utility classes
PhoneNumberTokenProvider that are subclasses of
If you want to generate a token that doesn’t expire for a long time,
DataProtectorTokenProvider is the way to go.
DataProtectorTokenProvider generates tokens using a
DataProtector and cryptographic algorithms. You can check out the implementation for more details here.
In this article we are going to subclass
DataProtectorTokenProvider so that our token is valid for 10 minutes.
How to Set Up Identity
Let’s start with a new project. Create a project by executing the command
dotnet new webapi –-name NoPasswordProject.
dotnet add package Microsoft.EntityFrameworkCore.InMemory --version 5.0.4dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore --version 5.0.4
We are going to create an in-memory database for this tutorial. But you can use a database of your choice and accordingly change the package above.
Note: The in memory database will clear the users every time the server restarts.
Custom Token Provider
Let’s create a custom token provider that generates token that are valid for 10 minutes.
Create a new file called NPTokenProvider.cs. NP prefix stands for No Password.
using Microsoft.Extensions.Options;public class NPTokenProvider<TUser> : DataProtectorTokenProvider<TUser>
where TUser : IdentityUser
IOptions<NPTokenProviderOptions> options, ILogger<NPTokenProvider<TUser>> logger)
: base(dataProtectionProvider, options, logger)
Here we’re subclassing the
DataProtectorTokenProvider. Nothing out of the ordinary, except in the constructor we are passing
NPTokenProviderOptions. The options need to be subclass of
Create a new file NPTokenProviderOptions.cs and paste in the below code.
using Microsoft.AspNetCore.Identity;public class NPTokenProviderOptions : DataProtectionTokenProviderOptions
Name = "NPTokenProvider";
TokenLifespan = TimeSpan.FromMinutes(10);
We are setting options for the tokens to be created. You can change the
TokenLifeSpan to your liking.
Almost every project needs a database to store its users and other data related to the project. The Dotnet EF Framework provides a nice helper
DbContext to handle sessions with the database and query and save entities.
So create a subclass of
IdentityDbContext which is in turn a subclass of
DbContext. Name the file
using Microsoft.EntityFrameworkCore;public class NPDataContext : IdentityDbContext
public NPDataContext(DbContextOptions<NPDataContext> options)
We have created the classes. Now it’s time to configure them in our
Startup.cs files. In
ConfigureServices add the below code at the start.
var builder = services
.AddEntityFrameworkStores<NPDataContext>();var UserType = builder.UserType;
var provider = typeof(NPTokenProvider<>).MakeGenericType(UserType);
builder.AddTokenProvider("NPTokenProvider", provider);services.AddDbContext<NPDataContext>(options =>
options.DefaultScheme = IdentityConstants.ExternalScheme;
app.UseAuthorization(); in the
Let’s create a controller for our login and verify the APIs. Create a
NoPasswordController.cs file in your
Controllers folder. Add the below content to the file.
using Microsoft.AspNetCore.Mvc;namespace NoPasswordProject.Controllers
public class NoPasswordController : ControllerBase
private readonly UserManager<IdentityUser> _userManager;public NoPasswordController(UserManager<IdentityUser> userManager)
_userManager = userManager;
We are injecting an instance of
UserManager in our controller. UserManager is used for CRUD operations for a user as well as generating tokens and validating them.
Let’s add a
Login API which accepts an Email as input. The Email is the unique identifier for a user, that is there should be a one-to-one relationship between user and email.
Create a new function in your controller as below.
public async Task<ActionResult<String>> Login([FromQuery] string Email)
// Create or Fetch your user from the database
var User = await _userManager.FindByNameAsync(Email);
if (User == null)
User = new IdentityUser();
User.Email = Email;
User.UserName = Email;
var IdentityResult = await _userManager.CreateAsync(User);
if (IdentityResult.Succeeded == false)
} var Token = await _userManager.GenerateUserTokenAsync(User, "NPTokenProvider", "nopassword-for-the-win"); // DON'T RETURN THE TOKEN.
// SEND IT TO THE USER VIA EMAIL.
Here we are fetching a User from the database. If the user doesn’t exist then we create a user. Make sure to set the UserName as well or it will give a runtime error.
Then based on the user, we generate a
GenerateUserTokenAsync takes the user, token provider, and the purpose for generating a token.
The token provider string should be the one you have used in
NPTokenProviderOptions. The purpose can be anything you want.
Send out the token to the user via a link in a nicely designed email. When the user clicks on the link in the email it will open your front-end page. Consequently this page will request the Verify API.
Let’s add another API called
Verify that takes the
Token as query parameters.
public async Task<ActionResult<String>> Verify([FromQuery] string Token, [FromQuery] string Email)
// Fetch your user from the database
var User = await _userManager.FindByNameAsync(Email);
if (User == null)
}var IsValid = await _userManager.VerifyUserTokenAsync(User, "NPTokenProvider", "nopassword-for-the-win", Token);
// TODO: Generate a bearer token
var BearerToken = "";
We are again fetching the user based on email. As a result, if we are not able to find the user we’ll return 404 Not Found.
We then continue to verify the user.
VerifyUserTokenAsync takes user, token provider, purpose, and token as input parameters. The purpose should be the same as the one used while generating the token.
If the token is not valid, return 401 Unauthorised. Otherwise return the bearer token. This is a good article on how to generate a bearer token for the user.
You can find the whole project here.
Good features used to be the main thing that mattered when creating an app. But today, besides having great features convenience is a priority for users.
In this article, we looked at one way you can make your apps more user-friendly. Let me know if you have other ways to improve your apps.
Check here for more tutorials like this.