Files
Umbraco-CMS/src/Umbraco.Cms.Api.Management/Security/BackOfficeApplicationManager.cs
Kenn Jacobsen 7b62fb282f Dedicated cookie setup for new backoffice login (#14122)
* Add a dedicated (temporary) cookie setup for new backoffice logins, so old and new backoffice can co-exist behind separate logins

* use temp management api login endpoint for authentication

* Update OpenAPI JSON

---------

Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
2023-04-19 13:32:11 +02:00

134 lines
5.5 KiB
C#

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using OpenIddict.Abstractions;
using Umbraco.New.Cms.Core;
using Umbraco.New.Cms.Core.Models.Configuration;
using Umbraco.New.Cms.Infrastructure.Security;
namespace Umbraco.Cms.Api.Management.Security;
public class BackOfficeApplicationManager : IBackOfficeApplicationManager
{
private readonly IOpenIddictApplicationManager _applicationManager;
private readonly IWebHostEnvironment _webHostEnvironment;
private readonly Uri? _backOfficeHost;
private readonly string? _authorizeCallbackPathName;
public BackOfficeApplicationManager(
IOpenIddictApplicationManager applicationManager,
IWebHostEnvironment webHostEnvironment,
IOptions<NewBackOfficeSettings> securitySettings)
{
_applicationManager = applicationManager;
_webHostEnvironment = webHostEnvironment;
_backOfficeHost = securitySettings.Value.BackOfficeHost;
_authorizeCallbackPathName = securitySettings.Value.AuthorizeCallbackPathName;
}
public async Task EnsureBackOfficeApplicationAsync(Uri backOfficeUrl, CancellationToken cancellationToken = default)
{
if (backOfficeUrl.IsAbsoluteUri is false)
{
throw new ArgumentException($"Expected an absolute URL, got: {backOfficeUrl}", nameof(backOfficeUrl));
}
await CreateOrUpdate(
new OpenIddictApplicationDescriptor
{
DisplayName = "Umbraco back-office access",
ClientId = Constants.OauthClientIds.BackOffice,
RedirectUris =
{
CallbackUrlFor(_backOfficeHost ?? backOfficeUrl, _authorizeCallbackPathName ?? "/umbraco")
},
Type = OpenIddictConstants.ClientTypes.Public,
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
OpenIddictConstants.Permissions.ResponseTypes.Code
}
},
cancellationToken);
if (_webHostEnvironment.IsProduction())
{
await Delete(Constants.OauthClientIds.Swagger, cancellationToken);
await Delete(Constants.OauthClientIds.Postman, cancellationToken);
}
else
{
await CreateOrUpdate(
new OpenIddictApplicationDescriptor
{
DisplayName = "Umbraco Swagger access",
ClientId = Constants.OauthClientIds.Swagger,
RedirectUris =
{
CallbackUrlFor(backOfficeUrl, "/umbraco/swagger/oauth2-redirect.html")
},
Type = OpenIddictConstants.ClientTypes.Public,
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.ResponseTypes.Code
}
},
cancellationToken);
await CreateOrUpdate(
new OpenIddictApplicationDescriptor
{
DisplayName = "Umbraco Postman access",
ClientId = Constants.OauthClientIds.Postman,
RedirectUris =
{
new Uri("https://oauth.pstmn.io/v1/callback")
},
Type = OpenIddictConstants.ClientTypes.Public,
Permissions =
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.ResponseTypes.Code
}
},
cancellationToken);
}
}
private async Task CreateOrUpdate(OpenIddictApplicationDescriptor clientDescriptor, CancellationToken cancellationToken)
{
var identifier = clientDescriptor.ClientId ??
throw new ApplicationException($"ClientId is missing for application: {clientDescriptor.DisplayName ?? "(no name)"}");
var client = await _applicationManager.FindByClientIdAsync(identifier, cancellationToken);
if (client is null)
{
await _applicationManager.CreateAsync(clientDescriptor, cancellationToken);
}
else
{
await _applicationManager.UpdateAsync(client, clientDescriptor, cancellationToken);
}
}
private async Task Delete(string identifier, CancellationToken cancellationToken)
{
var client = await _applicationManager.FindByClientIdAsync(identifier, cancellationToken);
if (client is null)
{
return;
}
await _applicationManager.DeleteAsync(client, cancellationToken);
}
private static Uri CallbackUrlFor(Uri url, string relativePath) => new Uri( $"{url.GetLeftPart(UriPartial.Authority)}/{relativePath.TrimStart(Core.Constants.CharArrays.ForwardSlash)}");
}