This project has moved. For the latest updates, please go here.

High Level Dependencies

AzureIdentityTableDependency.png
ElCamino.AspNet.Identity.AzureTable.dll acts as the data access layer under the Microsoft.AspNet.Identity.Core.dll classes UserManager and RoleManager by implementing the necessary interfaces on the UserStore and RoleStore respectively. These classes consume the IdentityCloudContext and the other Identity Model classes described below to persist the user and role information according to the business logic dictated by the respective UserManager and RoleManager classes.

UserStore and RoleStore Classes

IdentityUserStoreRoleStore.png

IdentityCloudContext and Connections

IdentityCloudContext that enables access to the Azure Table storage service and exposes the tables.
The IdentityCloudContext default constructor will look for the IdentityConfigurationSection in the app or web.config which is new in version 1.2.9.0. If this configuration section is not found, the storage connection string under the AppSettings key "StorageConnectionString" which is a deprecated option that will be phased out in lieu of the configuration section or the new IdentityCloudContext(IdentityConfiguration config) overload. The new IdentityConfiguration class is Json serializable for ease of loading/saving these settings.
New in 1.2.9.0 - use the new TablePrefix property to set a naming prefix for the azure tables that are using in the storage account. This enables multi-tenant support per storage account via configuration option for table name prefixing. e.g. Table prefix 'My' uses tables, MyAspNetIndex, MyAspNetRoles, MyAspNetUsers. This is an optional field, can be set to string.empty or left unset.
Example of using the new configuration section:
  <configSections>
    <section name="elcaminoIdentityConfiguration" type="ElCamino.AspNet.Identity.AzureTable.Configuration.IdentityConfigurationSection,ElCamino.AspNet.Identity.AzureTable " />
  </configSections>
  <elcaminoIdentityConfiguration tablePrefix="" storageConnectionString="UseDevelopmentStorage=true" />
...

Note: the following appSettings configuration option has been deprecated in 1.2.9.0. A custom AppSettings key can be passed in the overloaded constructor IdentityCloudContext(string appSettingsKey). If the appSettingsKey is not found, the literal string will be assumed to be the connection string.
For example, the default local connection string to the Azure Storage Emulator.
<configuration>
  <appSettings>
    ...
    <add key="StorageConnectionString" value="UseDevelopmentStorage=true" />

Identity Model to Azure Table Relationships

IdentityModelToAzureTable.png

AspNetUsers

Identity Model PartitionKey RowKey Cardinality
IdentityUser Escaped(UserName) Escaped(UserName) 1 per user
IdentityUserClaim Escaped(UserName) Escaped(ClaimType, ClaimValue) 0 to Many per user
IdentityUserLogin Escaped(UserName) Escaped(LoginProvider, ProviderKey) 0 to Many per user
IdentityUserRole Escaped(UserName) Escaped(RoleName) 0 to Many per user

AspNetIndex

Identity Model Type PartitionKey RowKey Id Cardinality
IdentityUserIndex User Email Index Escaped(First Char of Email) Escaped(User Email) Escaped(UserName) 0 or 1 per user
IdentityUserIndex User Login Index Escaped(LoginProvider) Escaped(LoginProvider, ProviderKey) Escaped(UserName) 0 to Many per user

AspNetRoles

Identity Model PartitionKey RowKey
IdentityRole Escaped(First Char of RoleName) Escaped(RoleName)


The properties of the respective identity model class are stored as a field in the table unless marked with the ignore attribute. Inheriting and extending these classes one can add fields whenever your extended class is saved. Also, the Escaped() psydo-code is a reference to the respective methods found in the KeyHelper class.

Performance

The AspNetUsers table is designed to keep all of the user's data in a single table and in a table partition for each user. This results in a single query using the user's id (partition key) to get all of the data in a single query when the user's id is known. The user's id is an 'Escaped' version of the username and the traditional guid is not used. This makes the UserStore.FindByUserNameAsync() and UserStoreFindByUserNameAsync() use the same query. When the user id is not known, the AspNetIndex table is queried first either by user's email UserStore.FindByEmailAsync() or external login information UserStore.FindAsync() to get the user's id to then query by user id for the complete user information. The AspNextIndex is always queried by partition and rowkey making that query extremely fast. See above for the details of the AspNetIndex partition and rowkey strategy.
AspNetRoles table also uses a composite of the RoleName for the partition and row keys making it possible query the table by its primary key optimizing performance.

Testing

A full suite of unit tests against this assembly ElCamino.AspNet.Identity.AzureTable.Tests.csproj

Release Management

  • Full suite of unit tests against this assembly at 100% pass rate against the Azure Local Emulator and against a live Azure Storage account. 100% pass rate is required before release. The tests are at about 99% code coverage currently and will work to keep the up.
  • Releases available on NuGet and are strong name signed. Binaries are available for download from this site.
  • https://www.nuget.org/packages/ElCamino.AspNet.Identity.AzureTable/

Last edited Sep 14, 2014 at 11:39 PM by dotnetdavy, version 8