I am trying to create a small ecommerce demo app using .net core API 3.1 with Identity server 4.
Config.cs (Demo.Auth Project)
public static class Config
{
public static IEnumerable<IdentityResource> Ids =>
new IdentityResource[]
{
new IdentityResources.Profile(),
};
public static IEnumerable<ApiResource> ApiResources => new[]
{
new ApiResource("Demo.Api", "Demo Api")
};
public static IEnumerable<Client> Clients => new[]
{
new Client()
{
ClientId = "mvc",
ClientName = "Demo.MvcClient",
AllowedGrantTypes = GrantTypes.ClientCredentials,
RequirePkce = true,
ClientSecrets =
{
new Secret("49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256())
},
RedirectUris = {"http://localhost:5003/signin-oidc"},
FrontChannelLogoutUri = "http://localhost:5003/signout-oidc",
PostLogoutRedirectUris = {"http://localhost:5003/signout-callback-oidc"},
AllowOfflineAccess = true,
AllowedScopes = {"profile"}
}
};
}
Startup.cs (Demo.Auth Project)
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
IConfigurationRoot config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
string identityConnectionString = config.GetSection("ConnectionStrings")
.Value;
var migratingAssembly = typeof(Startup).GetTypeInfo()
.Assembly.GetName()
.Name;
if (config.GetValue<bool>("UseInMemoryDatabase"))
{
services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
})
.AddTestUsers(TestUsers.Users)
.AddInMemoryIdentityResources(Config.Ids)
.AddInMemoryApiResources(Config.ApiResources)
.AddInMemoryClients(Config.Clients)
.AddDeveloperSigningCredential();
}
else
{
services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
})
.AddTestUsers(TestUsers.Users)
.AddDeveloperSigningCredential()
//This will store client and ApiResource
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(identityConnectionString,
sql => sql.MigrationsAssembly(migratingAssembly));
})
//This will store token, consent or code
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b => b.UseSqlServer(identityConnectionString,
sql => sql.MigrationsAssembly(migratingAssembly));
});
}
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app,
IWebHostEnvironment env)
{
// this will do the initial DB population
// InitializeDatabase(app);
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
app.UseRouting();
app.UseIdentityServer();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/",
async context => { await context.Response.WriteAsync("Hello World!"); });
});
}
}
Startup.cs (API Project)
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication("Bearer").AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ApiName = "Demo.Api";
});
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}
}
WeatherForecastController (of Demo.Api project)
[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
I test the API in postman and it is working fine. "Demo.Auth" project is generating the token and I am able to access my authorize controller successfully.
Idea here is:
MVC Client ----> Identity Server Project ---> API
MVC client wants to access the API. So I will authenticate the Mvc client on Identity server project, generate the token if he is valid user and I will then call my api.
Note: Currently I am using MVC Client but I will add one more client later on, may be Angular.
But I have a questions here.
How can I add the users to my database and authenticate the database user not the Test one.
Another thing which I am not understanding is where I should put the Login and Register functionality and how that code will look like.
I am new to identity server please excuse me.
Can anybody guide me on my above question with some code ? Thanks in advance
