# Getting started **To implement a custom OpenID Connect server using OpenIddict, the simplest option is to clone one of the official samples** from the [openiddict-samples repository](https://github.com/openiddict/openiddict-samples). If you don't want to start from one of the recommended samples, you'll need to: - **Install the [.NET Core 3.1 (or later) tooling](https://www.microsoft.com/net/download)**. - **Have an existing project or create a new one**: when creating a new project using Visual Studio's default ASP.NET Core template, using **individual user accounts authentication** is strongly recommended as it automatically includes the default ASP.NET Core Identity UI, based on Razor Pages. - **Update your `.csproj` file** to reference the latest `OpenIddict` packages: ```xml ``` - **Configure the OpenIddict core, server and validation services** in `Startup.ConfigureServices`. Here's an example for the client credentials grant, used in machine-to-machine scenarios: ```csharp public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddDbContext(options => { // Configure Entity Framework Core to use Microsoft SQL Server. options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")); // Register the entity sets needed by OpenIddict. // Note: use the generic overload if you need to replace the default OpenIddict entities. options.UseOpenIddict(); }); services.AddOpenIddict() // Register the OpenIddict core components. .AddCore(options => { // Configure OpenIddict to use the Entity Framework Core stores and models. // Note: call ReplaceDefaultEntities() to replace the default entities. options.UseEntityFrameworkCore() .UseDbContext(); }) // Register the OpenIddict server components. .AddServer(options => { // Enable the token endpoint. options.SetTokenEndpointUris("connect/token"); // Enable the client credentials flow. options.AllowClientCredentialsFlow(); // Register the signing and encryption credentials. options.AddDevelopmentEncryptionCertificate() .AddDevelopmentSigningCertificate(); // Register the ASP.NET Core host and configure the ASP.NET Core options. options.UseAspNetCore() .EnableTokenEndpointPassthrough(); }) // Register the OpenIddict validation components. .AddValidation(options => { // Import the configuration from the local OpenIddict server instance. options.UseLocalServer(); // Register the ASP.NET Core host. options.UseAspNetCore(); }); // Register the worker responsible of seeding the database with the sample clients. // Note: in a real world application, this step should be part of a setup script. services.AddHostedService(); } ``` - **Make sure the ASP.NET Core authentication middleware is correctly registered at the right place**: ```csharp public void Configure(IApplicationBuilder app) { app.UseDeveloperExceptionPage(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(options => { options.MapControllers(); options.MapDefaultControllerRoute(); }); } ``` - **Update your Entity Framework Core context registration to register the OpenIddict entities**: ```csharp services.AddDbContext(options => { // Configure Entity Framework Core to use Microsoft SQL Server. options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")); // Register the entity sets needed by OpenIddict. // Note: use the generic overload if you need to replace the default OpenIddict entities. options.UseOpenIddict(); }); ``` > [!NOTE] > By default, the OpenIddict Entity Framework Core integration uses `string` as the default type for primary keys. > To use a different type, read [Entity Framework Core integration : Use a custom primary key type](~/integrations/entity-framework-core.md#use-a-custom-primary-key-type). - **Create your own authorization controller:** Implementing a custom authorization controller is required to allow OpenIddict to create tokens based on the identities and claims you provide. Here's an example for the client credentials grant: ```csharp public class AuthorizationController : Controller { private readonly IOpenIddictApplicationManager _applicationManager; public AuthorizationController(IOpenIddictApplicationManager applicationManager) => _applicationManager = applicationManager; [HttpPost("~/connect/token"), Produces("application/json")] public async Task Exchange() { var request = HttpContext.GetOpenIddictServerRequest(); if (!request.IsClientCredentialsGrantType()) { throw new NotImplementedException("The specified grant is not implemented."); } // Note: the client credentials are automatically validated by OpenIddict: // if client_id or client_secret are invalid, this action won't be invoked. var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ?? throw new InvalidOperationException("The application cannot be found."); // Create a new ClaimsIdentity containing the claims that // will be used to create an id_token, a token or a code. var identity = new ClaimsIdentity(TokenValidationParameters.DefaultAuthenticationType, Claims.Name, Claims.Role); // Use the client_id as the subject identifier. identity.SetClaim(Claims.Subject, await _applicationManager.GetClientIdAsync(application)); identity.SetClaim(Claims.Name, await _applicationManager.GetDisplayNameAsync(application)); identity.SetDestinations(static claim => claim.Type switch { // Allow the "name" claim to be stored in both the access and identity tokens // when the "profile" scope was granted (by calling principal.SetScopes(...)). Claims.Name when claim.Subject.HasScope(Scopes.Profile) => new[] { Destinations.AccessToken, Destinations.IdentityToken }, // Otherwise, only store the claim in the access tokens. _ => new[] { Destinations.AccessToken } }); return SignIn(new ClaimsPrincipal(identity), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); } } ``` - **Register your client application** (e.g from an `IHostedService` implementation): ```csharp public class Worker : IHostedService { private readonly IServiceProvider _serviceProvider; public Worker(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; public async Task StartAsync(CancellationToken cancellationToken) { using var scope = _serviceProvider.CreateScope(); var context = scope.ServiceProvider.GetRequiredService(); await context.Database.EnsureCreatedAsync(); var manager = scope.ServiceProvider.GetRequiredService(); if (await manager.FindByClientIdAsync("console") is null) { await manager.CreateAsync(new OpenIddictApplicationDescriptor { ClientId = "console", ClientSecret = "388D45FA-B36B-4988-BA59-B187D329C207", DisplayName = "My client application", Permissions = { Permissions.Endpoints.Token, Permissions.GrantTypes.ClientCredentials } }); } } public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; } ``` Before running the application, make sure the database is updated with OpenIddict tables by running `Add-Migration` and `Update-Database`.