2022-01-08 01:11:48 +08:00
<!DOCTYPE html>
<!-- [if IE]><![endif] -->
< html >
2023-05-03 03:58:39 +08:00
2021-01-13 11:30:30 +08:00
< head >
< meta charset = "utf-8" >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1" >
< title > Getting started < / title >
< meta name = "viewport" content = "width=device-width" >
< meta name = "title" content = "Getting started " >
2023-05-03 03:58:39 +08:00
< meta name = "generator" content = "docfx 2.56.7.0" >
2021-01-13 11:49:03 +08:00
< link rel = "shortcut icon" href = "../images/favicon.ico" >
2022-01-08 01:11:48 +08:00
< link href = "https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel = "stylesheet" >
< link rel = "stylesheet" href = "//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/night-owl.min.css" >
< link rel = "stylesheet" href = "../styles/colors.css" >
< link rel = "stylesheet" href = "../styles/discord.css" >
2021-01-13 11:30:30 +08:00
< link rel = "stylesheet" href = "../styles/main.css" >
< meta property = "docfx:navrel" content = "../toc.html" >
< meta property = "docfx:tocrel" content = "toc.html" >
2023-05-03 03:58:39 +08:00
2022-01-08 01:11:48 +08:00
< / head >
< body >
< div class = "top-navbar" >
< a href = "javascript:void(0);" class = "burger-icon" onclick = "toggleMenu()" >
< svg name = "Hamburger" style = "vertical-align: middle;" width = "24" height = "24" viewbox = "0 0 24 24" > < path fill = "currentColor" fill-rule = "evenodd" clip-rule = "evenodd" d = "M20 6H4V9H20V6ZM4 10.999H20V13.999H4V10.999ZM4 15.999H20V18.999H4V15.999Z" > < / path > < / svg >
< / a >
2023-05-03 03:58:39 +08:00
2022-01-08 01:11:48 +08:00
< a class = "brand" href = "../index.html" >
2022-01-08 01:58:08 +08:00
< img src = "../images/logo.png" alt = "OpenIddict" class = "logomark" >
< span class = "brand-title" > OpenIddict< / span >
2022-01-08 01:11:48 +08:00
< / a >
< / div >
< div class = "body-content" >
< div id = "blackout" class = "blackout" onclick = "toggleMenu()" > < / div >
< nav id = "sidebar" role = "navigation" >
< div class = "sidebar" >
2023-05-03 03:58:39 +08:00
2022-01-08 01:11:48 +08:00
< div >
2023-05-03 03:58:39 +08:00
2022-01-08 01:11:48 +08:00
< a class = "brand" href = "../index.html" >
2022-01-08 01:58:08 +08:00
< img src = "../images/logo.png" alt = "OpenIddict" class = "logomark" >
< span class = "brand-title" > OpenIddict< / span >
2022-01-08 01:11:48 +08:00
< / a >
< div id = "navbar" >
2023-05-03 03:58:39 +08:00
2022-01-08 01:11:48 +08:00
< / div >
2023-05-03 03:58:39 +08:00
2022-01-08 01:11:48 +08:00
< / div >
< div class = "sidebar-item-separator" > < / div >
2023-05-03 03:58:39 +08:00
2022-01-08 01:11:48 +08:00
< div id = "sidetoggle" >
< div id = "sidetoc" > < / div >
< / div >
< / div >
< div class = "footer" >
2023-05-03 03:58:39 +08:00
< span > Generated by < strong > DocFX< / strong > < / span >
2022-01-08 01:11:48 +08:00
< / div >
< / nav >
< main class = "main-panel" >
< div role = "main" class = "hide-when-search" >
2023-05-03 03:58:39 +08:00
2022-01-08 01:11:48 +08:00
< div class = "subnav navbar navbar-default" >
< div class = "container hide-when-search" id = "breadcrumb" >
< ul class = "breadcrumb" >
< li > < / li >
< / ul >
< / div >
< / div >
< article class = "content wrap" id = "_content" data-uid = "" >
2021-01-13 11:30:30 +08:00
< h1 id = "getting-started" > Getting started< / h1 >
2021-01-13 12:49:17 +08:00
< p > < strong > To implement a custom OpenID Connect server using OpenIddict, the simplest option is to clone one of the official samples< / strong > from the < a href = "https://github.com/openiddict/openiddict-samples" > openiddict-samples repository< / a > .< / p >
2023-05-03 03:58:39 +08:00
< p > If you don' t want to start from one of the recommended samples, you' ll need to:< / p >
2021-01-13 11:30:30 +08:00
< ul >
2022-01-08 01:11:48 +08:00
< li > < p > < strong > Install the < a href = "https://www.microsoft.com/net/download" > .NET Core 3.1 (or later) tooling< / a > < / strong > .< / p >
2021-01-13 11:30:30 +08:00
< / li >
2023-05-03 03:58:39 +08:00
< li > < p > < strong > Have an existing project or create a new one< / strong > : when creating a new project using Visual Studio' s default ASP.NET Core template,
2021-01-13 12:49:17 +08:00
using < strong > individual user accounts authentication< / strong > is strongly recommended as it automatically includes the default ASP.NET Core Identity UI, based on Razor Pages.< / p >
2021-01-13 11:30:30 +08:00
< / li >
2021-02-09 00:11:42 +08:00
< li > < p > < strong > Update your < code > .csproj< / code > file< / strong > to reference the latest < code > OpenIddict< / code > packages:< / p >
2023-07-14 00:48:00 +08:00
< pre > < code class = "lang-xml" > < PackageReference Include=" OpenIddict.AspNetCore" Version=" 4.6.0" />
< PackageReference Include=" OpenIddict.EntityFrameworkCore" Version=" 4.6.0" />
2023-05-03 03:58:39 +08:00
< / code > < / pre > < / li >
2021-01-13 12:49:17 +08:00
< li > < p > < strong > Configure the OpenIddict core, server and validation services< / strong > in < code > Startup.ConfigureServices< / code > .
2023-05-03 03:58:39 +08:00
Here' s an example for the client credentials grant, used in machine-to-machine scenarios:< / p >
2021-01-13 11:30:30 +08:00
< pre > < code class = "lang-csharp" > public void ConfigureServices(IServiceCollection services)
{
2021-01-13 12:49:17 +08:00
services.AddControllersWithViews();
2021-01-13 11:30:30 +08:00
services.AddDbContext< ApplicationDbContext> (options =>
{
2022-01-12 00:30:01 +08:00
// Configure Entity Framework Core to use Microsoft SQL Server.
2021-01-13 12:49:17 +08:00
options.UseSqlServer(Configuration.GetConnectionString(" DefaultConnection" ));
2021-01-13 11:30:30 +08:00
// Register the entity sets needed by OpenIddict.
2022-01-12 00:30:01 +08:00
// Note: use the generic overload if you need to replace the default OpenIddict entities.
2021-01-13 11:30:30 +08:00
options.UseOpenIddict();
});
services.AddOpenIddict()
2021-01-13 12:49:17 +08:00
// Register the OpenIddict core components.
2021-01-13 11:30:30 +08:00
.AddCore(options =>
{
2021-01-13 12:49:17 +08:00
// Configure OpenIddict to use the Entity Framework Core stores and models.
2021-01-13 12:53:51 +08:00
// Note: call ReplaceDefaultEntities() to replace the default entities.
2021-01-13 11:30:30 +08:00
options.UseEntityFrameworkCore()
2021-01-13 12:53:51 +08:00
.UseDbContext< ApplicationDbContext> ();
2021-01-13 11:30:30 +08:00
})
2021-01-13 12:49:17 +08:00
// Register the OpenIddict server components.
2021-01-13 11:30:30 +08:00
.AddServer(options =>
{
2021-01-13 12:49:17 +08:00
// Enable the token endpoint.
2022-12-24 03:47:50 +08:00
options.SetTokenEndpointUris(" connect/token" );
2021-01-13 11:30:30 +08:00
2021-01-13 12:49:17 +08:00
// Enable the client credentials flow.
options.AllowClientCredentialsFlow();
2021-01-13 11:30:30 +08:00
2021-01-13 12:49:17 +08:00
// Register the signing and encryption credentials.
options.AddDevelopmentEncryptionCertificate()
2022-01-08 01:11:48 +08:00
.AddDevelopmentSigningCertificate();
2021-01-13 11:30:30 +08:00
2021-01-13 12:53:51 +08:00
// Register the ASP.NET Core host and configure the ASP.NET Core options.
2021-01-13 12:49:17 +08:00
options.UseAspNetCore()
2022-01-08 01:11:48 +08:00
.EnableTokenEndpointPassthrough();
2021-01-13 11:30:30 +08:00
})
2021-01-13 12:49:17 +08:00
// 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< Worker> ();
2021-01-13 11:30:30 +08:00
}
2023-05-03 03:58:39 +08:00
< / code > < / pre > < / li >
2021-01-13 12:49:17 +08:00
< li > < p > < strong > Make sure the ASP.NET Core authentication middleware is correctly registered at the right place< / strong > :< / p >
2021-01-13 11:30:30 +08:00
< pre > < code class = "lang-csharp" > public void Configure(IApplicationBuilder app)
{
2021-01-13 12:49:17 +08:00
app.UseDeveloperExceptionPage();
app.UseRouting();
2021-01-13 11:30:30 +08:00
app.UseAuthentication();
2021-01-13 12:49:17 +08:00
app.UseAuthorization();
2021-01-13 11:30:30 +08:00
2021-01-13 12:49:17 +08:00
app.UseEndpoints(options =>
{
options.MapControllers();
options.MapDefaultControllerRoute();
});
2021-01-13 11:30:30 +08:00
}
2023-05-03 03:58:39 +08:00
< / code > < / pre > < / li >
2021-01-13 11:30:30 +08:00
< li > < p > < strong > Update your Entity Framework Core context registration to register the OpenIddict entities< / strong > :< / p >
< pre > < code class = "lang-csharp" > services.AddDbContext< ApplicationDbContext> (options =>
{
2022-01-12 00:30:01 +08:00
// Configure Entity Framework Core to use Microsoft SQL Server.
2021-01-13 12:49:17 +08:00
options.UseSqlServer(Configuration.GetConnectionString(" DefaultConnection" ));
2021-01-13 11:30:30 +08:00
// Register the entity sets needed by OpenIddict.
2022-01-12 00:30:01 +08:00
// Note: use the generic overload if you need to replace the default OpenIddict entities.
2021-01-13 11:30:30 +08:00
options.UseOpenIddict();
});
2023-05-03 03:58:39 +08:00
< / code > < / pre > < div class = "NOTE" > < h5 > Note< / h5 > < p > By default, the OpenIddict Entity Framework Core integration uses < code > string< / code > as the default type for primary keys.
2022-01-12 00:30:01 +08:00
To use a different type, read < a href = "../integrations/entity-framework-core.html#use-a-custom-primary-key-type" > Entity Framework Core integration : Use a custom primary key type< / a > .< / p >
< / div >
2021-01-13 13:05:04 +08:00
< / li >
2021-01-13 12:49:17 +08:00
< li > < p > < strong > Create your own authorization controller:< / strong >
Implementing a custom authorization controller is required to allow OpenIddict to create tokens based on the identities and claims you provide.
2023-05-03 03:58:39 +08:00
Here' s an example for the client credentials grant:< / p >
2021-01-13 12:49:17 +08:00
< pre > < code class = "lang-csharp" > public class AuthorizationController : Controller
2021-01-13 11:30:30 +08:00
{
2021-02-13 01:16:04 +08:00
private readonly IOpenIddictApplicationManager _applicationManager;
2021-01-13 11:30:30 +08:00
2021-01-13 12:53:51 +08:00
public AuthorizationController(IOpenIddictApplicationManager applicationManager)
2021-01-13 12:49:17 +08:00
=> _applicationManager = applicationManager;
[HttpPost(" ~/connect/token" ), Produces(" application/json" )]
public async Task< IActionResult> Exchange()
{
var request = HttpContext.GetOpenIddictServerRequest();
2021-01-13 12:53:51 +08:00
if (!request.IsClientCredentialsGrantType())
2021-01-13 11:30:30 +08:00
{
2021-01-13 13:01:54 +08:00
throw new NotImplementedException(" The specified grant is not implemented." );
2021-01-13 12:53:51 +08:00
}
2021-01-13 11:30:30 +08:00
2021-01-13 12:53:51 +08:00
// Note: the client credentials are automatically validated by OpenIddict:
2023-05-03 03:58:39 +08:00
// if client_id or client_secret are invalid, this action won' t be invoked.
2021-01-13 11:30:30 +08:00
2022-01-08 01:11:48 +08:00
var application = await _applicationManager.FindByClientIdAsync(request.ClientId) ??
2021-01-13 13:12:48 +08:00
throw new InvalidOperationException(" The application cannot be found." );
2021-01-13 11:30:30 +08:00
2021-01-13 12:53:51 +08:00
// Create a new ClaimsIdentity containing the claims that
// will be used to create an id_token, a token or a code.
2022-01-08 01:11:48 +08:00
var identity = new ClaimsIdentity(TokenValidationParameters.DefaultAuthenticationType, Claims.Name, Claims.Role);
2021-01-13 11:30:30 +08:00
2021-01-13 12:53:51 +08:00
// Use the client_id as the subject identifier.
2023-03-04 00:06:36 +08:00
identity.SetClaim(Claims.Subject, await _applicationManager.GetClientIdAsync(application));
identity.SetClaim(Claims.Name, await _applicationManager.GetDisplayNameAsync(application));
2021-01-13 12:49:17 +08:00
2023-03-04 00:06:36 +08:00
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 }
});
2021-01-13 12:49:17 +08:00
2022-01-14 01:00:07 +08:00
return SignIn(new ClaimsPrincipal(identity), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
2021-01-13 12:49:17 +08:00
}
2021-01-13 11:30:30 +08:00
}
2023-05-03 03:58:39 +08:00
< / code > < / pre > < / li >
2021-01-13 12:49:17 +08:00
< li > < p > < strong > Register your client application< / strong > (e.g from an < code > IHostedService< / code > implementation):< / p >
< pre > < code class = "lang-csharp" > public class Worker : IHostedService
2021-01-13 11:30:30 +08:00
{
2021-01-13 12:49:17 +08:00
private readonly IServiceProvider _serviceProvider;
2021-01-13 11:30:30 +08:00
2021-01-13 12:49:17 +08:00
public Worker(IServiceProvider serviceProvider)
=> _serviceProvider = serviceProvider;
2021-01-13 11:30:30 +08:00
2021-01-13 12:49:17 +08:00
public async Task StartAsync(CancellationToken cancellationToken)
2021-01-13 11:30:30 +08:00
{
2021-01-13 12:49:17 +08:00
using var scope = _serviceProvider.CreateScope();
2021-01-13 11:30:30 +08:00
2021-01-13 12:49:17 +08:00
var context = scope.ServiceProvider.GetRequiredService< ApplicationDbContext> ();
await context.Database.EnsureCreatedAsync();
2022-01-14 01:00:07 +08:00
var manager = scope.ServiceProvider.GetRequiredService< IOpenIddictApplicationManager> ();
2021-01-13 12:49:17 +08:00
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
}
});
}
2021-01-13 11:30:30 +08:00
}
2021-01-13 12:49:17 +08:00
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
2021-01-13 11:30:30 +08:00
}
2023-05-03 03:58:39 +08:00
< / code > < / pre > < p > Before running the application, make sure the database is updated with OpenIddict tables by running < code > Add-Migration< / code > and < code > Update-Database< / code > .< / p >
2021-06-29 23:49:34 +08:00
< / li >
2021-01-13 11:30:30 +08:00
< / ul >
2022-01-08 01:11:48 +08:00
< / article >
< / div >
< / main >
< / div >
2023-05-03 03:58:39 +08:00
< script src = "https://code.jquery.com/jquery-3.5.1.min.js" integrity = "sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin = "anonymous" > < / script >
< script src = "https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity = "sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin = "anonymous" > < / script >
< script src = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity = "sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin = "anonymous" > < / script >
< script src = "//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" > < / script >
< script type = "text/javascript" src = "../styles/jquery.twbsPagination.js" > < / script >
< script type = "text/javascript" src = "../styles/url.min.js" > < / script >
< script src = "https://cdn.jsdelivr.net/npm/anchor-js/anchor.min.js" > < / script >
< script type = "text/javascript" src = "../styles/docfx.js" > < / script >
< script type = "text/javascript" src = "../styles/main.js" > < / script >
2022-01-08 01:11:48 +08:00
< / body >
< / html >