AspNetCore.Identity.CosmosDb 2.0.6

There is a newer version of this package available.
See the version list below for details.
dotnet add package AspNetCore.Identity.CosmosDb --version 2.0.6                
NuGet\Install-Package AspNetCore.Identity.CosmosDb -Version 2.0.6                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AspNetCore.Identity.CosmosDb" Version="2.0.6" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add AspNetCore.Identity.CosmosDb --version 2.0.6                
#r "nuget: AspNetCore.Identity.CosmosDb, 2.0.6"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install AspNetCore.Identity.CosmosDb as a Cake Addin
#addin nuget:?package=AspNetCore.Identity.CosmosDb&version=2.0.6

// Install AspNetCore.Identity.CosmosDb as a Cake Tool
#tool nuget:?package=AspNetCore.Identity.CosmosDb&version=2.0.6                

<h1 valign="center"><img src="./Assets/cosmosdb.svg"/> Cosmos DB Provider for ASP.NET Core Identity</h1>

.NET 6 Build-Test CodeQL Unit Tests

This is a Cosmos DB implementation of an Identity provider for .NET 6 that uses the "EF Core Azure Cosmos DB Provider."

This project was forked from Piero De Tomi's excellent project: efcore-identity-cosmos. If you are using .Net 5, it is highly recommended using that project instead of this one.

Questions and Feedback Welcome

Need help getting started, or have feedback on how we can improve this product, let us know!

We appreciate feedback through this project's discussion boards and issues list! That greatly helps us know what to improve with this project.

Installation (NuGet)

To add this provider to your own Asp.Net 6 web project, add the following NuGet package:

PM> Install-Package AspNetCore.Identity.CosmosDb

Integration Steps

Cosmos Account and optional SendGrid API Key

The following instructions show how to install the Cosmos DB identity provider. To continue please have the following ready:

  • Azure Cosmos DB account - either the serverless or dedicated instance. You do not have to create a database yet.
  • A SendGrid API Key if you are using the IEmailProvider used in these instructions

Note: This provider requires too many containers to use the free version of Cosmos DB. The serverless instance is very economical and is a good option to start with. See documentation to help choose which is best for you.

Application Configuration "Secrets"

Three secrets need to be created for this example:

  • SendGridApiKey (The API key for your SendGrid account)
  • CosmosIdentityDbName (The name of the database you want to use)
  • ConnectionStrings:ApplicationDbContextConnection (The connection string for your Cosmos account)

And if you want the provider to automatically setup the database and required containers, use this setting:

  • SetupCosmosDb

Here is an example of how to set the secrets in a secrets.json file that would be used with Visual Studio:

{
  "SendGridApiKey": "YOUR SENDGRID API KEY",
  "SetupCosmosDb": "true", // Importat: Remove this after first run.
  "CosmosIdentityDbName": "YourDabatabaseName",
  "ConnectionStrings": {
    "ApplicationDbContextConnection": "THE CONNECTION STRING TO YOUR COSMOS ACCOUNT"
  }
}

Update Database Context (ApplicationDbContext.cs)

Here you will need to modify the database context to inherit from the CosmosIdentityDbContext. Often the database context can be found in this location:

/Data/ApplicationDbContext.cs

Now modify the file above to look like this:

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;

namespace AspNetCore.Identity.CosmosDb.Example.Data
{
    public class ApplicationDbContext : CosmosIdentityDbContext<IdentityUser>
    {
        public ApplicationDbContext(DbContextOptions dbContextOptions)
          : base(dbContextOptions) { }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            // DO NOT REMOVE THIS LINE. If you do, your context won't work as expected.
            base.OnModelCreating(builder);

            // TODO: Add your own fluent mappings
        }
    }
}

Modify Program.cs or Startup.cs File

After the "secrets" have been set, the next task is to modify your project's startup file. For Asp.net 6 and higher that might be the Project.cs file. For other projects it might be your Startup.cs.

You will likely need to add these usings:

using AspNetCore.Identity.CosmosDb;
using AspNetCore.Identity.CosmosDb.Containers;
using AspNetCore.Identity.CosmosDb.Extensions;
using AspNetCore.Identity.Services.SendGrid;
using AspNetCore.Identity.Services.SendGrid.Extensions;

Next, the configuration variables need to be retrieved. Add the following to your startup file:

