2021-01-13 11:30:30 +08:00
<!DOCTYPE html>
<!-- [if IE]><![endif] -->
< html >
< 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 " >
< meta name = "generator" content = "docfx 2.56.6.0" >
2021-01-13 11:49:03 +08:00
< link rel = "shortcut icon" href = "../images/favicon.ico" >
2021-01-13 11:30:30 +08:00
< link rel = "stylesheet" href = "../styles/docfx.vendor.css" >
< link rel = "stylesheet" href = "../styles/docfx.css" >
< link rel = "stylesheet" href = "../styles/main.css" >
< link href = "https://fonts.googleapis.com/css?family=Roboto" rel = "stylesheet" >
< meta property = "docfx:navrel" content = "../toc.html" >
< meta property = "docfx:tocrel" content = "toc.html" >
< / head > < body data-spy = "scroll" data-target = "#affix" data-offset = "120" >
< div id = "wrapper" >
< header >
< nav id = "autocollapse" class = "navbar navbar-inverse ng-scope" role = "navigation" >
< div class = "container" >
< div class = "navbar-header" >
< button type = "button" class = "navbar-toggle" data-toggle = "collapse" data-target = "#navbar" >
< span class = "sr-only" > Toggle navigation< / span >
< span class = "icon-bar" > < / span >
< span class = "icon-bar" > < / span >
< span class = "icon-bar" > < / span >
< / button >
2021-01-13 12:03:45 +08:00
< a class = "navbar-brand" href = "../index.html" >
< img id = "logo" class = "svg" src = "../images/logo.png" alt = "" >
< / a > < / div >
2021-01-13 11:30:30 +08:00
< div class = "collapse navbar-collapse" id = "navbar" >
< form class = "navbar-form navbar-right" role = "search" id = "search" >
< div class = "form-group" >
< input type = "text" class = "form-control" id = "search-query" placeholder = "Search" autocomplete = "off" >
< / div >
< / form >
< / div >
< / div >
< / nav >
< div class = "subnav navbar navbar-default" >
< div class = "container hide-when-search" id = "breadcrumb" >
< ul class = "breadcrumb" >
< li > < / li >
< / ul >
< / div >
< / div >
< / header >
< div role = "main" class = "container body-content hide-when-search" >
< div class = "sidenav hide-when-search" >
< a class = "btn toc-toggle collapse" data-toggle = "collapse" href = "#sidetoggle" aria-expanded = "false" aria-controls = "sidetoggle" > Show / Hide Table of Contents< / a >
< div class = "sidetoggle collapse" id = "sidetoggle" >
< div id = "sidetoc" > < / div >
< / div >
< / div >
< div class = "article row grid-right" >
< div class = "col-md-10" >
< article class = "content wrap" id = "_content" data-uid = "" >
< 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 >
< 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 >
2021-01-13 12:49:17 +08:00
< li > < p > < strong > Install the < a href = "https://www.microsoft.com/net/download" > .NET Core 2.1.x, 3.1.x or .NET 5.0.x tooling< / a > < / strong > .< / p >
2021-01-13 11:30:30 +08:00
< / li >
2021-01-13 12:49:17 +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,
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 >
< li > < p > < strong > Update your < code > .csproj< / code > file< / strong > to reference the < code > OpenIddict< / code > packages:< / p >
2021-01-13 12:49:17 +08:00
< pre > < code class = "lang-xml" > < PackageReference Include=" OpenIddict.AspNetCore" Version=" 3.0.0" />
< PackageReference Include=" OpenIddict.EntityFrameworkCore" Version=" 3.0.0" />
2021-01-13 11:30:30 +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 > .
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 =>
{
// Configure the context 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.
// Note: use the generic overload if you need
// to replace the default OpenIddict entities.
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.
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()
.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()
.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
}
< / 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();
});
app.UseWelcomePage();
2021-01-13 11:30:30 +08:00
}
< / code > < / pre > < / li >
< 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 =>
{
// Configure the context 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.
// Note: use the generic overload if you need
// to replace the default OpenIddict entities.
options.UseOpenIddict();
});
< / code > < / pre > < / li >
< / ul >
2021-01-13 12:53:51 +08:00
< p > -> [!WARNING]< / p >
2021-01-13 12:49:17 +08:00
< blockquote > < p > Important: if you change the default entity primary key (e.g. to < code > int< / code > or < code > Guid< / code > instead of < code > string< / code > ), make sure you use the < code > options.ReplaceDefaultEntities< TKey> ()< / code >
core extension accepting a < code > TKey< / code > generic argument and use the generic < code > options.UseOpenIddict< TKey> ()< / code > overload to configure Entity Framework Core to use the specified key type:< / p >
2021-01-13 11:30:30 +08:00
< pre > < code class = "lang-csharp" > services.AddOpenIddict()
.AddCore(options =>
{
// Configure OpenIddict to use the default entities with a custom key type.
options.UseEntityFrameworkCore()
.UseDbContext< ApplicationDbContext> ()
.ReplaceDefaultEntities< Guid> ();
});
services.AddDbContext< ApplicationDbContext> (options =>
{
// Configure the context to use Microsoft SQL Server.
options.UseSqlServer(configuration[" Data:DefaultConnection:ConnectionString" ]);
options.UseOpenIddict< Guid> ();
});
< / code > < / pre > < / blockquote >
< ul >
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.
Here' s an example for the client credentials grant:< / p >
< pre > < code class = "lang-csharp" > public class AuthorizationController : Controller
2021-01-13 11:30:30 +08:00
{
2021-01-13 12:53:51 +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 12:53:51 +08:00
throw new NotImplementedException(" The specified grant type is not implemented." );
}
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:
// if client_id or client_secret are invalid, this action won' t be invoked.
2021-01-13 11:30:30 +08:00
2021-01-13 12:53:51 +08:00
var application = await _applicationManager.FindByClientIdAsync(request.ClientId);
if (application == null)
{
throw new InvalidOperationException(" The application details cannot be found in the database." );
}
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.
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.
identity.AddClaim(Claims.Subject, await _applicationManager.GetClientIdAsync(application),
Destinations.AccessToken, Destinations.IdentityToken);
2021-01-13 12:49:17 +08:00
2021-01-13 12:53:51 +08:00
identity.AddClaim(Claims.Name, await _applicationManager.GetDisplayNameAsync(application),
Destinations.AccessToken, Destinations.IdentityToken);
2021-01-13 12:49:17 +08:00
2021-01-13 12:53:51 +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
}
< / 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();
2021-01-13 12:53:51 +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
}
< / code > < / pre > < / li >
< / ul >
< / article >
< / div >
< div class = "hidden-sm col-md-2" role = "complementary" >
< div class = "sideaffix" >
< div class = "contribution" >
< ul class = "nav" >
< li >
< a href = "https://github.com/openiddict/openiddict-documentation/blob/dev/guide/getting-started.md/#L1" class = "contribution-link" > Improve this Doc< / a >
< / li >
< / ul >
< / div >
< nav class = "bs-docs-sidebar hidden-print hidden-xs hidden-sm affix" id = "affix" >
< h5 > In This Article< / h5 >
< div > < / div >
< / nav >
< / div >
< / div >
< / div >
< / div >
< footer >
< div class = "grad-bottom" > < / div >
< div class = "footer" >
< div class = "container" >
< span class = "pull-right" >
< a href = "#top" > Back to top< / a >
< / span >
< span > Generated by < strong > DocFX< / strong > < / span >
< / div >
< / div >
< / footer >
< / div >
< script type = "text/javascript" src = "../styles/docfx.vendor.js" > < / script >
< script type = "text/javascript" src = "../styles/docfx.js" > < / script >
< script type = "text/javascript" src = "../styles/main.js" > < / script >
< / body >
< / html >