Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added settings to reduce tokensize for OpenId #4129

Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using OrchardCore.OpenId.Filters;
using OrchardCore.OpenId.Services;
using OrchardCore.OpenId.ViewModels;
using OrchardCore.Security.Permissions;
using OrchardCore.Security.Services;
using OrchardCore.Users.Services;

Expand All @@ -36,6 +37,7 @@ public class AccessController : Controller
private readonly IOpenIdScopeManager _scopeManager;
private readonly ShellSettings _shellSettings;
private readonly IStringLocalizer<AccessController> T;
private readonly IOpenIdServerService _serverService;

public AccessController(
IOpenIdApplicationManager applicationManager,
Expand All @@ -50,6 +52,7 @@ public AccessController(
_authorizationManager = authorizationManager;
_scopeManager = scopeManager;
_shellSettings = shellSettings;
_serverService = serverService;
}

[AllowAnonymous, HttpGet, HttpPost, IgnoreAntiforgeryToken]
Expand Down Expand Up @@ -483,6 +486,8 @@ private async Task<AuthenticationTicket> CreateUserTicketAsync(
}
}

await CleanUpClaimsAsync(identity);

// Note: by default, claims are NOT automatically included in the access and identity tokens.
// To allow OpenIddict to serialize them, you must attach them a destination, that specifies
// whether they should be included in access tokens, in identity tokens or in both.
Expand Down Expand Up @@ -516,6 +521,36 @@ private async Task<AuthenticationTicket> CreateUserTicketAsync(
return ticket;
}

// Dependening on the configuration, we clean up claims to limit the size of the token
private async Task CleanUpClaimsAsync(ClaimsIdentity identity)
{
var settings = await _serverService.GetSettingsAsync();

if(!settings.IncludeRolesInToken)
{
RemoveAllClaims(identity, OpenIddictConstants.Claims.Role);
RemoveAllClaims(identity, OpenIddictConstants.Claims.Roles);
}

if(!settings.IncludeLegacyMicrosoftClaimsInToken)
{
RemoveAllClaims(identity, ClaimTypes.Role);
RemoveAllClaims(identity, ClaimTypes.Name);
RemoveAllClaims(identity, ClaimTypes.NameIdentifier);
}

if(!settings.IncludePermissionsInToken)
{
RemoveAllClaims(identity, Permission.ClaimType);
}
}

private void RemoveAllClaims(ClaimsIdentity identity, string claimName)
{
var claims = identity.Claims.Where(claim => claim.Type == claimName).ToList();
claims.ForEach(claim => identity.RemoveClaim(claim));
}

private async Task<IEnumerable<string>> GetResourcesAsync(IEnumerable<string> scopes)
{
// Note: the current tenant name is always added as a valid resource/audience,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ public override Task<IDisplayResult> EditAsync(OpenIdServerSettings settings, Bu
model.AllowRefreshTokenFlow = settings.GrantTypes.Contains(GrantTypes.RefreshToken);
model.AllowImplicitFlow = settings.GrantTypes.Contains(GrantTypes.Implicit);

model.IncludePermissionsInToken = settings.IncludePermissionsInToken;
model.IncludeRolesInToken = settings.IncludeRolesInToken;
model.IncludeLegacyMicrosoftClaimsInToken = settings.IncludeLegacyMicrosoftClaimsInToken;

model.UseRollingTokens = settings.UseRollingTokens;

foreach (var (certificate, location, name) in await _serverService.GetAvailableCertificatesAsync())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ public class OpenIdServerSettings
public PathString UserinfoEndpointPath { get; set; }
public ISet<string> GrantTypes { get; } = new HashSet<string>(StringComparer.Ordinal);
public bool UseRollingTokens { get; set; }

public bool IncludePermissionsInToken { get; set; } = true;
public bool IncludeRolesInToken { get; set; } = true;
public bool IncludeLegacyMicrosoftClaimsInToken { get; set; } = true;
public enum TokenFormat
{
Encrypted = 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ public class OpenIdServerSettingsViewModel
public bool AllowRefreshTokenFlow { get; set; }
public bool AllowImplicitFlow { get; set; }
public bool UseRollingTokens { get; set; }
public bool IncludePermissionsInToken { get; set; }
public bool IncludeRolesInToken { get; set; }
public bool IncludeLegacyMicrosoftClaimsInToken { get; set; }

public class CertificateInfo
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@
}
</fieldset>

<h3>Tokens</h3>

<fieldset class="form-group" asp-validation-class-for="UseRollingTokens">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" asp-for="UseRollingTokens">
Expand All @@ -175,6 +177,28 @@
<span asp-validation-for="AccessTokenFormat"></span>
</fieldset>

<fieldset class="form-group" asp-validation-class-for="IncludeLegacyMicrosoftClaimsInToken">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" asp-for="IncludeLegacyMicrosoftClaimsInToken">
<label class="custom-control-label" asp-for="IncludeLegacyMicrosoftClaimsInToken">@T["Include Legacy MicrosoftClaims in the Token."]</label>
MatthijsKrempel marked this conversation as resolved.
Show resolved Hide resolved
</div>
</fieldset>

<fieldset class="form-group" asp-validation-class-for="IncludePermissionsInToken">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" asp-for="IncludePermissionsInToken">
<label class="custom-control-label" asp-for="IncludePermissionsInToken">@T["Include OrchardCore Permissions in the Token."]</label>
<span class="hint">— @T["Warning, this will increase tokensize significantly."]</span>
</div>
</fieldset>

<fieldset class="form-group" asp-validation-class-for="IncludeRolesInToken">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" asp-for="IncludeRolesInToken">
<label class="custom-control-label" asp-for="IncludeRolesInToken">@T["Include OrchardCore Roles in the Token."]</label>
</div>
</fieldset>

<script at="Foot" type="text/javascript">
////<![CDATA[
window.onload = function () {
Expand Down