V14: Redirect to login screen (#16051)
* Redirect to login screen after flows complete * Revoke tokens after completing flow * Use Ok not Redirect * skip length check
This commit is contained in:
@@ -54,16 +54,16 @@ public class BackOfficeLoginController : Controller
|
||||
model.UmbracoUrl = _hostingEnvironment.ToAbsolute(_globalSettings.UmbracoPath);
|
||||
}
|
||||
|
||||
if ( Uri.TryCreate(model.ReturnUrl, UriKind.Relative, out _) is false) // Needs to test for relative and not absolute, as /whatever/ is an absolute path on linux
|
||||
{
|
||||
return BadRequest("ReturnUrl must be a relative path.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(model.ReturnUrl))
|
||||
{
|
||||
model.ReturnUrl = model.UmbracoUrl;
|
||||
}
|
||||
|
||||
if ( Uri.TryCreate(model.ReturnUrl, UriKind.Relative, out _) is false) // Needs to test for relative and not absolute, as /whatever/ is an absolute path on linux
|
||||
{
|
||||
return BadRequest("ReturnUrl must be a relative path.");
|
||||
}
|
||||
|
||||
return View("/umbraco/UmbracoLogin/Index.cshtml", model);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using Asp.Versioning;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using OpenIddict.Abstractions;
|
||||
using Umbraco.Cms.Api.Common.Builders;
|
||||
using Umbraco.Cms.Api.Management.Filters;
|
||||
using Umbraco.Cms.Api.Management.ViewModels.Security;
|
||||
@@ -10,6 +11,7 @@ using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
using Umbraco.Cms.Web.Common.Authorization;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Api.Management.Controllers.Security;
|
||||
|
||||
@@ -18,8 +20,13 @@ namespace Umbraco.Cms.Api.Management.Controllers.Security;
|
||||
public class ResetPasswordTokenController : SecurityControllerBase
|
||||
{
|
||||
private readonly IUserService _userService;
|
||||
private readonly IOpenIddictTokenManager _tokenManager;
|
||||
|
||||
public ResetPasswordTokenController(IUserService userService) => _userService = userService;
|
||||
public ResetPasswordTokenController(IUserService userService, IOpenIddictTokenManager tokenManager)
|
||||
{
|
||||
_userService = userService;
|
||||
_tokenManager = tokenManager;
|
||||
}
|
||||
|
||||
[HttpPost("forgot-password/reset")]
|
||||
[MapToApiVersion("1.0")]
|
||||
@@ -31,8 +38,13 @@ public class ResetPasswordTokenController : SecurityControllerBase
|
||||
{
|
||||
Attempt<PasswordChangedModel, UserOperationStatus> result = await _userService.ResetPasswordAsync(model.User.Id, model.ResetCode, model.Password);
|
||||
|
||||
return result.Success
|
||||
? NoContent()
|
||||
: UserOperationStatusResult(result.Status, result.Result);
|
||||
if (result.Success is false)
|
||||
{
|
||||
return UserOperationStatusResult(result.Status, result.Result);
|
||||
}
|
||||
|
||||
await _tokenManager.RevokeUmbracoUserTokens(model.User.Id);
|
||||
return Ok();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,14 @@ using Asp.Versioning;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using OpenIddict.Abstractions;
|
||||
using Umbraco.Cms.Api.Management.ViewModels.User;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Core.Services.OperationStatus;
|
||||
using Umbraco.Cms.Web.Common.Authorization;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Api.Management.Controllers.User;
|
||||
|
||||
@@ -16,8 +18,13 @@ namespace Umbraco.Cms.Api.Management.Controllers.User;
|
||||
public class CreateInitialPasswordUserController : UserControllerBase
|
||||
{
|
||||
private readonly IUserService _userService;
|
||||
private readonly IOpenIddictTokenManager _tokenManager;
|
||||
|
||||
public CreateInitialPasswordUserController(IUserService userService) => _userService = userService;
|
||||
public CreateInitialPasswordUserController(IUserService userService, IOpenIddictTokenManager tokenManager)
|
||||
{
|
||||
_userService = userService;
|
||||
_tokenManager = tokenManager;
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpPost("invite/create-password")]
|
||||
@@ -31,8 +38,12 @@ public class CreateInitialPasswordUserController : UserControllerBase
|
||||
{
|
||||
Attempt<PasswordChangedModel, UserOperationStatus> response = await _userService.CreateInitialPasswordAsync(model.User.Id, model.Token, model.Password);
|
||||
|
||||
return response.Success
|
||||
? Ok()
|
||||
: UserOperationStatusResult(response.Status, response.Result);
|
||||
if (response.Success is false)
|
||||
{
|
||||
return UserOperationStatusResult(response.Status, response.Result);
|
||||
}
|
||||
|
||||
await _tokenManager.RevokeUmbracoUserTokens(model.User.Id);
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using OpenIddict.Abstractions;
|
||||
|
||||
namespace Umbraco.Extensions;
|
||||
|
||||
public static class OpenIdDictTokenManagerExtensions
|
||||
{
|
||||
public static async Task RevokeUmbracoUserTokens(this IOpenIddictTokenManager openIddictTokenManager, Guid userKey)
|
||||
{
|
||||
var tokens = await openIddictTokenManager.FindBySubjectAsync(userKey.ToString()).ToArrayAsync();
|
||||
|
||||
foreach (var token in tokens)
|
||||
{
|
||||
await openIddictTokenManager.DeleteAsync(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,17 +215,9 @@ internal sealed class RevokeUserAuthenticationTokensNotificationHandler :
|
||||
|
||||
private async Task RevokeTokensAsync(IUser user)
|
||||
{
|
||||
var tokens = await _tokenManager.FindBySubjectAsync(user.Key.ToString()).ToArrayAsync();
|
||||
if (tokens.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_logger.LogInformation("Revoking active tokens for user with ID {id}", user.Id);
|
||||
|
||||
_logger.LogInformation("Revoking {count} active tokens for user with ID {id}", tokens.Length, user.Id);
|
||||
foreach (var token in tokens)
|
||||
{
|
||||
await _tokenManager.DeleteAsync(token);
|
||||
}
|
||||
await _tokenManager.RevokeUmbracoUserTokens(user.Key);
|
||||
}
|
||||
|
||||
private async Task<IUser?> FindUserFromString(string userId)
|
||||
|
||||
Reference in New Issue
Block a user