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

Migrate the OpenID module to OpenIddict 6.0 #16929

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
12 changes: 6 additions & 6 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@
<PackageVersion Include="NJsonSchema" Version="11.0.2" />
<PackageVersion Include="NLog.Web.AspNetCore" Version="5.3.14" />
<PackageVersion Include="NodaTime" Version="3.2.0" />
<PackageVersion Include="OpenIddict.Core" Version="5.8.0" />
<PackageVersion Include="OpenIddict.Server.AspNetCore" Version="5.8.0" />
<PackageVersion Include="OpenIddict.Server.DataProtection" Version="5.8.0" />
<PackageVersion Include="OpenIddict.Validation.AspNetCore" Version="5.8.0" />
<PackageVersion Include="OpenIddict.Validation.DataProtection" Version="5.8.0" />
<PackageVersion Include="OpenIddict.Validation.SystemNetHttp" Version="5.8.0" />
<PackageVersion Include="OpenIddict.Core" Version="6.0.0-preview3.24551.41" />
<PackageVersion Include="OpenIddict.Server.AspNetCore" Version="6.0.0-preview3.24551.41" />
<PackageVersion Include="OpenIddict.Server.DataProtection" Version="6.0.0-preview3.24551.41" />
<PackageVersion Include="OpenIddict.Validation.AspNetCore" Version="6.0.0-preview3.24551.41" />
<PackageVersion Include="OpenIddict.Validation.DataProtection" Version="6.0.0-preview3.24551.41" />
<PackageVersion Include="OpenIddict.Validation.SystemNetHttp" Version="6.0.0-preview3.24551.41" />
<PackageVersion Include="OrchardCore.Translations.All" Version="2.1.0" />
<PackageVersion Include="PdfPig" Version="0.1.9" />
<PackageVersion Include="Serilog.AspNetCore" Version="8.0.3" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public void Configure(OpenIddictServerOptions options)

