identity entityframework

in Architetture Software

IdentityServer4 – Sql Server

Reading Time: 2 minutes

Nel post precedente abbiamo implementato una semplice applicazione che utilizza IdentityServer4 con dati in memory. Ovviamente, questo tipo di soluzione non può essere utilizzata in ambiente di produzione. In questo caso è necessario effettuare una migrazione dalla configurazione in memoria verso una soluzione basata su database. Nel nostro caso, utilizzeremo SQL Server ed ovviamente Entity Framework.

Il pacchetto nuget che deve essere installato per poter utilizzare EntityFramework con IdentityServer è:

IdentityServer4.EntityFramework

Il passo successivo è quello di modificare Startup.cs sostituendo il codice che utilizza le risorse in memory, con quelle per la persistenza dei dati su database. In particolare, il blocco:

var builder = services.AddIdentityServer()
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApis())
                .AddInMemoryClients(Config.GetClients());

dovrà essere sostituito da:

string connectionString = Configuration.GetConnectionString("DefaultConnection");
 
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
 
var builder = services.AddIdentityServer(options =>
{
	options.Events.RaiseErrorEvents = true;
	options.Events.RaiseInformationEvents = true;
	options.Events.RaiseFailureEvents = true;
	options.Events.RaiseSuccessEvents = true;
	options.UserInteraction.LoginUrl = "/Account/Login";
	options.UserInteraction.LogoutUrl = "/Account/Logout";
	options.Authentication = new AuthenticationOptions()
	{
		CookieLifetime = TimeSpan.FromHours(10), // ID server cookie timeout set to 10 hours
		CookieSlidingExpiration = true
	};
})
.AddConfigurationStore(options =>
{
	options.ConfigureDbContext = b => b.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly));
})
.AddOperationalStore(options =>
{
	options.ConfigureDbContext = b => b.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly));
	options.EnableTokenCleanup = true;
});

Oltre ad un serie di options legate legate alla definizione degli entry point per il login ed il logout, sono state aggiunte le configurazioni AddConfigurationStore(…) e AddOperationalStore(…) per l’utilizzo di SqlServer.

Per maggiore completezza e facilità di gestione della configurazione modificheremo Startup.cs nel seguente modo:

public Startup(IHostingEnvironment environment, IConfiguration configuration)
{
   ...
   ...
}

in modo da accettare in ingresso un oggetto di tipo Iconfiguration. Questo passaggio si rende necessario per poter effettuare l’inject tramite DI della configurazione, che dovrà essere letta da un file esterno. Un oggetto di tipo Iconfiguration, infatti, mette a disposizione tutte le proprietà per la lettura i file di configurazione. Per la nostra applicazione, creeremo un file appsettings.json all’interno del quale inserire la stringa di connessione da utilzzare con SqlServer.

{
	"ConnectionStrings": {
		"DefaultConnection": "Server=(localdb)\MSSQLLocalDB;Database=IdentityServerQuickstart;Trusted_Connection=True;MultipleActiveResultSets=true"
	}
}

Una volta creato il database vuoto, sarà necessario effettuare la migrazione per ricreare la struttura in memory all’interno delle tabelle del database:

Add-Migration InitialPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb
Add-Migration InitialConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServe

Update-Database -Context PersistedGrantDbContext
Update-Database -Context ConfigurationDbContext

I comandi precedenti consentono proprio di creare un oggetto migrazione per i grant e per la configurazione, e di aggiornare il database creando le nuove tabelle.

La struttura finale del database sarà:

In questo posto abbiamo effettuato la migrazione da un sistema in memory ad un sistema in cui i dati sono resi persistenti all’interno di un database, tramite entity-framework.