// The Cosmos connection string
var connectionString = builder.Configuration.GetConnectionString("ApplicationDbContextConnection");

// Name of the Cosmos database to use
var cosmosIdentityDbName = builder.Configuration.GetValue<string>("CosmosIdentityDbName");

// If this is set, the Cosmos identity provider will:
// 1. Create the database if it does not already exist.
// 2. Create the required containers if they do not already exist.
// IMPORTANT: Remove this setting if after first run. It will improve startup performance.
var setupCosmosDb = builder.Configuration.GetValue<string>("SetupCosmosDb");

Next, add the code that will trigger the provider to create the database and required containers:

// If the following is set, then create the identity database and required containers.
// You can omit the following, or simplify it as needed.
if (bool.TryParse(setupCosmosDb, out var setup) && setup)
{
    var utils = new ContainerUtilities(connectionString, cosmosIdentityDbName);
    utils.CreateDatabaseAsync(cosmosIdentityDbName).Wait();
    utils.CreateRequiredContainers().Wait();
}

Now add the database context that is required for this provider. Note: This context can be modified to add your own entities (documentation on that is being developed).

Put this in your startup file:

builder.Services.AddDbContext<CosmosIdentityDbContext<IdentityUser>>(options =>
  options.UseCosmos(connectionString: connectionString, databaseName: cosmosIdentityDbName));

The next step is to add the identity provider to your starup file. Here is an example:

builder.Services.AddCosmosIdentity<CosmosIdentityDbContext<IdentityUser>, IdentityUser, IdentityRole>(
      options => options.SignIn.RequireConfirmedAccount = true // Always a good idea :)
    )
    .AddDefaultTokenProviders();

Configure Email Provider

When users register accounts or need to reset passwords, you will need (at a minimum), the ability to send tokens via an Email provider. The example below uses a SendGrid provider. Here is how to add it:

Start by adding the following NuGet package to your project:

PM> Install-Package AspNetCore.Identity.Services.SendGrid

Note: You can sign up for a free SendGrid account if you do not already have one.

Configure app to support email

Next we need to configure the application to support our Email provider. Start by adding the following code to your startup file:

var sendGridApiKey = builder.Configuration.GetValue<string>("SendGridApiKey");
// Modify 'from' email address to your own.
var sendGridOptions = new SendGridEmailProviderOptions(sendGridApiKey, "foo@mycompany.com");

builder.Services.AddSendGridEmailProvider(sendGridOptions);

Modify "Scaffolded" Identity UI

The example web project uses the "scaffolded" Identity UI. By default it does not use an IEmailProvider. But in our case we have installed one so we need to modify the UI to enable it.

In your project, find this file:

/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs

Find the OnGetAsync() method, then look for the following line:

DisplayConfirmAccountLink = true;

Change that line to false like the following:

DisplayConfirmAccountLink = false;

Complete Startup File Example

The above instructions showed how to modify the startup file to make use of this provider. Sometimes it is easier to see the end result rather than peicemeal. Here is an example Asp.Net 6 Project.cs file fully configured:

using AspNetCore.Identity.CosmosDb;
using AspNetCore.Identity.CosmosDb.Containers;
using AspNetCore.Identity.CosmosDb.Extensions;
using AspNetCore.Identity.Services.SendGrid;
using AspNetCore.Identity.Services.SendGrid.Extensions;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

// The Cosmos connection string
var connectionString = builder.Configuration.GetConnectionString("ApplicationDbContextConnection");

// Name of the Cosmos database to use
var cosmosIdentityDbName = builder.Configuration.GetValue<string>("CosmosIdentityDbName");

// If this is set, the Cosmos identity provider will:
// 1. Create the database if it does not already exist.
// 2. Create the required containers if they do not already exist.
// IMPORTANT: Remove this variable if after first run. It will improve startup performance.
var setupCosmosDb = builder.Configuration.GetValue<string>("SetupCosmosDb");

// If the following is set, then create the identity database and required containers.
// You can omit the following, or simplify it as needed.
if (bool.TryParse(setupCosmosDb, out var setup) && setup)
{
    var utils = new ContainerUtilities(connectionString, cosmosIdentityDbName);
    utils.CreateDatabaseAsync(cosmosIdentityDbName).Wait();
    utils.CreateRequiredContainers().Wait();
}