if (settings.LogoutEndpointPath.HasValue)
{
options.LogoutEndpointUris.Add(new Uri(
options.EndSessionEndpointUris.Add(new Uri(
settings.LogoutEndpointPath.ToUriComponent()[1..], UriKind.Relative));
}

Expand All @@ -95,7 +95,7 @@ public void Configure(OpenIddictServerOptions options)

if (settings.UserinfoEndpointPath.HasValue)
{
options.UserinfoEndpointUris.Add(new Uri(
options.UserInfoEndpointUris.Add(new Uri(
settings.UserinfoEndpointPath.ToUriComponent()[1..], UriKind.Relative));
}

Expand Down Expand Up @@ -195,18 +195,18 @@ public void Configure(OpenIddictServerDataProtectionOptions options)

public void Configure(string name, OpenIddictServerAspNetCoreOptions options)
{
// Note: the OpenID module handles the authorization, logout, token and userinfo requests
// Note: the OpenID module handles the authorization, end session, token and userinfo requests
// in its dedicated ASP.NET Core MVC controller, which requires enabling the pass-through mode.
options.EnableAuthorizationEndpointPassthrough = true;
options.EnableLogoutEndpointPassthrough = true;
options.EnableEndSessionEndpointPassthrough = true;
options.EnableTokenEndpointPassthrough = true;
options.EnableUserinfoEndpointPassthrough = true;
options.EnableUserInfoEndpointPassthrough = true;

// Note: caching is enabled for both authorization and logout requests to allow sending
// large POST authorization and logout requests, but can be programmatically disabled, as the
// authorization and logout views support flowing the entire payload and not just the request_id.
// Note: caching is enabled for both authorization and end session requests to allow sending
// large POST authorization and end session requests, but can be programmatically disabled, as the
// authorization and end session views support flowing the entire payload and not just the request_id.
options.EnableAuthorizationRequestCaching = true;
options.EnableLogoutRequestCaching = true;
options.EnableEndSessionRequestCaching = true;

// Note: error pass-through is enabled to allow the actions of the MVC authorization controller
// to handle the errors returned by the interactive endpoints without relying on the generic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Primitives;
using OpenIddict.Abstractions;
using OpenIddict.Server.AspNetCore;
using OrchardCore.Environment.Shell;
Expand Down Expand Up @@ -64,7 +65,7 @@ public async Task<IActionResult> Authorize()
// Retrieve the claims stored in the authentication cookie.
// If they can't be extracted, redirect the user to the login page.
var result = await HttpContext.AuthenticateAsync();
if (result == null || !result.Succeeded || request.HasPrompt(Prompts.Login))
if (result == null || !result.Succeeded || request.HasPromptValue(PromptValues.Login))
{
return RedirectToLoginPage(request);
}
Expand Down Expand Up @@ -99,7 +100,7 @@ public async Task<IActionResult> Authorize()

case ConsentTypes.Implicit:
case ConsentTypes.External when authorizations.Count > 0:
case ConsentTypes.Explicit when authorizations.Count > 0 && !request.HasPrompt(Prompts.Consent):
case ConsentTypes.Explicit when authorizations.Count > 0 && !request.HasPromptValue(PromptValues.Consent):
var identity = new ClaimsIdentity(result.Principal.Claims, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(OpenIdConstants.Claims.EntityType, OpenIdConstants.EntityTypes.User));

Expand All @@ -123,7 +124,7 @@ public async Task<IActionResult> Authorize()

return SignIn(new ClaimsPrincipal(identity), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);

case ConsentTypes.Explicit when request.HasPrompt(Prompts.None):
case ConsentTypes.Explicit when request.HasPromptValue(PromptValues.None):
return Forbid(new AuthenticationProperties(new Dictionary<string, string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.ConsentRequired,
Expand All @@ -144,7 +145,7 @@ IActionResult RedirectToLoginPage(OpenIddictRequest request)
{
// If the client application requested promptless authentication,
// return an error indicating that the user is not logged in.
if (request.HasPrompt(Prompts.None))
if (request.HasPromptValue(PromptValues.None))
{
return Forbid(new AuthenticationProperties(new Dictionary<string, string>
{
Expand All @@ -155,9 +156,15 @@ IActionResult RedirectToLoginPage(OpenIddictRequest request)

string GetRedirectUrl()
{
// Override the prompt parameter to prevent infinite authentication/authorization loops.
var parameters = Request.Query.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
parameters[Parameters.Prompt] = "continue";
// To avoid endless login -> authorization redirects, the prompt=login flag
// is removed from the authorization request payload before redirecting the user.
var prompt = string.Join(" ", request.GetPromptValues().Remove(PromptValues.Login));

var parameters = Request.HasFormContentType ?
Request.Form.Where(parameter => parameter.Key != Parameters.Prompt).ToList() :
Request.Query.Where(parameter => parameter.Key != Parameters.Prompt).ToList();

parameters.Add(new(Parameters.Prompt, new StringValues(prompt)));

return Request.PathBase + Request.Path + QueryString.Create(parameters);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ await HasPermissionAsync(OpenIddictConstants.Permissions.ResponseTypes.Token)),

AllowPasswordFlow = await HasPermissionAsync(OpenIddictConstants.Permissions.GrantTypes.Password),
AllowRefreshTokenFlow = await HasPermissionAsync(OpenIddictConstants.Permissions.GrantTypes.RefreshToken),
AllowLogoutEndpoint = await HasPermissionAsync(OpenIddictConstants.Permissions.Endpoints.Logout),
AllowLogoutEndpoint = await HasPermissionAsync(OpenIddictConstants.Permissions.Endpoints.EndSession),
AllowIntrospectionEndpoint = await HasPermissionAsync(OpenIddictConstants.Permissions.Endpoints.Introspection),
AllowRevocationEndpoint = await HasPermissionAsync(OpenIddictConstants.Permissions.Endpoints.Revocation),
ClientId = await _applicationManager.GetClientIdAsync(application),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ public static async Task UpdateDescriptorFromSettings(this IOpenIdApplicationMan

if (model.AllowLogoutEndpoint)
{
descriptor.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout);
descriptor.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.EndSession);
}
else
{
descriptor.Permissions.Remove(OpenIddictConstants.Permissions.Endpoints.Logout);
descriptor.Permissions.Remove(OpenIddictConstants.Permissions.Endpoints.EndSession);
}

if (model.AllowAuthorizationCodeFlow || model.AllowHybridFlow)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,17 @@
<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="AllowLogoutEndpoint" data-bs-toggle="collapse" data-bs-target="#postLogoutRedirectUris" checked="@Model.AllowLogoutEndpoint">
<label class="form-check-label" asp-for="AllowLogoutEndpoint">@T["Allow Logout Endpoint"]</label>
<label class="form-check-label" asp-for="AllowLogoutEndpoint">@T["Allow End Session Endpoint"]</label>
</div>
</div>
<div class="mb-3 collapse" id="postLogoutRedirectUris" name="postLogoutRedirectUris">
<div class="mb-3" asp-validation-class-for="PostLogoutRedirectUris">
<label asp-for="PostLogoutRedirectUris" class="form-label">@T["Logout Redirect Uris"]</label>
<label asp-for="PostLogoutRedirectUris" class="form-label">@T["Post-Logout Redirect Uris"]</label>
<input asp-for="PostLogoutRedirectUris" class="form-control" autofocus />
<span asp-validation-for="PostLogoutRedirectUris" class="text-danger"></span>
</div>
<div class="hint">
@T["Space delimited list of logout redirect URIs."]
@T["Space delimited list of post-logout redirect URIs."]
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,17 +131,17 @@
<div class="mb-3">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="AllowLogoutEndpoint" data-bs-toggle="collapse" data-bs-target="#postLogoutRedirectUris" checked="@Model.AllowLogoutEndpoint">
<label class="form-check-label" asp-for="AllowLogoutEndpoint">@T["Allow Logout Endpoint"]</label>
<label class="form-check-label" asp-for="AllowLogoutEndpoint">@T["Allow End Session Endpoint"]</label>
</div>
</div>
<div class="mb-3 collapse" id="postLogoutRedirectUris" name="postLogoutRedirectUris">
<div class="mb-3" asp-validation-class-for="PostLogoutRedirectUris">
<label asp-for="PostLogoutRedirectUris">@T["Post Logout Redirect Uris"]</label>
<label asp-for="PostLogoutRedirectUris">@T["Post-Logout Redirect Uris"]</label>
<input asp-for="PostLogoutRedirectUris" class="form-control" autofocus />
<span asp-validation-for="PostLogoutRedirectUris" class="text-danger"></span>
</div>
<div class="hint">
@T["Space delimited list of logout redirect URIs."]
@T["Space delimited list of post-logout redirect URIs."]
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<div class="mb-3" asp-validation-class-for="EnableLogoutEndpoint">
<div class="form-check">
<input type="checkbox" class="form-check-input" asp-for="EnableLogoutEndpoint">
<label class="form-check-label" asp-for="EnableLogoutEndpoint">@T["Enable Logout Endpoint"]</label>
<label class="form-check-label" asp-for="EnableLogoutEndpoint">@T["Enable End Session Endpoint"]</label>
<span class="hint dashed">@T["Enables the endpoint:"]</span> <code>/connect/logout</code>
</div>
</div>
Expand Down
Loading