Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ public async Task<IActionResult> Index(CancellationToken cancellationToken, Back
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
if (string.IsNullOrEmpty(model.ReturnUrl))
{
return BadRequest("ReturnUrl must be a relative path.");
model.ReturnUrl = model.UmbracoUrl;
}

if (string.IsNullOrEmpty(model.ReturnUrl))
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
{
model.ReturnUrl = model.UmbracoUrl;
return BadRequest("ReturnUrl must be a relative path.");
}

return View("/umbraco/UmbracoLogin/Index.cshtml", model);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
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;
Expand All @@ -10,6 +11,7 @@
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;

Expand All @@ -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")]
Expand All @@ -31,8 +38,13 @@ public async Task<IActionResult> ResetPasswordToken(CancellationToken cancellati
{
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();

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
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;

Expand All @@ -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")]
Expand All @@ -31,8 +38,12 @@ public async Task<IActionResult> CreateInitialPassword(
{
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();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
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();
if (tokens.Length == 0)
Comment thread
Zeegaan marked this conversation as resolved.
Outdated
{
return;
}

foreach (var token in tokens)
{
await openIddictTokenManager.DeleteAsync(token);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -215,17 +215,9 @@ private UserStartNodesAndGroupAccess MapToUserStartNodesAndGroupAccess(IUser use

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)
Expand Down