{"id":26667,"date":"2020-05-20T00:00:00","date_gmt":"2020-05-19T22:00:00","guid":{"rendered":"https:\/\/blexin.com\/?p=26667"},"modified":"2021-06-09T12:13:26","modified_gmt":"2021-06-09T10:13:26","slug":"angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker","status":"publish","type":"post","link":"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/","title":{"rendered":"Angular, Microservizi e Autenticazione con IdentityServer, MongoDB e Docker"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"608\" data-attachment-id=\"26669\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/attachment\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png?fit=1024%2C608&amp;ssl=1\" data-orig-size=\"1024,608\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png?fit=1024%2C608&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png?resize=1024%2C608&#038;ssl=1\" alt=\"\" class=\"wp-image-26669\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png 1024w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0-980x582.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0-480x285.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In un mio\u00a0<a href=\"https:\/\/blexin.com\/it\/blog\/angular-microservices-e-autenticazione\/\" target=\"_blank\" rel=\"noreferrer noopener\">articolo precedente\u00a0<\/a>, abbiamo parlato di microservizi e come autenticare un client Angular con essi usando IdentityServer come authentication authority. In quel caso, ho usato la configurazione in memoria per semplificare il concetto, ma in un&#8217;applicazione reale abbiamo bisogno di salvare i dati in uno storage persistente come un database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Visto che in un progetto ho usato MongoDB per alcuni microservizi, ho pensato fosse utile usare l\u2019istanza di Mongo per salvare anche i dati di IdentityServer, ovviamente in un database separato, e la cosa ha avuto dei risvolti interessanti che vale la pena raccontare. Inoltre, in uno scenario di sviluppo reale, non avrete mai tutti i microservizi e i client in uno stesso repository, quindi, lavorare in localhost pu\u00f2 diventare un problema, che per\u00f2 \u00e8 facilmente risolvibile utilizzando docker e docker-compose. Anche questo aspetto ha dei risvolti interessanti perch\u00e9 vi mette di fronte ad alcune considerazioni di networking che in localhost sfuggono sicuramente.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>IdentityServer e MongoDB<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Cominciamo dall\u2019integrazione di MongoDB con IdentityServer. Esistono alcune librerie pronte all&#8217;uso per questo scopo, ma le migliori utilizzano entity framework, come layer intermedio per archiviare dati su MongoDB. Non capisco il motivo dell&#8217;uso di un ORM con un database NoSql, penso che non abbia senso, ma ho accettato l\u2019idea che si tratti di una comodit\u00e0 per poter cambiare storage quando riutilizzo qualcosa in un progetto differente, perch\u00e8 diciamocelo\u2026 cambiare database in un progetto in produzione \u00e8 una favola che viene raccontata ai bambini e ai giovani programmatori.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ho quindi utilizzato una mia implementazione generica del&nbsp;<em>Repository<\/em>&nbsp;pattern per MongoDB:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic interface IRepository\n{\n\u00a0\u00a0\u00a0\u00a0IQueryable&lt;T&gt; All&lt;T&gt;() where T : class, new();\n\u00a0\u00a0\u00a0\u00a0IQueryable&lt;T&gt; Where&lt;T&gt;(Expression&lt;Func&lt;T, bool&gt;&gt; expression) where T : class, new();\n\u00a0\u00a0\u00a0\u00a0T Single&lt;T&gt;(Expression&lt;Func&lt;T, bool&gt;&gt; expression) where T : class, new();\n\u00a0\u00a0\u00a0\u00a0void Delete&lt;T&gt;(Expression&lt;Func&lt;T, bool&gt;&gt; expression) where T : class, new();\n\u00a0\u00a0\u00a0\u00a0void Add&lt;T&gt;(T item) where T : class, new();\n\u00a0\u00a0\u00a0\u00a0void Add&lt;T&gt;(IEnumerable&lt;T&gt; items) where T : class, new();\n}\n\u00a0\npublic class MongoRepository : IRepository\n{\n\u00a0\u00a0\u00a0\u00a0private readonly IMongoClient _client;\n\u00a0\u00a0\u00a0\u00a0private readonly IMongoDatabase _database;\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public MongoRepository(string mongoConnection, string mongoDatabaseName)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_client = new MongoClient(mongoConnection);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_database = _client.GetDatabase(mongoDatabaseName);\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public IQueryable&lt;T&gt; All&lt;T&gt;() where T : class, new()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=&gt; _database.GetCollection&lt;T&gt;(typeof(T).Name).AsQueryable();\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public IQueryable&lt;T&gt; Where&lt;T&gt;(System.Linq.Expressions.Expression&lt;Func&lt;T, bool&gt;&gt; expression) where T : class, new()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=&gt; All&lt;T&gt;().Where(expression);\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public void Delete&lt;T&gt;(System.Linq.Expressions.Expression&lt;Func&lt;T, bool&gt; predicate) where T : class, new()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=&gt; _database.GetCollection&lt;T&gt;(typeof(T).Name).DeleteMany(predicate);\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public T Single&lt;T&gt;(System.Linq.Expressions.Expression&lt;Func&lt;T, bool&gt;&gt; expression) where T : class, new()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=&gt; All&lt;T&gt;().Where(expression).SingleOrDefault();\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public void Add&lt;T&gt;(T item) where T : class, new()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=&gt; _database.GetCollection&lt;T&gt;(typeof(T).Name).InsertOne(item);\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public void Add&lt;T&gt;(IEnumerable&lt;T&gt; items) where T : class, new()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=&gt; _database.GetCollection&lt;T&gt;(typeof(T).Name).InsertMany(items);\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Niente di complicato, \u00e8 un semplice utilizzo del driver C# ufficiale per MongoDB per implementare le operazioni CRUD del repository. Per poter usare il repository con IdentityServer, dobbiamo implementare le interfacce&nbsp;<strong>IResourceStore, IPersistedGrantStore<\/strong>&nbsp;e&nbsp;<strong>IClientStore<\/strong>&nbsp;con cui IdentityServer recupera le Resource, i Grant e i Client da utilizzare nel processo di autenticazione e generazione del token. A titolo di esempio, vi riporto l\u2019implementazione di&nbsp;<strong>IClientStore<\/strong>, le restanti classi le trovate sul mio repository GitHub:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class RepositoryClientStore : IClientStore\n{\n\u00a0\u00a0\u00a0\u00a0protected IRepository _repository;\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public RepositoryClientStore(IRepository repository)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=&gt; _repository = repository;\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public Task&lt;Client&gt; FindClientByIdAsync(string clientId)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=&gt; Task.FromResult(_repository.Single&lt;Client&gt;(c =&gt; c.ClientId == clientId));\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Creiamo una classe di helpers per registrare tutte queste interfacce in modo da rendere pi\u00f9 fluente la configurazione dei servizi:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic static class RepositoryExtensions\n{\n\u00a0\u00a0\u00a0\u00a0public static IIdentityServerBuilder AddMongoRepository(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this IIdentityServerBuilder builder,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0string mongoConnection,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0string mongoDatabaseName)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0builder.Services.AddTransient&lt;IRepository, MongoRepository&gt;(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0s =&gt; new MongoRepository(mongoConnection, mongoDatabaseName));\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return builder;\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public static IIdentityServerBuilder AddClients(this IIdentityServerBuilder builder)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0builder.Services.AddTransient&lt;IClientStore, RepositoryClientStore&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0builder.Services.AddTransient&lt;ICorsPolicyService, InMemoryCorsPolicyService&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return builder;\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public static IIdentityServerBuilder AddIdentityApiResources(this IIdentityServerBuilder builder)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0builder.Services.AddTransient&lt;IResourceStore, RepositoryResourceStore&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return builder;\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public static IIdentityServerBuilder AddPersistedGrants(this IIdentityServerBuilder builder)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0builder.Services.AddSingleton&lt;IPersistedGrantStore, RepositoryPersistedGrantStore&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return builder;\n\u00a0\u00a0\u00a0\u00a0}\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Niente di complicato, \u00e8 un semplice utilizzo del driver C# ufficiale per MongoDB per implementare le operazioni CRUD del repository. Per poter usare il repository con IdentityServer, dobbiamo implementare le interfacce&nbsp;<strong>IResourceStore, IPersistedGrantStore<\/strong>&nbsp;e&nbsp;<strong>IClientStore<\/strong>&nbsp;con cui IdentityServer recupera le Resource, i Grant e i Client da utilizzare nel processo di autenticazione e generazione del token. A titolo di esempio, vi riporto l\u2019implementazione di&nbsp;<strong>IClientStore<\/strong>, le restanti classi le trovate sul mio repository GitHub:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class RepositoryClientStore : IClientStore\n{\n\u00a0\u00a0\u00a0\u00a0protected IRepository _repository;\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public RepositoryClientStore(IRepository repository)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=&gt; _repository = repository;\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public Task&lt;Client&gt; FindClientByIdAsync(string clientId)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=&gt; Task.FromResult(_repository.Single&lt;Client&gt;(c =&gt; c.ClientId == clientId));\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Creiamo una classe di helpers per registrare tutte queste interfacce in modo da rendere pi\u00f9 fluente la configurazione dei servizi:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic static class RepositoryExtensions\n{\n\u00a0\u00a0\u00a0\u00a0public static IIdentityServerBuilder AddMongoRepository(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0this IIdentityServerBuilder builder,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0string mongoConnection,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0string mongoDatabaseName)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0builder.Services.AddTransient&lt;IRepository, MongoRepository&gt;(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0s =&gt; new MongoRepository(mongoConnection, mongoDatabaseName));\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return builder;\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public static IIdentityServerBuilder AddClients(this IIdentityServerBuilder builder)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0builder.Services.AddTransient&lt;IClientStore, RepositoryClientStore&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0builder.Services.AddTransient&lt;ICorsPolicyService, InMemoryCorsPolicyService&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return builder;\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public static IIdentityServerBuilder AddIdentityApiResources(this IIdentityServerBuilder builder)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0builder.Services.AddTransient&lt;IResourceStore, RepositoryResourceStore&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return builder;\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public static IIdentityServerBuilder AddPersistedGrants(this IIdentityServerBuilder builder)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0builder.Services.AddSingleton&lt;IPersistedGrantStore, RepositoryPersistedGrantStore&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return builder;\n\u00a0\u00a0\u00a0\u00a0}\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">A questo punto la configurazione diventa banale:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic void ConfigureServices(IServiceCollection services)\n{\n\u00a0\u00a0\u00a0\u00a0...\n\u00a0\u00a0\u00a0\u00a0var builder = services.AddIdentityServer(options =&gt;\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0options.Events.RaiseErrorEvents = true;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0options.Events.RaiseInformationEvents = true;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0options.Events.RaiseFailureEvents = true;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0options.Events.RaiseSuccessEvents = true;\n\u00a0\u00a0\u00a0\u00a0})\n\u00a0\u00a0\u00a0\u00a0.AddMongoRepository(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Configuration.GetValue&lt;string&gt;(&quot;MONGO_CONNECTION&quot;),\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Configuration.GetValue&lt;string&gt;(&quot;MONGO_DATABASE_NAME&quot;))\n\u00a0\u00a0\u00a0\u00a0.AddClients()\n\u00a0\u00a0\u00a0\u00a0.AddIdentityApiResources()\n\u00a0\u00a0\u00a0\u00a0.AddPersistedGrants();\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0seedDatabase(services);\n\u00a0\u00a0\u00a0\u00a0...\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Ho anche aggiunto un metodo privato&nbsp;<strong>seedDatabase()<\/strong>che inserisce nel database i dati che usavamo in memoria se rileva che le rispettive collection sono vuote:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nprivate void seedDatabase(IServiceCollection services)\n{\n\u00a0\u00a0\u00a0\u00a0configureMongoDriverIgnoreExtraElements();\n\u00a0\u00a0\u00a0\u00a0var sp = services.BuildServiceProvider();\n\u00a0\u00a0\u00a0\u00a0var repository = sp.GetService&lt;IRepository&gt;();\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0if (repository.All&lt;Client&gt;().Count() == 0)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0foreach (var client in Config.Clients)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0repository.Add&lt;Client&gt;(client);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0...\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Dato che andiamo a salvare su Mongo degli oggetti non nostri, ma di IdentityServer, dobbiamo istruire MongoDB sul fatto che non trover\u00e0 in queste classi alcuni elementi extra che vengono aggiunti dal motore del database durante la creazione dei documenti, come ad esempio la propriet\u00e0&nbsp;<strong>_id<\/strong>. Per farlo, ho creato un metodo privato che chiamo prima dell\u2019eventuale inserimento dei dati,&nbsp;<strong>configureMongoDriverIgnoreExtraElements():<\/strong><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nprivate void configureMongoDriverIgnoreExtraElements()\n{\n\u00a0\u00a0\u00a0\u00a0var pack = new ConventionPack();\n\u00a0\u00a0\u00a0\u00a0pack.Add(new IgnoreExtraElementsConvention(true));\n\u00a0\u00a0\u00a0\u00a0ConventionRegistry.Register(&quot;IdentityServer Mongo Conventions&quot;, pack, t =&gt; true);\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">In teoria abbiamo terminato, andiamo adesso a testare la nostra configurazione.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Docker e Docker Compose<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Visto che dobbiamo tirare su il demone di MongoDB, approfittiamo per cominciare a configurare il nostro\u00a0<em>docker-compose<\/em>, dove al momento mettiamo solo MongoDB. Se siete a digiuno di Docker potete leggere\u00a0<a href=\"https:\/\/blexin.com\/it\/blog\/net-core-docker-e-kubernetes\/\" target=\"_blank\" rel=\"noreferrer noopener\">un mio precedente articolo<\/a>\u00a0oppure il mio libro gratuito che parla anche di Kubernetes (<a href=\"https:\/\/www.syncfusion.com\/ebooks\/using-netcore-docker-and-kubernetes-succinctly\">https:\/\/www.syncfusion.com\/ebooks\/using-netcore-docker-and-kubernetes-succinctly<\/a>).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u0116 possibile creare manualmente il file&nbsp;<strong>docker-compose.yml<\/strong>&nbsp;nella root del progetto, oppure utilizzare i tool di Docker per Visual Studio Code:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"589\" data-attachment-id=\"26674\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/attachment\/image01-3-2\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-3.png?fit=1376%2C791&amp;ssl=1\" data-orig-size=\"1376,791\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image01-3\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-3.png?fit=1024%2C589&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-3.png?resize=1024%2C589&#038;ssl=1\" alt=\"\" class=\"wp-image-26674\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-3-980x563.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image01-3-480x276.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Modifichiamo lo script per tirare su il container con MongoDB e esponiamo la porta su localhost. In generale, non \u00e8 una bella cosa lasciare che Mongo salvi i dati all\u2019interno del container, ma per i nostri esempi e limitatamente alla fase di sviluppo, possiamo evitare di creare un volume per essi:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nversion: &#039;3.4&#039;\nservices:\n\u00a0mongodb:\n\u00a0\u00a0\u00a0image: mongo:latest\n\u00a0\u00a0\u00a0hostname: mongodb\n\u00a0\u00a0\u00a0ports:\n\u00a0\u00a0\u00a0\u00a0\u00a0- &quot;27017:27017&quot;\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">A questo punto possiamo eseguire lo script (<strong>docker-compose up<\/strong>) e una volta su, possiamo lanciare il progetto&nbsp;<em>IdentityServer<\/em>&nbsp;con il classico&nbsp;<strong>dotnet run<\/strong>. Se tutto va a buon fine vedrete le collection del database Mongo:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"588\" data-attachment-id=\"26677\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/attachment\/image02-2-2\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-2.png?fit=1375%2C790&amp;ssl=1\" data-orig-size=\"1375,790\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image02-2\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-2.png?fit=1024%2C588&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-2.png?resize=1024%2C588&#038;ssl=1\" alt=\"\" class=\"wp-image-26677\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-2-980x563.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image02-2-480x276.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Creiamo adesso un Dockerfile per poterlo containerizzare il nostro IdentityServer. Nella folder del progetto&nbsp;<strong>identityserver<\/strong>, creiamo un file&nbsp;<strong>Dockerfile<\/strong>&nbsp;che conterr\u00e0 le seguenti istruzioni:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nFROM mcr.microsoft.com\/dotnet\/core\/sdk:3.1 AS build\nWORKDIR \/app\nCOPY . .\nRUN dotnet restore\nRUN dotnet publish -c Release -o out\n\u00a0\u00a0\nFROM mcr.microsoft.com\/dotnet\/core\/aspnet:3.1 AS runtime\nWORKDIR \/app\nCOPY --from=build \/app\/out .\/\nENTRYPOINT &#x5B;&quot;dotnet&quot;, &quot;identityserver.dll&quot;]\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Aggiungiamo anche un .<strong>Dockerignore<\/strong>&nbsp;per escludere dalla copia dei file nel container le cartelle&nbsp;<strong>bin<\/strong>&nbsp;e&nbsp;<strong>obj<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/bin\n\/obj\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Aggiungiamo la build del Dockerfile al nostro script&nbsp;<strong>docker-compose.yml<\/strong>&nbsp;in modo da avere tutto pronto per il client e i microservizi:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nversion: &#039;3.4&#039;\nservices:\n\u00a0identityserver:\n\u00a0\u00a0\u00a0build: .\/identityserver\n\u00a0\u00a0\u00a0environment:\n\u00a0\u00a0\u00a0\u00a0\u00a0- MONGO_CONNECTION=mongodb:\/\/mongodb\n\u00a0\u00a0\u00a0\u00a0\u00a0- MONGO_DATABASE_NAME=identityserber\n\u00a0\u00a0\u00a0ports:\n\u00a0\u00a0\u00a0\u00a0\u00a0- &quot;5000:80&quot;\n\u00a0\u00a0\u00a0depends_on:\n\u00a0\u00a0\u00a0\u00a0\u00a0- mongodb\n\u00a0\u00a0\n\u00a0mongodb:\n\u00a0\u00a0\u00a0image: mongo:latest\n\u00a0\u00a0\u00a0hostname: mongodb\n\u00a0\u00a0\u00a0ports:\n\u00a0\u00a0\u00a0\u00a0\u00a0- &quot;27017:27017&quot;\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">In realt\u00e0, non c\u2019\u00e8 pi\u00f9 bisogno di esporre la porta di MongoDB su&nbsp;<em>localhost<\/em>, dato che il container&nbsp;<em>identityserver<\/em>&nbsp;si connetter\u00e0 a Mongo utilizzando la network di default creata da Docker e risolver\u00e0 l\u2019indirizzo del database attraverso il nome del service (<em>mongodb<\/em>). Nonostante questo, ho lasciato il forwarding della porta per comodit\u00e0, in modo da potermi sempre collegare con un client come&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/robomongo.org\/\" target=\"_blank\">Robo 3T&nbsp;<\/a>, per ispezionare le collection. Lanciando il comando&nbsp;<strong>docker-compose up<\/strong>, viene prima creata l\u2019immagine per IdentityServer (solo la prima volta) e poi lanciati entrambi i container, quindi aprendo il browser all\u2019indirizzo&nbsp;<strong><a href=\"http:\/\/localhost:5000\/account\/login\" rel=\"nofollow\">http:\/\/localhost:5000\/account\/login<\/a><\/strong>&nbsp;vedremo IdentityServer risponderci correttamente:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"660\" data-attachment-id=\"26680\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/attachment\/image03-2-2\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-2.png?fit=1099%2C708&amp;ssl=1\" data-orig-size=\"1099,708\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image03-2\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-2.png?fit=1024%2C660&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-2.png?resize=1024%2C660&#038;ssl=1\" alt=\"\" class=\"wp-image-26680\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-2-1024x660.png 1024w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-2-980x631.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image03-2-480x309.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">A questo punto, possiamo lanciare il client Angular e vedere se riusciamo ad eseguire l\u2019autenticazione. Andiamo nella cartella&nbsp;<strong>client-angular<\/strong>&nbsp;e lanciamo il solito comando&nbsp;<strong>ng serve<\/strong>, apriamo il browser all\u2019indirizzo&nbsp;<strong><a href=\"http:\/\/localhost:4200\" rel=\"nofollow\">http:\/\/localhost:4200<\/a><\/strong>&nbsp;e verifichiamo di essere reindirizzati alla pagina di autenticazione:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"593\" data-attachment-id=\"26683\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/attachment\/image04-2-2\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image04-2.png?fit=1360%2C788&amp;ssl=1\" data-orig-size=\"1360,788\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image04-2\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image04-2.png?fit=1024%2C593&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image04-2.png?resize=1024%2C593&#038;ssl=1\" alt=\"\" class=\"wp-image-26683\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image04-2-980x568.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image04-2-480x278.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Purtroppo, nonostante la pagina di autenticazione sia raggiungibile, otteniamo un errore&nbsp;<em>CORS<\/em>, che sembrerebbe legittimo a causa della differenza di porta tra client (4200) e server (5000). Ma allora perch\u00e9 nell\u2019articolo precedente lo stesso esempio funzionava senza problemi? Premesso che spesso e volentieri IdentityServer risponde con un errore CORS anche per errori diversi come, ad esempio un errore di accesso ai dati, in questo caso il problema segnalato \u00e8 quello giusto.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nell\u2019articolo precedente, le origini dei Client registrati venivano automaticamente aggiunti alle origini autorizzate, quindi il&nbsp;<strong>localhost:4200<\/strong>&nbsp;dovrebbe essere tra queste. Se per\u00f2 consultiamo la documentazione ufficiale,&nbsp;<a href=\"https:\/\/identityserver4.readthedocs.io\/en\/latest\/topics\/cors.html\" target=\"_blank\" rel=\"noreferrer noopener\">alla sezione CORS&nbsp;<\/a>scopriamo un effetto collaterale del non aver usato Entity Framework:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>\u201cThis default CORS implementation will be in use if you are using either the \u201cin-memory\u201d or EF-based client configuration that we provide. If you define your own IClientStore, then you will need to implement your own custom CORS policy service (see below)\u201d.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quindi non ci scoraggiamo e implementiamo il nostro CORS policy service:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic class RepositoryCorsPolicyService : ICorsPolicyService\n{\n\u00a0\u00a0\u00a0\u00a0private readonly string&#x5B;] _allowedOrigins;\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public RepositoryCorsPolicyService(IRepository repository)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_allowedOrigins = repository.All&lt;Client&gt;().SelectMany(x =&gt; x.AllowedCorsOrigins).ToArray();\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0public Task&lt;bool&gt; IsOriginAllowedAsync(string origin)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=&gt; Task.FromResult(_allowedOrigins.Contains(origin));\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Non ci resta che registrare la nostra implementazione:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic void ConfigureServices(IServiceCollection services)\n{\n\u00a0\u00a0\u00a0\u00a0...\n\u00a0\u00a0\u00a0\u00a0var builder = services.AddIdentityServer(options =&gt;\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0...\n\u00a0\u00a0\u00a0\u00a0})\n\u00a0\u00a0\n\u00a0\u00a0\u00a0\u00a0...\n\u00a0\u00a0\u00a0\u00a0services.AddSingleton&lt;ICorsPolicyService, RepositoryCorsPolicyService&gt;();\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Ricordatevi di aggiungere la vostra registrazione DOPO&nbsp;<strong>AddIdentityServer()<\/strong>, altrimenti sar\u00e0 sovrascritta da quella standard che non interrogher\u00e0 i vostri Client. Forziamo la rigenerazione dell\u2019immagine Docker utilizzando il comando&nbsp;<strong>docker-compose build &#8211;no-cache<\/strong>&nbsp;e riproviamo con&nbsp;<strong>docker-compose up<\/strong>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"548\" data-attachment-id=\"26686\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/attachment\/image05-2-2\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image05-2.png?fit=1283%2C687&amp;ssl=1\" data-orig-size=\"1283,687\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image05-2\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image05-2.png?fit=1024%2C548&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image05-2.png?resize=1024%2C548&#038;ssl=1\" alt=\"\" class=\"wp-image-26686\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image05-2-980x525.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image05-2-480x257.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Questa volta tutto funzioner\u00e0 correttamente, dandoci accesso all\u2019applicazione subito dopo l\u2019autenticazione. Se provate a lanciare anche i microservizi vedrete che risponderanno senza problemi. Finito quindi? Per completare il giro non ci resta che dockerizzare anche i due microservizi, rendendo configurabili i parametri di comunicazione con IdentityServer, dato che non siamo pi\u00f9 in localhost, ma nella rete di default di Docker:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic void ConfigureServices(IServiceCollection services)\n{\n\u00a0\u00a0\u00a0\u00a0services.AddAuthentication(options =&gt;\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0...\n\u00a0\u00a0\u00a0\u00a0}).AddJwtBearer(o =&gt;\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0o.Authority = Configuration.GetValue&lt;string&gt;(&quot;IDENTITY_AUTHORITY&quot;);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0o.Audience = Configuration.GetValue&lt;string&gt;(&quot;IDENTITY_AUDIENCE&quot;);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0o.RequireHttpsMetadata = Configuration.GetValue&lt;bool&gt;(&quot;IDENTITY_REQUIREHTTPSMETADATA&quot;);\n\u00a0\u00a0\u00a0\u00a0});\n\u00a0\u00a0\u00a0\u00a0...\n}\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">A questo punto, possiamo utilizzare lo stesso Dockerfile usato per IdentityServer (sono entrambe applicazioni ASP.NET Core) in cui modifichiamo solo il nome dell\u2019assembly da lanciare su&nbsp;<strong>ENTRYPOINT<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n...\nENTRYPOINT &#x5B;&quot;dotnet&quot;, &quot;microservice1.dll&quot;]\n\u00a0\u00a0\n...\nENTRYPOINT &#x5B;&quot;dotnet&quot;, &quot;microservice2.dll&quot;]\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Modifichiamo il file&nbsp;<strong>docker-compose.yml<\/strong>&nbsp;aggiungendo i due servizi:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nversion: &#039;3.4&#039;\nservices:\n\u00a0microservice1:\n\u00a0\u00a0\u00a0build: .\/microservice1\n\u00a0\u00a0\u00a0environment:\n\u00a0\u00a0\u00a0\u00a0\u00a0- IDENTITY_AUTHORITY=http:\/\/identityserver\n\u00a0\u00a0\u00a0ports:\n\u00a0\u00a0\u00a0\u00a0\u00a0- &quot;5002:80&quot;\n\u00a0\u00a0\u00a0depends_on:\n\u00a0\u00a0\u00a0\u00a0\u00a0- identityserver\n\u00a0\u00a0\n\u00a0microservice2:\n\u00a0\u00a0\u00a0build: .\/microservice2\n\u00a0\u00a0\u00a0environment:\n\u00a0\u00a0\u00a0\u00a0\u00a0- IDENTITY_AUTHORITY=http:\/\/identityserver\n\u00a0\u00a0\u00a0ports:\n\u00a0\u00a0\u00a0\u00a0\u00a0- &quot;5003:80&quot;\n\u00a0\u00a0\u00a0depends_on:\n\u00a0\u00a0\u00a0\u00a0\u00a0- identityserver\n\u00a0\u00a0\n\u00a0identityserver:\n\u00a0\u00a0\u00a0build: .\/identityserver\n\u00a0\u00a0\u00a0...\n\u00a0\u00a0\n\u00a0mongodb:\n\u00a0\u00a0\u00a0image: mongo:latest\n\u00a0\u00a0\u00a0...\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Notate che l\u2019indirizzo dell\u2019authority non \u00e8 pi\u00f9&nbsp;<strong><a href=\"http:\/\/localhost:5000\" rel=\"nofollow\">http:\/\/localhost:5000<\/a><\/strong>&nbsp;ma lo impostiamo su&nbsp;<strong><a href=\"http:\/\/identityserver\" rel=\"nofollow\">http:\/\/identityserver<\/a><\/strong>, utilizzando quindi il nome del servizio per risolvere l\u2019ip del container di identityserver nella rete di default creata da Docker per noi. Lanciamo il comando&nbsp;<strong>docker-compose up<\/strong>, che impiegher\u00e0 un po\u2019 di tempo in pi\u00f9 per creare le immagini dei microservizi, e testiamo le invocazioni:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"754\" data-attachment-id=\"26689\" data-permalink=\"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/attachment\/image06-2-2\/\" data-orig-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image06-2.png?fit=1288%2C949&amp;ssl=1\" data-orig-size=\"1288,949\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"image06-2\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image06-2.png?fit=1024%2C754&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/image06-2.png?resize=1024%2C754&#038;ssl=1\" alt=\"\" class=\"wp-image-26689\" srcset=\"https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image06-2-980x722.png 980w, https:\/\/blexin.com\/wp-content\/uploads\/2020\/12\/image06-2-480x354.png 480w\" sizes=\"auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Come potete notare, riceviamo un errore 401 perch\u00e8 il nostro token non risulta valido a causa del valore di&nbsp;<em>issuer<\/em>. La documentazione ufficiale dello&nbsp;<a href=\"https:\/\/tools.ietf.org\/html\/rfc7523\" target=\"_blank\" rel=\"noreferrer noopener\">standard JWT&nbsp;<\/a>ci dice:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>\u201cThe JWT MUST contain an &#8220;iss&#8221; (issuer) claim that contains a unique identifier for the entity that issued the JWT. In the absence of an application profile specifying otherwise,compliant applications MUST compare issuer values using the Simple String Comparison method defined in Section 6.2.1 of RFC39862\u201d<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In localhost tutto funzionava perch\u00e9 IdentityServer genera per noi questo valore, come chiaramente espresso dalla&nbsp;<a href=\"http:\/\/docs.identityserver.io\/en\/3.1.0\/reference\/options.html\" target=\"_blank\" rel=\"noreferrer noopener\">documentazione ufficale<\/a>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>\u201cIssuerUri: Set the issuer name that will appear in the discovery document and the issued JWT tokens. It is recommended to not set this property, which infers the issuer name from the host name that is used by the clients.\u201d<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quindi, alla generazione del token richiesta dal nostro cliente, viene utilizzato come issuer&nbsp;<strong><a href=\"http:\/\/localhost:5000\" rel=\"nofollow\">http:\/\/localhost:5000<\/a><\/strong>, mentre il nostro microservizio contatta IdentityServer per la validazione del token utilizzando l\u2019authority&nbsp;<strong><a href=\"http:\/\/identityserver\" rel=\"nofollow\">http:\/\/identityserver<\/a><\/strong>&nbsp;che abbiamo configurato nello script docker-compose. In produzione non avremmo nessun problema, dato che questi coinciderebbero, ma in questo caso ibrido invece dobbiamo forzare la mano di IdentityServer, utilizzando un&nbsp;<strong>IssuerUri<\/strong>&nbsp;fissato:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nvar builder = services.AddIdentityServer(options =&gt;\n{\noptions.IssuerUri = Configuration.GetValue&lt;string&gt;(&quot;ISSUER_URI&quot;);\n...\n})\n.AddMongoRepository(\nConfiguration.GetValue&lt;string&gt;(&quot;MONGO_CONNECTION&quot;),\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Configuration.GetValue&lt;string&gt;(&quot;MONGO_DATABASE_NAME&quot;))\n.AddClients()\n.AddIdentityApiResources()\n.AddPersistedGrants();\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusioni<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Con questa modifica tutto torna a funzionare correttamente! Potete verificare voi stessi scaricando ed eseguendo i sorgenti che trovate qui:&nbsp;<a href=\"https:\/\/github.com\/apomic80\/angular-microservices-identityserver\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/apomic80\/angular-microservices-identityserver<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Se volete approfondire Docker e Docker Compose, potete guardare le registrazioni delle dirette del nostro Antonio, che ha trattato tematiche relative a DevOps sul suo canale Twitch:\u00a0<a href=\"https:\/\/www.twitch.tv\/turibbio\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/www.twitch.tv\/turibbio<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Happy Coding!<\/em><\/p>\n\n\n\n\n","protected":false},"excerpt":{"rendered":"<p>Vediamo insieme come gestire l\u2019autenticazione in una architettura a microservizi con ASP.NET Core, Angular, IdentityServer, MongoDB e Docker<\/p>\n","protected":false},"author":196716248,"featured_media":26669,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"off","_et_pb_old_content":"","_et_gb_content_width":"","_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","_crdt_document":"","inline_featured_image":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_wpas_customize_per_network":false,"jetpack_post_was_ever_published":false},"categories":[688637374],"tags":[688637387,688637414,688637382,688637545,688637426,688637425,688637424],"class_list":["post-26667","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-angular","tag-asp-net-core","tag-c","tag-docker","tag-identityserver","tag-microservices","tag-mongdb"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Angular, Microservizi e Autenticazione con IdentityServer, MongoDB e Docker - Blexin<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Angular, Microservizi e Autenticazione con IdentityServer, MongoDB e Docker - Blexin\" \/>\n<meta property=\"og:description\" content=\"Vediamo insieme come gestire l\u2019autenticazione in una architettura a microservizi con ASP.NET Core, Angular, IdentityServer, MongoDB e Docker\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/\" \/>\n<meta property=\"og:site_name\" content=\"Blexin\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-19T22:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-06-09T10:13:26+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i1.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png?fit=1024%2C608\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"608\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Michele Aponte\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Michele Aponte\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\\\/\"},\"author\":{\"name\":\"Michele Aponte\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/cdc5540c3b6edcacd8d760669e797005\"},\"headline\":\"Angular, Microservizi e Autenticazione con IdentityServer, MongoDB e Docker\",\"datePublished\":\"2020-05-19T22:00:00+00:00\",\"dateModified\":\"2021-06-09T10:13:26+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\\\/\"},\"wordCount\":1626,\"image\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png?fit=1024%2C608&ssl=1\",\"keywords\":[\"Angular\",\"Asp.net core\",\"C#\",\"Docker\",\"Identityserver\",\"Microservices\",\"MongDB\"],\"articleSection\":[\"Blog\"],\"inLanguage\":\"it-IT\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\\\/\",\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\\\/\",\"name\":\"Angular, Microservizi e Autenticazione con IdentityServer, MongoDB e Docker - Blexin\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png?fit=1024%2C608&ssl=1\",\"datePublished\":\"2020-05-19T22:00:00+00:00\",\"dateModified\":\"2021-06-09T10:13:26+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/cdc5540c3b6edcacd8d760669e797005\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\\\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png?fit=1024%2C608&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/blexin.com\\\/wp-content\\\/uploads\\\/2020\\\/12\\\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png?fit=1024%2C608&ssl=1\",\"width\":1024,\"height\":608},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/blog\\\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/blexin.com\\\/it\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Angular, Microservizi e Autenticazione con IdentityServer, MongoDB e Docker\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#website\",\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/\",\"name\":\"Blexin\",\"description\":\"Con noi \u00e8 semplice\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/blexin.com\\\/it\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"it-IT\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/blexin.com\\\/it\\\/#\\\/schema\\\/person\\\/cdc5540c3b6edcacd8d760669e797005\",\"name\":\"Michele Aponte\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/32138aff568f2063b34d27a23cef27e09f3159bfcadea5ea05599c499cf4342f?s=96&d=identicon&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/32138aff568f2063b34d27a23cef27e09f3159bfcadea5ea05599c499cf4342f?s=96&d=identicon&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/32138aff568f2063b34d27a23cef27e09f3159bfcadea5ea05599c499cf4342f?s=96&d=identicon&r=g\",\"caption\":\"Michele Aponte\"},\"url\":\"https:\\\/\\\/blexin.com\\\/it\\\/author\\\/michele-aponteblexin-com\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Angular, Microservizi e Autenticazione con IdentityServer, MongoDB e Docker - Blexin","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/","og_locale":"it_IT","og_type":"article","og_title":"Angular, Microservizi e Autenticazione con IdentityServer, MongoDB e Docker - Blexin","og_description":"Vediamo insieme come gestire l\u2019autenticazione in una architettura a microservizi con ASP.NET Core, Angular, IdentityServer, MongoDB e Docker","og_url":"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/","og_site_name":"Blexin","article_published_time":"2020-05-19T22:00:00+00:00","article_modified_time":"2021-06-09T10:13:26+00:00","og_image":[{"width":1024,"height":608,"url":"https:\/\/i1.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png?fit=1024%2C608","type":"image\/png"}],"author":"Michele Aponte","twitter_card":"summary_large_image","twitter_misc":{"Scritto da":"Michele Aponte","Tempo di lettura stimato":"11 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/#article","isPartOf":{"@id":"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/"},"author":{"name":"Michele Aponte","@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/cdc5540c3b6edcacd8d760669e797005"},"headline":"Angular, Microservizi e Autenticazione con IdentityServer, MongoDB e Docker","datePublished":"2020-05-19T22:00:00+00:00","dateModified":"2021-06-09T10:13:26+00:00","mainEntityOfPage":{"@id":"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/"},"wordCount":1626,"image":{"@id":"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png?fit=1024%2C608&ssl=1","keywords":["Angular","Asp.net core","C#","Docker","Identityserver","Microservices","MongDB"],"articleSection":["Blog"],"inLanguage":"it-IT"},{"@type":"WebPage","@id":"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/","url":"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/","name":"Angular, Microservizi e Autenticazione con IdentityServer, MongoDB e Docker - Blexin","isPartOf":{"@id":"https:\/\/blexin.com\/it\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/#primaryimage"},"image":{"@id":"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png?fit=1024%2C608&ssl=1","datePublished":"2020-05-19T22:00:00+00:00","dateModified":"2021-06-09T10:13:26+00:00","author":{"@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/cdc5540c3b6edcacd8d760669e797005"},"breadcrumb":{"@id":"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/"]}]},{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/#primaryimage","url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png?fit=1024%2C608&ssl=1","contentUrl":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png?fit=1024%2C608&ssl=1","width":1024,"height":608},{"@type":"BreadcrumbList","@id":"https:\/\/blexin.com\/it\/blog\/angular-microservizi-e-autenticazione-con-identityserver-mongodb-e-docker\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blexin.com\/it\/"},{"@type":"ListItem","position":2,"name":"Angular, Microservizi e Autenticazione con IdentityServer, MongoDB e Docker"}]},{"@type":"WebSite","@id":"https:\/\/blexin.com\/it\/#website","url":"https:\/\/blexin.com\/it\/","name":"Blexin","description":"Con noi \u00e8 semplice","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blexin.com\/it\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"it-IT"},{"@type":"Person","@id":"https:\/\/blexin.com\/it\/#\/schema\/person\/cdc5540c3b6edcacd8d760669e797005","name":"Michele Aponte","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/secure.gravatar.com\/avatar\/32138aff568f2063b34d27a23cef27e09f3159bfcadea5ea05599c499cf4342f?s=96&d=identicon&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/32138aff568f2063b34d27a23cef27e09f3159bfcadea5ea05599c499cf4342f?s=96&d=identicon&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/32138aff568f2063b34d27a23cef27e09f3159bfcadea5ea05599c499cf4342f?s=96&d=identicon&r=g","caption":"Michele Aponte"},"url":"https:\/\/blexin.com\/it\/author\/michele-aponteblexin-com\/"}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/blexin.com\/wp-content\/uploads\/2020\/12\/5ea7a0a4-b8a8-442f-9cdf-084c1cec81d0.png?fit=1024%2C608&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/pcyUBx-6W7","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/26667","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/users\/196716248"}],"replies":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/comments?post=26667"}],"version-history":[{"count":14,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/26667\/revisions"}],"predecessor-version":[{"id":33046,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/posts\/26667\/revisions\/33046"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/media\/26669"}],"wp:attachment":[{"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/media?parent=26667"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/categories?post=26667"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blexin.com\/it\/wp-json\/wp\/v2\/tags?post=26667"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}