//
// Add the Cosmos database context here
//
builder.Services.AddDbContext<CosmosIdentityDbContext<IdentityUser>>(options =>
  options.UseCosmos(connectionString: connectionString, databaseName: cosmosIdentityDbName));

//
// Add Cosmos Identity here
//
builder.Services.AddCosmosIdentity<CosmosIdentityDbContext<IdentityUser>, IdentityUser, IdentityRole>(
      options => options.SignIn.RequireConfirmedAccount = true
    )
    .AddDefaultTokenProviders();

//
// Must have an Email sender when using Identity Framework.
// You will need an IEmailProvider. Below uses a SendGrid EmailProvider. You can use another.
// Below users NuGet package: AspNetCore.Identity.Services.SendGrid
var sendGridApiKey = builder.Configuration.GetValue<string>("SendGridApiKey");
// Modify 'from' email address to your own.
var sendGridOptions = new SendGridEmailProviderOptions(sendGridApiKey, "foo@mycompany.com");
builder.Services.AddSendGridEmailProvider(sendGridOptions);
// End add SendGrid

builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for
    // production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

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

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();

app.Run();

TIP: Download and run a working website that implements these instructions.

Supported LINQ Operators User and Role Stores

Both the user and role stores now support queries via LINQ using Entity Framework. Here is an example:

var userResults = userManager.Users.Where(u => u.Email.StartsWith("bob"));
var roleResults = roleManager.Roles.Where (r => r.Name.Contains("water"));

For a list of supported LINQ operations, please see the "Supported LINQ Operations" documentation for more details.

Changelog

v1.0.6

  • Introduced support for IUserLoginStore<TUser> in User Store

v1.0.5

  • Introduced support for IUserPhoneNumberStore<TUser> in User Store

v1.0.4

  • Introduced support for IUserEmailStore<TUser> in User Store

v2.0.0-alpha

  • Forked from source repository pierodetomi/efcore-identity-cosmos.
  • Refactored for .Net 6 LTS.
  • Added UserStore, RoleStore, UserManager and RoleManager unit tests.
  • Namespace changed to one more generic: AspNetCore.Identity.CosmosDb
  • Implemented IUserLockoutStore interface for UserStore

v2.0.1.0

  • Added example web project

v2.0.5.1

  • Implemented IQueryableUserStore and IQueryableRoleStore

References

To learn more about Asp.Net Identity and items realted to this project, please see the following:

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on AspNetCore.Identity.CosmosDb:

Package Downloads
Cosmos.Cms.Common

This package contains all the common methods and objects used by the Cosmos CMS editor website, and by any website service the role of a publishing website.

Cosmos.Common

This package contains all the common methods and objects used by the Cosmos CMS editor website, and by any website service the role of a publishing website.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
8.0.7 1,871 9/3/2024
8.0.6 2,451 5/29/2024
8.0.4 562 4/18/2024
8.0.3 845 3/12/2024
8.0.2 936 2/15/2024
8.0.1 1,438 1/12/2024
8.0.0 824 12/18/2023
8.0.0-rc.3 77 12/15/2023
2.1.4 7,082 1/30/2023
2.1.3 672 12/15/2022
2.1.2 491 11/16/2022
2.1.1 510 11/11/2022
2.0.22 401 11/9/2022
2.0.21 402 11/6/2022
2.0.20 1,299 10/27/2022
2.0.19-rc 156 10/26/2022
2.0.18 893 9/24/2022
2.0.17 412 9/5/2022
2.0.16 711 8/24/2022
2.0.15 477 8/13/2022
2.0.14 411 8/11/2022
2.0.13 450 8/8/2022
2.0.12 459 7/31/2022
2.0.11 461 7/23/2022
2.0.10 473 7/13/2022
2.0.9 448 7/12/2022
2.0.8 476 7/12/2022
2.0.7 454 7/8/2022
2.0.6 456 7/8/2022
2.0.5.1 459 7/6/2022
2.0.4 464 7/5/2022
2.0.3.3 460 7/4/2022
2.0.3.2 483 7/3/2022
2.0.3.1 482 7/3/2022
2.0.2.1 471 7/1/2022
2.0.1-alpha 192 6/30/2022
2.0.0-alpha 203 6/25/2022

Updated Readme.md