Tweak the documentation routes and revamp the menus

This commit is contained in:
Kévin Chalet
2018-09-13 13:48:01 +02:00
parent aedcc6a70a
commit 87725369a5
13 changed files with 50 additions and 23 deletions

187
guide/getting-started.md Normal file
View File

@@ -0,0 +1,187 @@
# Getting started
To use OpenIddict, you need to:
- **Install the latest [.NET Core 2.x tooling](https://www.microsoft.com/net/download) and update your packages to reference the ASP.NET Core 2.x packages**.
- **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. When updating an existing project, you must provide your own `AccountController` to handle the registration process and the authentication flow.
- **Update your `.csproj` file** to reference the `OpenIddict` packages:
```xml
<PackageReference Include="OpenIddict" Version="2.0.0-*" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="2.0.0-*" />
```
- **Configure the OpenIddict services** in `Startup.ConfigureServices`:
```csharp
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<ApplicationDbContext>(options =>
{
// Configure the context to use Microsoft SQL Server.
options.UseSqlServer(configuration["Data:DefaultConnection:ConnectionString"]);
// Register the entity sets needed by OpenIddict.
// Note: use the generic overload if you need
// to replace the default OpenIddict entities.
options.UseOpenIddict();
});
// Register the Identity services.
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Register the OpenIddict services.
services.AddOpenIddict()
.AddCore(options =>
{
// Configure OpenIddict to use the Entity Framework Core stores and entities.
options.UseEntityFrameworkCore()
.UseDbContext<ApplicationDbContext>();
})
.AddServer(options =>
{
// Register the ASP.NET Core MVC binder used by OpenIddict.
// Note: if you don't call this method, you won't be able to
// bind OpenIdConnectRequest or OpenIdConnectResponse parameters.
options.UseMvc();
// Enable the token endpoint (required to use the password flow).
options.EnableTokenEndpoint("/connect/token");
// Allow client applications to use the grant_type=password flow.
options.AllowPasswordFlow();
// During development, you can disable the HTTPS requirement.
options.DisableHttpsRequirement();
// Accept token requests that don't specify a client_id.
options.AcceptAnonymousClients();
})
.AddValidation();
}
```
- **Make sure the authentication middleware is registered before all the other middleware, including `app.UseMvc()`**:
```csharp
public void Configure(IApplicationBuilder app)
{
app.UseAuthentication();
app.UseMvc();
}
```
- **Update your Entity Framework Core context registration to register the OpenIddict entities**:
```csharp
services.AddDbContext<ApplicationDbContext>(options =>
{
// Configure the context to use Microsoft SQL Server.
options.UseSqlServer(configuration["Data:DefaultConnection:ConnectionString"]);
// Register the entity sets needed by OpenIddict.
// Note: use the generic overload if you need
// to replace the default OpenIddict entities.
options.UseOpenIddict();
});
```
> **Note:** if you change the default entity primary key (e.g. to `int` or `Guid` instead of `string`), make sure you use the `options.ReplaceDefaultEntities<TKey>()` core extension accepting a `TKey` generic argument and use the generic `options.UseOpenIddict<TKey>()` overload to configure Entity Framework Core to use the specified key type:
>
> ```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>();
> });
>```
- **Create your own authorization controller**:
To **support the password or the client credentials flow, you must provide your own token endpoint action**.
To enable authorization code/implicit flows support, you'll similarly have to create your own authorization endpoint action and your own views/view models.
The **Mvc.Server sample comes with an [`AuthorizationController` that supports both the password flow and the authorization code flow and that you can easily reuse in your application](https://github.com/openiddict/openiddict-core/blob/dev/samples/Mvc.Server/Controllers/AuthorizationController.cs)**.
- **Enable the corresponding flows in the OpenIddict options**:
```csharp
public void ConfigureServices(IServiceCollection services)
{
// Register the OpenIddict services.
services.AddOpenIddict()
.AddCore(options =>
{
// Configure OpenIddict to use the Entity Framework Core stores and entities.
options.UseEntityFrameworkCore()
.UseDbContext<ApplicationDbContext>();
})
.AddServer(options =>
{
// Register the ASP.NET Core MVC binder used by OpenIddict.
// Note: if you don't call this method, you won't be able to
// bind OpenIdConnectRequest or OpenIdConnectResponse parameters.
options.UseMvc();
// Enable the authorization/token endpoints (required to use the code flow).
options.EnableAuthorizationEndpoint("/connect/authorize")
.EnableTokenEndpoint("/connect/token");
// Allow client applications to use the code flow.
options.AllowAuthorizationCodeFlow();
// During development, you can disable the HTTPS requirement.
options.DisableHttpsRequirement();
})
.AddValidation();
}
```
- **Register your client application**:
```csharp
// Create a new service scope to ensure the database context
// is correctly disposed when this methods returns.
using (var scope = app.ApplicationServices.CreateScope())
{
var provider = scope.ServiceProvider;
var context = provider.GetRequiredService<ApplicationDbContext>();
await context.Database.EnsureCreatedAsync();
var manager = provider.GetRequiredService<IOpenIddictApplicationManager>();
if (await manager.FindByClientIdAsync("[client identifier]") == null)
{
var descriptor = new OpenIddictApplicationDescriptor
{
ClientId = "[client identifier]",
ClientSecret = "[client secret]",
RedirectUris = { new Uri("[redirect uri]") }
};
await manager.CreateAsync(descriptor);
}
}
```

22
guide/index.md Normal file
View File

@@ -0,0 +1,22 @@
# Introduction
## What's OpenIddict?
OpenIddict aims at providing a **simple and easy-to-use solution** to implement an **OpenID Connect server in any ASP.NET Core 1.x or 2.x application**.
OpenIddict is based on
**[AspNet.Security.OpenIdConnect.Server (codenamed ASOS)](https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server)** to control the OpenID Connect authentication flow and can be used with any membership stack, **including [ASP.NET Core Identity](https://github.com/aspnet/Identity)**.
OpenIddict fully supports the **[code/implicit/hybrid flows](http://openid.net/specs/openid-connect-core-1_0.html)** and the **[client credentials/resource owner password grants](https://tools.ietf.org/html/rfc6749)**. You can also create your own custom grant types.
Note: OpenIddict natively supports **[Entity Framework Core](https://github.com/aspnet/EntityFramework)** and **[Entity Framework 6](https://github.com/aspnet/EntityFramework6)** out-of-the-box, but you can also provide your own stores.
> Note: **the OpenIddict 2.x packages are only compatible with ASP.NET Core 2.x**.
> If your application targets ASP.NET Core 1.x, use the OpenIddict 1.x packages.
## Why an OpenID Connect server?
Adding an OpenID Connect server to your application **allows you to support token authentication**.
It also allows you to manage all your users using local password or an external identity provider
(e.g. Facebook or Google) for all your applications in one central place,
with the power to control who can access your API and the information that is exposed to each client.

450
guide/migration.md Normal file
View File

@@ -0,0 +1,450 @@
# Migrate to OpenIddict RC3
## What's new in OpenIddict RC3?
The announcement listing the changes introduced in this milestone can be found [here](https://kevinchalet.com/2018/06/20/openiddict-rc3-is-out/).
## Update your packages references
For that, simply update your `.csproj` file to point to the newest OpenIddict packages:
### ASP.NET Core 1.x
```xml
<ItemGroup>
<PackageReference Include="OpenIddict" Version="1.0.0-rc3-final" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="1.0.0-rc3-final" />
</ItemGroup>
```
### ASP.NET Core 2.x
```xml
<ItemGroup>
<PackageReference Include="OpenIddict" Version="2.0.0-rc3-final" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="2.0.0-rc3-final" />
</ItemGroup>
```
> [!TIP]
> Note: if you have an explicit reference to `AspNet.Security.OAuth.Validation` or `OpenIddict.Mvc`,
> you can safely remove these dependencies: they are now transitively referenced by the `OpenIddict` metapackage.
> [!IMPORTANT]
> Note: if your application references `OpenIddict.Models` or `OpenIddict.Stores`, you MUST remove them as these packages are no longer used in RC3.
## Use the new OpenIddict services registration APIs
To offer a better user experience, the registrations APIs exposed by OpenIddict have been reworked. Updating your code should be quite straightforward:
```csharp
// In OpenIddict RC2, all the options used to be grouped.
services.AddOpenIddict(options =>
{
options.AddEntityFrameworkCoreStores<ApplicationDbContext>();
options.AddMvcBinders();
options.EnableAuthorizationEndpoint("/connect/authorize")
.EnableLogoutEndpoint("/connect/logout")
.EnableTokenEndpoint("/connect/token")
.EnableUserinfoEndpoint("/api/userinfo");
options.AllowAuthorizationCodeFlow()
.AllowPasswordFlow()
.AllowRefreshTokenFlow();
options.RegisterScopes(OpenIdConnectConstants.Scopes.Email,
OpenIdConnectConstants.Scopes.Profile,
OpenIddictConstants.Scopes.Roles);
options.RequireClientIdentification();
options.EnableRequestCaching();
options.EnableScopeValidation();
options.DisableHttpsRequirement();
});
```
```csharp
// In OpenIddict RC3, the options are now split into 3 categories:
// the core services, the server services and the validation services.
services.AddOpenIddict()
.AddCore(options =>
{
// AddEntityFrameworkCoreStores() is now UseEntityFrameworkCore().
options.UseEntityFrameworkCore()
.UseDbContext<ApplicationDbContext>();
})
.AddServer(options =>
{
// AddMvcBinders() is now UseMvc().
options.UseMvc();
options.EnableAuthorizationEndpoint("/connect/authorize")
.EnableLogoutEndpoint("/connect/logout")
.EnableTokenEndpoint("/connect/token")
.EnableUserinfoEndpoint("/api/userinfo");
options.AllowAuthorizationCodeFlow()
.AllowPasswordFlow()
.AllowRefreshTokenFlow();
options.RegisterScopes(OpenIdConnectConstants.Scopes.Email,
OpenIdConnectConstants.Scopes.Profile,
OpenIddictConstants.Scopes.Roles);
// This API was removed as client identification is now
// required by default. You can remove or comment this line.
//
// options.RequireClientIdentification();
options.EnableRequestCaching();
// This API was removed as scope validation is now enforced
// by default. You can safely remove or comment this line.
//
// options.EnableScopeValidation();
options.DisableHttpsRequirement();
});
```
## Move to the OpenIddict validation handler (optional)
While not required, moving to the new validation handler is recommended:
```csharp
// Replace...
services.AddAuthentication()
.AddOAuthValidation();
// ... by:
services.AddOpenIddict()
.AddValidation();
```
> [!TIP]
> Note: the OpenIddict validation handler lives in the `OpenIddict.Validation` package, which is referenced by the `OpenIddict` metapackage.
> You don't have to explicitly add a new `PackageReference` in your `.csproj` file to be able to use it.
## If necessary, create new application entries
OpenIddict now rejects unauthenticated token/revocation requests by default.
If, after migrating to RC3, you see errors similar to this one:
> **invalid_request** : The mandatory 'client_id' parameter is missing.
Add an application entry for the client application and send the corresponding `client_id` as part of the token request:
```csharp
var descriptor = new OpenIddictApplicationDescriptor
{
ClientId = "postman",
DisplayName = "Postman",
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.GrantTypes.Password,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
OpenIddictConstants.Permissions.Scopes.Email,
OpenIddictConstants.Permissions.Scopes.Profile,
OpenIddictConstants.Permissions.Scopes.Roles
}
};
await _applicationManager.CreateAsync(descriptor);
```
If you prefer accepting anonymous clients, use `options.AcceptAnonymousClients()`:
```csharp
services.AddOpenIddict()
.AddServer(options =>
{
options.AcceptAnonymousClients();
});
```
## If necessary, register the scopes used by your clients
Starting with RC3, OpenIddict will reject unrecognized scopes by default.
If, after migrating to RC3, you see errors similar to this one:
> **invalid_scope** : The specified 'scope' parameter is not valid.
Simply add the scopes you want to use to the list of registered scopes:
```csharp
services.AddOpenIddict()
// Register the OpenIddict server handler.
.AddServer(options =>
{
options.RegisterScopes(OpenIdConnectConstants.Scopes.Email,
OpenIdConnectConstants.Scopes.Profile,
OpenIddictConstants.Scopes.Roles);
});
```
If you prefer disabling scope validation, use `options.DisableScopeValidation()`:
```csharp
services.AddOpenIddict()
.AddServer(options =>
{
options.DisableScopeValidation();
});
```
## If necessary, adjust the permissions granted to your clients
**Starting with RC3, permissions are no longer optional nor implicit**:
if you don't explicitly grant an application the necessary permissions, it will be blocked by OpenIddict.
To attach permissions to an application, use `OpenIddictApplicationManager`:
```csharp
var descriptor = new OpenIddictApplicationDescriptor
{
ClientId = "mvc",
ClientSecret = "901564A5-E7FE-42CB-B10D-61EF6A8F3654",
DisplayName = "MVC client application",
PostLogoutRedirectUris = { new Uri("http://localhost:53507/signout-callback-oidc") },
RedirectUris = { new Uri("http://localhost:53507/signin-oidc") },
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Logout,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
OpenIddictConstants.Permissions.Scopes.Email,
OpenIddictConstants.Permissions.Scopes.Profile,
OpenIddictConstants.Permissions.Scopes.Roles
}
};
await _applicationManager.CreateAsync(descriptor);
```
If you don't care about permissions (e.g because you don't have third-party clients), you can instead disable them:
```csharp
services.AddOpenIddict()
// Register the OpenIddict server handler.
.AddServer(options =>
{
options.IgnoreEndpointPermissions()
.IgnoreGrantTypePermissions()
.IgnoreScopePermissions();
});
```
---------------------------
# Migrate to OpenIddict RC2
## What's new in OpenIddict RC2?
The full list of changes can be found [here](https://github.com/openiddict/openiddict-core/milestone/8?closed=1). It includes **bug fixes** (including a bug fix in the refresh token handling)
and new features like **application permissions**, that allow limiting the OpenID Connect features (endpoints and flows) an application is able to use.
**Migrating to OpenIddict RC2 (`1.0.0-rc2-final` and `2.0.0-rc2-final`) requires making changes in your database**: existing properties have been reworked
(e.g [to work around a MySQL limitation](https://github.com/openiddict/openiddict-core/issues/497)) and new ones have been added to support the new features.
This procedure is quite easy and only requires a few minutes.
> Note: this guide assumes your application uses the OpenIddict Entity Framework Core 2.x stores. If you use a custom store, changes will have to be made manually.
A list of added/updated/renamed columns is available at the end of this guide.
## Ensure migrations are correctly enabled for your project
**Before migrating to OpenIddict RC2, make sure migrations are already enabled for your application**. If you have a `Migrations`
folder in your application root folder and an `__EFMigrationsHistory` table in your database, you're good to go.
If you don't have these Entity Framework Core artifacts, migrations are likely not enabled. To fix that, add the following entries in your `.csproj`:
```xml
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design"
Version="2.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet"
Version="2.0.0" />
</ItemGroup>
```
Then, open a new command line and add an initial migration using `dotnet ef migrations add InitialMigration` (**but don't apply it!**).
## Update your packages references
For that, simply update your `.csproj` file to point to the newest OpenIddict packages:
### ASP.NET Core 1.x
```xml
<ItemGroup>
<PackageReference Include="OpenIddict" Version="1.0.0-rc2-final" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="1.0.0-rc2-final" />
<PackageReference Include="OpenIddict.Mvc" Version="1.0.0-rc2-final" />
</ItemGroup>
```
### ASP.NET Core 2.x
```xml
<ItemGroup>
<PackageReference Include="OpenIddict" Version="2.0.0-rc2-final" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="2.0.0-rc2-final" />
<PackageReference Include="OpenIddict.Mvc" Version="2.0.0-rc2-final" />
</ItemGroup>
```
## Add a new migration
1. First, open a new command line and run `dotnet ef migrations add MigrateToOpenIddictRc2`.
2. **If you created an initial migration at step 1, remove it from the `Migrations` folder**.
3. Apply the `MigrateToOpenIddictRc2` migration using `dotnet ef database update MigrateToOpenIddictRc2`.
## Run the migration script to convert columns to the new format
For that, add the following snippet to your `Startup` class:
```csharp
private async Task UpdateOpenIddictTablesAsync(IServiceProvider services)
{
using (var scope = services.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
// Change ApplicationDbContext to match your context name if you've changed it.
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
await context.Database.EnsureCreatedAsync();
// If you use a different entity type or a custom key,
// change this line (e.g OpenIddictApplication<long>).
foreach (var application in context.Set<OpenIddictApplication>())
{
// Convert the space-separated PostLogoutRedirectUris property to JSON.
if (!string.IsNullOrEmpty(application.PostLogoutRedirectUris) &&
application.PostLogoutRedirectUris[0] != '[')
{
var addresses = application.PostLogoutRedirectUris.Split(
new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
application.PostLogoutRedirectUris =
new JArray(addresses).ToString(Formatting.None);
}
// Convert the space-separated RedirectUris property to JSON.
if (!string.IsNullOrEmpty(application.RedirectUris) &&
application.RedirectUris[0] != '[')
{
var addresses = application.RedirectUris.Split(
new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
application.RedirectUris = new JArray(addresses).ToString(Formatting.None);
}
}
// If you use a different entity type or a custom key,
// change this line (e.g OpenIddictAuthorization<long>).
foreach (var authorization in context.Set<OpenIddictAuthorization>())
{
// Convert the space-separated Scopes property to JSON.
if (!string.IsNullOrEmpty(authorization.Scopes) && authorization.Scopes[0] != '[')
{
var scopes = authorization.Scopes.Split(
new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
authorization.Scopes = new JArray(scopes).ToString(Formatting.None);
}
}
await context.SaveChangesAsync();
}
}
```
Then, at the end of the `public void Configure(IApplicationBuilder app)` method, add the following line:
```csharp
public void Configure(IApplicationBuilder app)
{
app.UseDeveloperExceptionPage();
app.UseStaticFiles();
app.UseStatusCodePagesWithReExecute("/error");
app.UseAuthentication();
app.UseMvcWithDefaultRoute();
// Run the migration script synchronously.
UpdateOpenIddictTablesAsync(app.ApplicationServices).GetAwaiter().GetResult();
}
```
Run your application. Once it's correctly started, stop it and remove the migration script.
## If your authorization server uses introspection, make sure resources are set in the authentication ticket
**Setting an explicit list of resources is now required to allow client applications to introspect a token.**
For that, call `ticket.SetResources()` with the list of the client identifiers allowed to validate the token. E.g:
```csharp
var ticket = new AuthenticationTicket(
new ClaimsPrincipal(identity),
new AuthenticationProperties(),
OpenIdConnectServerDefaults.AuthenticationScheme);
ticket.SetResources("tracking_api", "marketing_api");
```
## Optionally, update your code to grant applications the minimum required permissions
Starting with RC2, OpenIddict includes an optional feature codenamed "app permissions" that allows
controlling and limiting the OAuth2/OpenID Connect features a client application is able to use.
To learn more about this feature, read the [Application permissions documentation](../configuration/application-permissions.md).
## List of changes (for applications using custom stores)
### Renamed properties
| Table | Old column name | New column name | Observations |
|--------------------------|-----------------|------------------|----------------------------------------------------------------------------|
| OpenIddictApplications | Timestamp | ConcurrencyToken | The column type was changed to nvarchar to work around a MySQL limitation. |
| OpenIddictAuthorizations | Timestamp | ConcurrencyToken | The column type was changed to nvarchar to work around a MySQL limitation. |
| OpenIddictScopes | Timestamp | ConcurrencyToken | The column type was changed to nvarchar to work around a MySQL limitation. |
| OpenIddictTokens | Timestamp | ConcurrencyToken | The column type was changed to nvarchar to work around a MySQL limitation. |
| OpenIddictTokens | Ciphertext | Payload | |
| OpenIddictTokens | Hash | ReferenceId | |
### Updated properties
| Table | Column name | Observations |
|--------------------------|------------------------|-----------------------------------------------------------------------------|
| OpenIddictApplications | PostLogoutRedirectUris | Values are now formatted as JSON arrays instead of space-separated strings. |
| OpenIddictApplications | RedirectUris | Values are now formatted as JSON arrays instead of space-separated strings. |
| OpenIddictAuthorizations | Scopes | Values are now formatted as JSON arrays instead of space-separated strings. |
### Added properties
| Table | Column name | Type | Nullable |
|--------------------------|-------------|---------------|----------|
| OpenIddictApplications | ConsentType | nvarchar(max) | Yes |
| OpenIddictApplications | Properties | nvarchar(max) | Yes |
| OpenIddictApplications | Permissions | nvarchar(max) | Yes |
| OpenIddictAuthorizations | Properties | nvarchar(max) | Yes |
| OpenIddictScopes | DisplayName | nvarchar(max) | Yes |
| OpenIddictScopes | Properties | nvarchar(max) | Yes |
| OpenIddictScopes | Resources | nvarchar(max) | Yes |
| OpenIddictTokens | Properties | nvarchar(max) | Yes |

11
guide/samples.md Normal file
View File

@@ -0,0 +1,11 @@
# Samples
**[Specialized samples can be found in the samples repository](https://github.com/openiddict/openiddict-samples):**
- [Authorization code flow sample](https://github.com/openiddict/openiddict-samples/tree/dev/samples/CodeFlow)
- [Implicit flow sample](https://github.com/openiddict/openiddict-samples/tree/dev/samples/ImplicitFlow)
- [Password flow sample](https://github.com/openiddict/openiddict-samples/tree/dev/samples/PasswordFlow)
- [Client credentials flow sample](https://github.com/openiddict/openiddict-samples/tree/dev/samples/ClientCredentialsFlow)
- [Refresh flow sample](https://github.com/openiddict/openiddict-samples/tree/dev/samples/RefreshFlow)
> **Samples for ASP.NET Core 1.x can be found [in the master branch of the samples repository](https://github.com/openiddict/openiddict-samples/tree/master)**.

14
guide/toc.yml Normal file
View File

@@ -0,0 +1,14 @@
- name: Introduction
href: index.md
- name: Getting started
href: getting-started.md
- name: Samples
href: samples.md
- name: Migration guide
href: migration.md
- name: Understanding the different token formats
href: token-formats.md

74
guide/token-formats.md Normal file
View File

@@ -0,0 +1,74 @@
# Understanding the different token formats
OpenIddict can be configured to use three access token formats:
- opaque tokens (default)
- reference tokens
- JWTs (Json Web Tokens)
Tokens differ in what they look like and how they are validated. The default tokens will work fine in most use cases. There are times, however, where the other token formats would be preferred or required.
> **Note: Identity tokens are always JWTs, according to spec.**
## Opaque tokens (default)
The default access tokens are opaque tokens. They are encrypted and signed by the authorization server using the ASP.NET Core Data Protection stack. Their contents can only be inspected by the authorization server or another server sharing the same ASP.NET Core Data Protection configuration.
These are "proprietary" tokens that are not meant to be read or verified by a third-party, as the token format is not standard and necessarily relies on symmetric signing and encryption.
We use this format for authorization codes and refresh tokens. They are only meant to be consumed by OpenIddict itself.
### Benefits
- No additional configuration required
- Uses OpenIddict's built-in validation
- Resource servers can validate tokens without having to contact authorization server if using shared ASP.NET Core DataProtection
- Tokens are encrypted so no one can inspect the token, e.g. if tokens somehow end up in your logs somewhere or are intercepted somehow
### Drawbacks
- Proprietary format, so if you add non .NET Core resource servers in the future you need to switch to JWTs for direct validation or use introspection for indirect validation
- Claims are stored within the token, which is convenient but token size could get large if there are a lot of claims (probably not an issue in real-world scenarios)
- Token expiration is in the token itself, so even if users sign out their tokens will still be valid until they reach their expiration
### Setup and API validation configuration
[Here](../configuration/token-setup-and-validation.md#default-configuration-opaque-tokens)
---
## Reference tokens
When using reference token format, authorization codes, access tokens and refresh tokens are stored as ciphertext in the database and a crypto-secure random identifier is returned to the client application.
### Benefits
- Minimal configuration required
- Uses OpenIddict's built-in validation
- Resource servers can validate tokens without having to contact authorization server
- Token sizes are very small regardless of number of claims because they only contain ids
- Issued tokens are tracked in data store
- Can immediately be revoked
### Drawbacks
- .NET Core validation only (although someone could write it for other platforms)
- Requires a connection to OpenIddict's data store, e.g. Entity Framework DataContext. Resource servers may not want to have to reference OpenIddict's database
- Because only ids are in the access tokens, a call to the database is required for every request
### Setup and API validation configuration
[Here](../configuration/token-setup-and-validation.md#reference-token-format)
---
## JWTs (JSON Web Tokens)
These are standard tokens verifiable by third parties, used by Azure Active Directory, Auth0, and other valid OAuth 2.0 service. They are signed by the authorization server but their contents are not encrypted so they can be read by anyone.
### Benefits
- Good to be familiar with JWTs because they are a commonly used access token type in OAuth 2.0 and are also `id token` type
- Plenty of platforms include JWT validation libraries (.NET, PHP, Node, Python, etc)
- Future proof
### Drawbacks
- Anyone can inspect contents (see https://jwt.io/), so if token is hanging around in a log somewhere or intercepted somehow all claims or other information in the token can be read, even if token is expired
- Claims are stored within the token, which is convenient but token size could get large if there are a lot of claims (probably not an issue in real-world scenarios)
- Token expiration is in the token itself, so even if users sign out their tokens will still be valid until they reach their expiration
### Setup and API validation configuration
[Here](../configuration/token-setup-and-validation.md#jwts)