From 0675b47e57059c6b1b94fe00060956c964daf1fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Chalet?= <kevinchalet@gmail.com> Date: Mon, 8 Feb 2021 11:56:07 +0100 Subject: [PATCH] Add claim destinations documentation --- configuration/claim-destinations.md | 59 +++++++++++++++++++++++++++++ configuration/toc.yml | 3 ++ 2 files changed, 62 insertions(+) create mode 100644 configuration/claim-destinations.md diff --git a/configuration/claim-destinations.md b/configuration/claim-destinations.md new file mode 100644 index 0000000..b00c82a --- /dev/null +++ b/configuration/claim-destinations.md @@ -0,0 +1,59 @@ +# Claim destinations + +**When generating authorization codes, refresh tokens and device/user codes** from the `ClaimsPrincipal` specified during a sign-in operation, +**OpenIddict automatically copies all the claims to the resulting codes/tokens**. This is a safe operation because these tokens are always encrypted +and can't be read by anyone but OpenIddict itself (the user or the client application that requested them cannot read their content). + +**For access and identity tokens, things work differently**, as these tokens are meant to be read by different parties: + - Client applications have a total access to the claims contained in the identity tokens they receive. + - Resource servers are expected to be able to read the claims contained in the access tokens used in API calls. + - With desktop, mobile or browser-based applications, it's generally not hard for users to access identity tokens +(e.g by intercepting the HTTP response using Fiddler, by using developer tools or by dumping the memory of the client process). + - If access token encryption was explicitly disabled, it's possible for the client applications or the users themselves +to access the content of access tokens (e.g by copying the token payload and using a tool like https://jwt.io/). + +For these reasons, **OpenIddict doesn't automatically copy the claims attached to a `ClaimsPrincipal` to access or identity tokens** +(except the `sub` claim, which is the only mandatory claim in OpenIddict). To allow OpenIddict to persist specific claims +to an access or identity token, a flag known as "claim destination" must be added to each `Claim` instance you want to expose. + +> [!NOTE] +> To attach one or multiple destinations to a claim, use the `claim.SetDestinations()` extension defined in `OpenIddict.Abstractions`. +> In the typical case, granted scopes can be used to determine what claims are allowed to be copied to access and identity tokens, as in this example: + +```csharp +var principal = await _signInManager.CreateUserPrincipalAsync(user); + +// Note: in this sample, the granted scopes match the requested scope +// but you may want to allow the user to uncheck specific scopes. +// For that, simply restrict the list of scopes before calling SetScopes(). +principal.SetScopes(request.GetScopes()); +principal.SetResources( + await _scopeManager.ListResourcesAsync(principal.GetScopes()).ToListAsync()); + +foreach (var claim in principal.Claims) +{ + claim.SetDestinations(claim.Type switch + { + // If the "profile" scope was granted, allow the "name" claim to be + // added to the access and identity tokens derived from the principal. + Claims.Name when principal.HasScope(Scopes.Profile) => new[] + { + OpenIddictConstants.Destinations.AccessToken, + OpenIddictConstants.Destinations.IdentityToken + }, + + // Never add the "secret_value" claim to access or identity tokens. + // In this case, it will only be added to authorization codes, + // refresh tokens and user/device codes, that are always encrypted. + "secret_value" => Array.Empty<string>(), + + // Otherwise, add the claim to the access tokens only. + _ => new[] + { + OpenIddictConstants.Destinations.AccessToken + } + }); +} + +return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); +``` \ No newline at end of file diff --git a/configuration/toc.yml b/configuration/toc.yml index ae712c8..356803f 100644 --- a/configuration/toc.yml +++ b/configuration/toc.yml @@ -7,6 +7,9 @@ - name: Authorization storage href: authorization-storage.md +- name: Claim destinations + href: claim-destinations.md + - name: Token formats href: token-formats.md