Adjust Auth on server (#15)
* add auth that verifies identity is marked online * few changes for testing * handle identity with requirements * remove unnecessary logging from auth handler * change to UserRequirements * fixes to checks * fixes to UserRequirementHandler Co-authored-by: rootdarkarchon <root.darkarchon@outlook.com>
This commit is contained in:
@@ -2,7 +2,6 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MareSynchronos.API;
|
using MareSynchronos.API;
|
||||||
using MareSynchronosShared.Authentication;
|
|
||||||
using MareSynchronosShared.Models;
|
using MareSynchronosShared.Models;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
@@ -12,16 +11,11 @@ namespace MareSynchronosServer.Hubs;
|
|||||||
|
|
||||||
public partial class MareHub
|
public partial class MareHub
|
||||||
{
|
{
|
||||||
private bool IsAdmin => _dbContext.Users.Single(b => b.UID == AuthenticatedUserId).IsAdmin;
|
|
||||||
|
|
||||||
private bool IsModerator => _dbContext.Users.Single(b => b.UID == AuthenticatedUserId).IsModerator || IsAdmin;
|
|
||||||
|
|
||||||
private List<string> OnlineAdmins => _dbContext.Users.Where(u => (u.IsModerator || u.IsAdmin)).Select(u => u.UID).ToList();
|
private List<string> OnlineAdmins => _dbContext.Users.Where(u => (u.IsModerator || u.IsAdmin)).Select(u => u.UID).ToList();
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Admin")]
|
||||||
public async Task AdminChangeModeratorStatus(string uid, bool isModerator)
|
public async Task AdminChangeModeratorStatus(string uid, bool isModerator)
|
||||||
{
|
{
|
||||||
if (!IsAdmin) return;
|
|
||||||
var user = await _dbContext.Users.SingleOrDefaultAsync(u => u.UID == uid).ConfigureAwait(false);
|
var user = await _dbContext.Users.SingleOrDefaultAsync(u => u.UID == uid).ConfigureAwait(false);
|
||||||
|
|
||||||
if (user == null) return;
|
if (user == null) return;
|
||||||
@@ -32,10 +26,10 @@ public partial class MareHub
|
|||||||
await Clients.Users(user.UID).Client_AdminForcedReconnect().ConfigureAwait(false);
|
await Clients.Users(user.UID).Client_AdminForcedReconnect().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Moderator")]
|
||||||
public async Task AdminDeleteBannedUser(BannedUserDto dto)
|
public async Task AdminDeleteBannedUser(BannedUserDto dto)
|
||||||
{
|
{
|
||||||
if (!IsModerator || string.IsNullOrEmpty(dto.CharacterHash)) return;
|
if (string.IsNullOrEmpty(dto.CharacterHash)) return;
|
||||||
|
|
||||||
var existingUser =
|
var existingUser =
|
||||||
await _dbContext.BannedUsers.SingleOrDefaultAsync(b => b.CharacterIdentification == dto.CharacterHash).ConfigureAwait(false);
|
await _dbContext.BannedUsers.SingleOrDefaultAsync(b => b.CharacterIdentification == dto.CharacterHash).ConfigureAwait(false);
|
||||||
@@ -49,10 +43,10 @@ public partial class MareHub
|
|||||||
await Clients.Users(OnlineAdmins).Client_AdminDeleteBannedUser(dto).ConfigureAwait(false);
|
await Clients.Users(OnlineAdmins).Client_AdminDeleteBannedUser(dto).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Admin")]
|
||||||
public async Task AdminDeleteForbiddenFile(ForbiddenFileDto dto)
|
public async Task AdminDeleteForbiddenFile(ForbiddenFileDto dto)
|
||||||
{
|
{
|
||||||
if (!IsAdmin || string.IsNullOrEmpty(dto.Hash)) return;
|
if (string.IsNullOrEmpty(dto.Hash)) return;
|
||||||
|
|
||||||
var existingFile =
|
var existingFile =
|
||||||
await _dbContext.ForbiddenUploadEntries.SingleOrDefaultAsync(b => b.Hash == dto.Hash).ConfigureAwait(false);
|
await _dbContext.ForbiddenUploadEntries.SingleOrDefaultAsync(b => b.Hash == dto.Hash).ConfigureAwait(false);
|
||||||
@@ -66,11 +60,9 @@ public partial class MareHub
|
|||||||
await Clients.Users(OnlineAdmins).Client_AdminDeleteForbiddenFile(dto).ConfigureAwait(false);
|
await Clients.Users(OnlineAdmins).Client_AdminDeleteForbiddenFile(dto).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Moderator")]
|
||||||
public async Task<List<BannedUserDto>> AdminGetBannedUsers()
|
public async Task<List<BannedUserDto>> AdminGetBannedUsers()
|
||||||
{
|
{
|
||||||
if (!IsModerator) return null;
|
|
||||||
|
|
||||||
return await _dbContext.BannedUsers.AsNoTracking().Select(b => new BannedUserDto()
|
return await _dbContext.BannedUsers.AsNoTracking().Select(b => new BannedUserDto()
|
||||||
{
|
{
|
||||||
CharacterHash = b.CharacterIdentification,
|
CharacterHash = b.CharacterIdentification,
|
||||||
@@ -78,11 +70,9 @@ public partial class MareHub
|
|||||||
}).ToListAsync().ConfigureAwait(false);
|
}).ToListAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Moderator")]
|
||||||
public async Task<List<ForbiddenFileDto>> AdminGetForbiddenFiles()
|
public async Task<List<ForbiddenFileDto>> AdminGetForbiddenFiles()
|
||||||
{
|
{
|
||||||
if (!IsModerator) return null;
|
|
||||||
|
|
||||||
return await _dbContext.ForbiddenUploadEntries.AsNoTracking().Select(b => new ForbiddenFileDto()
|
return await _dbContext.ForbiddenUploadEntries.AsNoTracking().Select(b => new ForbiddenFileDto()
|
||||||
{
|
{
|
||||||
Hash = b.Hash,
|
Hash = b.Hash,
|
||||||
@@ -90,11 +80,9 @@ public partial class MareHub
|
|||||||
}).ToListAsync().ConfigureAwait(false);
|
}).ToListAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Moderator")]
|
||||||
public async Task<List<OnlineUserDto>> AdminGetOnlineUsers()
|
public async Task<List<OnlineUserDto>> AdminGetOnlineUsers()
|
||||||
{
|
{
|
||||||
if (!IsModerator) return null;
|
|
||||||
|
|
||||||
var users = await _dbContext.Users.AsNoTracking().ToListAsync().ConfigureAwait(false);
|
var users = await _dbContext.Users.AsNoTracking().ToListAsync().ConfigureAwait(false);
|
||||||
return users.Where(c => !string.IsNullOrEmpty(_clientIdentService.GetCharacterIdentForUid(c.UID))).Select(b => new OnlineUserDto
|
return users.Where(c => !string.IsNullOrEmpty(_clientIdentService.GetCharacterIdentForUid(c.UID))).Select(b => new OnlineUserDto
|
||||||
{
|
{
|
||||||
@@ -105,10 +93,10 @@ public partial class MareHub
|
|||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Moderator")]
|
||||||
public async Task AdminUpdateOrAddBannedUser(BannedUserDto dto)
|
public async Task AdminUpdateOrAddBannedUser(BannedUserDto dto)
|
||||||
{
|
{
|
||||||
if (!IsModerator || string.IsNullOrEmpty(dto.CharacterHash)) return;
|
if (string.IsNullOrEmpty(dto.CharacterHash)) return;
|
||||||
|
|
||||||
var existingUser =
|
var existingUser =
|
||||||
await _dbContext.BannedUsers.SingleOrDefaultAsync(b => b.CharacterIdentification == dto.CharacterHash).ConfigureAwait(false);
|
await _dbContext.BannedUsers.SingleOrDefaultAsync(b => b.CharacterIdentification == dto.CharacterHash).ConfigureAwait(false);
|
||||||
@@ -135,10 +123,10 @@ public partial class MareHub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Admin")]
|
||||||
public async Task AdminUpdateOrAddForbiddenFile(ForbiddenFileDto dto)
|
public async Task AdminUpdateOrAddForbiddenFile(ForbiddenFileDto dto)
|
||||||
{
|
{
|
||||||
if (!IsAdmin || string.IsNullOrEmpty(dto.Hash)) return;
|
if (string.IsNullOrEmpty(dto.Hash)) return;
|
||||||
|
|
||||||
var existingForbiddenFile =
|
var existingForbiddenFile =
|
||||||
await _dbContext.ForbiddenUploadEntries.SingleOrDefaultAsync(b => b.Hash == dto.Hash).ConfigureAwait(false);
|
await _dbContext.ForbiddenUploadEntries.SingleOrDefaultAsync(b => b.Hash == dto.Hash).ConfigureAwait(false);
|
||||||
|
|||||||
@@ -9,19 +9,16 @@ using Google.Protobuf;
|
|||||||
using Grpc.Core;
|
using Grpc.Core;
|
||||||
using MareSynchronos.API;
|
using MareSynchronos.API;
|
||||||
using MareSynchronosServer.Utils;
|
using MareSynchronosServer.Utils;
|
||||||
using MareSynchronosShared.Authentication;
|
|
||||||
using MareSynchronosShared.Models;
|
using MareSynchronosShared.Models;
|
||||||
using MareSynchronosShared.Protos;
|
using MareSynchronosShared.Protos;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace MareSynchronosServer.Hubs;
|
namespace MareSynchronosServer.Hubs;
|
||||||
|
|
||||||
public partial class MareHub
|
public partial class MareHub
|
||||||
{
|
{
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task FilesAbortUpload()
|
public async Task FilesAbortUpload()
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo();
|
_logger.LogCallInfo();
|
||||||
@@ -31,7 +28,7 @@ public partial class MareHub
|
|||||||
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
|
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task FilesDeleteAll()
|
public async Task FilesDeleteAll()
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo();
|
_logger.LogCallInfo();
|
||||||
@@ -46,7 +43,7 @@ public partial class MareHub
|
|||||||
_ = await _fileServiceClient.DeleteFilesAsync(request, headers).ConfigureAwait(false);
|
_ = await _fileServiceClient.DeleteFilesAsync(request, headers).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task<List<DownloadFileDto>> FilesGetSizes(List<string> hashes)
|
public async Task<List<DownloadFileDto>> FilesGetSizes(List<string> hashes)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(hashes.Count.ToString()));
|
_logger.LogCallInfo(MareHubLogger.Args(hashes.Count.ToString()));
|
||||||
@@ -83,7 +80,7 @@ public partial class MareHub
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task<bool> FilesIsUploadFinished()
|
public async Task<bool> FilesIsUploadFinished()
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo();
|
_logger.LogCallInfo();
|
||||||
@@ -92,7 +89,7 @@ public partial class MareHub
|
|||||||
.AnyAsync(f => f.Uploader.UID == userUid && !f.Uploaded).ConfigureAwait(false);
|
.AnyAsync(f => f.Uploader.UID == userUid && !f.Uploaded).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task<List<UploadFileDto>> FilesSend(List<string> fileListHashes)
|
public async Task<List<UploadFileDto>> FilesSend(List<string> fileListHashes)
|
||||||
{
|
{
|
||||||
var userSentHashes = new HashSet<string>(fileListHashes.Distinct(StringComparer.Ordinal), StringComparer.Ordinal);
|
var userSentHashes = new HashSet<string>(fileListHashes.Distinct(StringComparer.Ordinal), StringComparer.Ordinal);
|
||||||
@@ -142,7 +139,7 @@ public partial class MareHub
|
|||||||
return notCoveredFiles.Values.ToList();
|
return notCoveredFiles.Values.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task FilesUploadStreamAsync(string hash, IAsyncEnumerable<byte[]> fileContent)
|
public async Task FilesUploadStreamAsync(string hash, IAsyncEnumerable<byte[]> fileContent)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(hash));
|
_logger.LogCallInfo(MareHubLogger.Args(hash));
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace MareSynchronosServer.Hubs;
|
|||||||
|
|
||||||
public partial class MareHub
|
public partial class MareHub
|
||||||
{
|
{
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task<GroupCreatedDto> GroupCreate()
|
public async Task<GroupCreatedDto> GroupCreate()
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo();
|
_logger.LogCallInfo();
|
||||||
@@ -78,7 +78,7 @@ public partial class MareHub
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task<List<GroupDto>> GroupsGetAll()
|
public async Task<List<GroupDto>> GroupsGetAll()
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo();
|
_logger.LogCallInfo();
|
||||||
@@ -96,7 +96,7 @@ public partial class MareHub
|
|||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task<List<GroupPairDto>> GroupsGetUsersInGroup(string gid)
|
public async Task<List<GroupPairDto>> GroupsGetUsersInGroup(string gid)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(gid));
|
_logger.LogCallInfo(MareHubLogger.Args(gid));
|
||||||
@@ -117,7 +117,7 @@ public partial class MareHub
|
|||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task GroupChangeInviteState(string gid, bool enabled)
|
public async Task GroupChangeInviteState(string gid, bool enabled)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(gid, enabled.ToString()));
|
_logger.LogCallInfo(MareHubLogger.Args(gid, enabled.ToString()));
|
||||||
@@ -138,7 +138,7 @@ public partial class MareHub
|
|||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task GroupDelete(string gid)
|
public async Task GroupDelete(string gid)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(gid));
|
_logger.LogCallInfo(MareHubLogger.Args(gid));
|
||||||
@@ -162,7 +162,7 @@ public partial class MareHub
|
|||||||
await SendGroupDeletedToAll(groupPairs).ConfigureAwait(false);
|
await SendGroupDeletedToAll(groupPairs).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task<bool> GroupJoin(string gid, string password)
|
public async Task<bool> GroupJoin(string gid, string password)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(gid));
|
_logger.LogCallInfo(MareHubLogger.Args(gid));
|
||||||
@@ -239,7 +239,7 @@ public partial class MareHub
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task GroupLeave(string gid)
|
public async Task GroupLeave(string gid)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(gid));
|
_logger.LogCallInfo(MareHubLogger.Args(gid));
|
||||||
@@ -322,7 +322,7 @@ public partial class MareHub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task GroupChangePauseState(string gid, bool isPaused)
|
public async Task GroupChangePauseState(string gid, bool isPaused)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(gid, isPaused));
|
_logger.LogCallInfo(MareHubLogger.Args(gid, isPaused));
|
||||||
@@ -370,7 +370,7 @@ public partial class MareHub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task GroupRemoveUser(string gid, string uid)
|
public async Task GroupRemoveUser(string gid, string uid)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(gid, uid));
|
_logger.LogCallInfo(MareHubLogger.Args(gid, uid));
|
||||||
@@ -412,7 +412,7 @@ public partial class MareHub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task GroupBanUser(string gid, string uid, string reason)
|
public async Task GroupBanUser(string gid, string uid, string reason)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(gid, uid));
|
_logger.LogCallInfo(MareHubLogger.Args(gid, uid));
|
||||||
@@ -443,7 +443,7 @@ public partial class MareHub
|
|||||||
_logger.LogCallInfo(MareHubLogger.Args(gid, uid, "Success"));
|
_logger.LogCallInfo(MareHubLogger.Args(gid, uid, "Success"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task GroupUnbanUser(string gid, string uid)
|
public async Task GroupUnbanUser(string gid, string uid)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(gid, uid));
|
_logger.LogCallInfo(MareHubLogger.Args(gid, uid));
|
||||||
@@ -484,7 +484,7 @@ public partial class MareHub
|
|||||||
return bannedGroupUsers;
|
return bannedGroupUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task GroupSetModerator(string gid, string uid, bool isGroupModerator)
|
public async Task GroupSetModerator(string gid, string uid, bool isGroupModerator)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(gid, uid, isGroupModerator));
|
_logger.LogCallInfo(MareHubLogger.Args(gid, uid, isGroupModerator));
|
||||||
@@ -517,7 +517,7 @@ public partial class MareHub
|
|||||||
_logger.LogCallInfo(MareHubLogger.Args(gid, uid, isGroupModerator, "Success"));
|
_logger.LogCallInfo(MareHubLogger.Args(gid, uid, isGroupModerator, "Success"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task GroupChangeOwnership(string gid, string uid)
|
public async Task GroupChangeOwnership(string gid, string uid)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(gid, uid));
|
_logger.LogCallInfo(MareHubLogger.Args(gid, uid));
|
||||||
@@ -567,7 +567,7 @@ public partial class MareHub
|
|||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task<bool> GroupChangePassword(string gid, string password)
|
public async Task<bool> GroupChangePassword(string gid, string password)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(gid));
|
_logger.LogCallInfo(MareHubLogger.Args(gid));
|
||||||
@@ -583,7 +583,7 @@ public partial class MareHub
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task GroupChangePinned(string gid, string uid, bool isPinned)
|
public async Task GroupChangePinned(string gid, string uid, bool isPinned)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(gid, uid, isPinned));
|
_logger.LogCallInfo(MareHubLogger.Args(gid, uid, isPinned));
|
||||||
@@ -609,7 +609,7 @@ public partial class MareHub
|
|||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task GroupClear(string gid)
|
public async Task GroupClear(string gid)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(gid));
|
_logger.LogCallInfo(MareHubLogger.Args(gid));
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace MareSynchronosServer.Hubs;
|
|||||||
|
|
||||||
public partial class MareHub
|
public partial class MareHub
|
||||||
{
|
{
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task UserDelete()
|
public async Task UserDelete()
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo();
|
_logger.LogCallInfo();
|
||||||
@@ -66,7 +66,7 @@ public partial class MareHub
|
|||||||
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
|
await _dbContext.SaveChangesAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task<List<string>> UserGetOnlineCharacters()
|
public async Task<List<string>> UserGetOnlineCharacters()
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo();
|
_logger.LogCallInfo();
|
||||||
@@ -77,7 +77,7 @@ public partial class MareHub
|
|||||||
return usersToSendOnlineTo.Select(e => _clientIdentService.GetCharacterIdentForUid(e)).Where(t => !string.IsNullOrEmpty(t)).Distinct(System.StringComparer.Ordinal).ToList();
|
return usersToSendOnlineTo.Select(e => _clientIdentService.GetCharacterIdentForUid(e)).Where(t => !string.IsNullOrEmpty(t)).Distinct(System.StringComparer.Ordinal).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task<List<ClientPairDto>> UserGetPairedClients()
|
public async Task<List<ClientPairDto>> UserGetPairedClients()
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo();
|
_logger.LogCallInfo();
|
||||||
@@ -118,7 +118,7 @@ public partial class MareHub
|
|||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task UserPushData(CharacterCacheDto characterCache, List<string> visibleCharacterIds)
|
public async Task UserPushData(CharacterCacheDto characterCache, List<string> visibleCharacterIds)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(visibleCharacterIds.Count));
|
_logger.LogCallInfo(MareHubLogger.Args(visibleCharacterIds.Count));
|
||||||
@@ -138,7 +138,7 @@ public partial class MareHub
|
|||||||
_mareMetrics.IncCounter(MetricsAPI.CounterUserPushDataTo, allPairedUsersDict.Count());
|
_mareMetrics.IncCounter(MetricsAPI.CounterUserPushDataTo, allPairedUsersDict.Count());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task UserAddPair(string uid)
|
public async Task UserAddPair(string uid)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(uid));
|
_logger.LogCallInfo(MareHubLogger.Args(uid));
|
||||||
@@ -211,7 +211,7 @@ public partial class MareHub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task UserChangePairPauseStatus(string otherUserUid, bool isPaused)
|
public async Task UserChangePairPauseStatus(string otherUserUid, bool isPaused)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(otherUserUid, isPaused));
|
_logger.LogCallInfo(MareHubLogger.Args(otherUserUid, isPaused));
|
||||||
@@ -256,7 +256,7 @@ public partial class MareHub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Identified")]
|
||||||
public async Task UserRemovePair(string otherUserUid)
|
public async Task UserRemovePair(string otherUserUid)
|
||||||
{
|
{
|
||||||
_logger.LogCallInfo(MareHubLogger.Args(otherUserUid));
|
_logger.LogCallInfo(MareHubLogger.Args(otherUserUid));
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
|
|
||||||
namespace MareSynchronosServer.Hubs;
|
namespace MareSynchronosServer.Hubs;
|
||||||
|
|
||||||
|
[Authorize]
|
||||||
public partial class MareHub : Hub<IMareHub>, IMareHub
|
public partial class MareHub : Hub<IMareHub>, IMareHub
|
||||||
{
|
{
|
||||||
private readonly MareMetrics _mareMetrics;
|
private readonly MareMetrics _mareMetrics;
|
||||||
@@ -54,7 +55,7 @@ public partial class MareHub : Hub<IMareHub>, IMareHub
|
|||||||
_dbContext = mareDbContext;
|
_dbContext = mareDbContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Authenticated")]
|
||||||
public async Task<ConnectionDto> Heartbeat(string characterIdentification)
|
public async Task<ConnectionDto> Heartbeat(string characterIdentification)
|
||||||
{
|
{
|
||||||
_mareMetrics.IncCounter(MetricsAPI.CounterInitializedConnections);
|
_mareMetrics.IncCounter(MetricsAPI.CounterInitializedConnections);
|
||||||
@@ -111,14 +112,12 @@ public partial class MareHub : Hub<IMareHub>, IMareHub
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)]
|
[Authorize(Policy = "Authenticated")]
|
||||||
public async Task<bool> CheckClientHealth()
|
public async Task<bool> CheckClientHealth()
|
||||||
{
|
{
|
||||||
var serverId = _clientIdentService.GetServerForUid(AuthenticatedUserId);
|
var needsReconnect = !_clientIdentService.IsOnCurrentServer(AuthenticatedUserId);
|
||||||
bool needsReconnect = false;
|
if (needsReconnect)
|
||||||
if (string.IsNullOrEmpty(serverId) || !string.Equals(serverId, _shardName, StringComparison.Ordinal))
|
|
||||||
{
|
{
|
||||||
needsReconnect = true;
|
|
||||||
_logger.LogCallWarning(MareHubLogger.Args(needsReconnect));
|
_logger.LogCallWarning(MareHubLogger.Args(needsReconnect));
|
||||||
}
|
}
|
||||||
return needsReconnect;
|
return needsReconnect;
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.RequirementHandlers;
|
||||||
|
|
||||||
|
public class UserRequirement : IAuthorizationRequirement
|
||||||
|
{
|
||||||
|
public UserRequirement(UserRequirements requirements)
|
||||||
|
{
|
||||||
|
Requirements = requirements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserRequirements Requirements { get; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using MareSynchronosShared.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using MareSynchronosServer.Services;
|
||||||
|
|
||||||
|
namespace MareSynchronosServer.RequirementHandlers;
|
||||||
|
|
||||||
|
public class UserRequirementHandler : AuthorizationHandler<UserRequirement, HubInvocationContext>
|
||||||
|
{
|
||||||
|
private readonly GrpcClientIdentificationService identClient;
|
||||||
|
private readonly MareDbContext dbContext;
|
||||||
|
private readonly ILogger<UserRequirementHandler> logger;
|
||||||
|
|
||||||
|
public UserRequirementHandler(GrpcClientIdentificationService identClient, MareDbContext dbContext, ILogger<UserRequirementHandler> logger)
|
||||||
|
{
|
||||||
|
this.identClient = identClient;
|
||||||
|
this.dbContext = dbContext;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, UserRequirement requirement, HubInvocationContext resource)
|
||||||
|
{
|
||||||
|
var uid = context.User.Claims.SingleOrDefault(g => string.Equals(g.Type, ClaimTypes.NameIdentifier, StringComparison.Ordinal))?.Value;
|
||||||
|
var auth = context.User.Claims.SingleOrDefault(g => string.Equals(g.Type, ClaimTypes.Authentication, StringComparison.Ordinal))?.Value;
|
||||||
|
|
||||||
|
if (uid == null || auth == null) context.Fail();
|
||||||
|
|
||||||
|
if ((requirement.Requirements & UserRequirements.Identified) is UserRequirements.Identified)
|
||||||
|
{
|
||||||
|
var ident = identClient.GetCharacterIdentForUid(uid);
|
||||||
|
if (ident == null) context.Fail();
|
||||||
|
|
||||||
|
var isOnCurrent = identClient.IsOnCurrentServer(uid);
|
||||||
|
if (!isOnCurrent) identClient.MarkUserOnline(uid, ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((requirement.Requirements & UserRequirements.Administrator) is UserRequirements.Administrator)
|
||||||
|
{
|
||||||
|
var user = await dbContext.Users.AsNoTracking().SingleOrDefaultAsync(b => b.UID == uid).ConfigureAwait(false);
|
||||||
|
if (user == null || !user.IsAdmin) context.Fail();
|
||||||
|
logger.LogInformation("Admin {uid} authenticated", uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((requirement.Requirements & UserRequirements.Moderator) is UserRequirements.Moderator)
|
||||||
|
{
|
||||||
|
var user = await dbContext.Users.AsNoTracking().SingleOrDefaultAsync(b => b.UID == uid).ConfigureAwait(false);
|
||||||
|
if (user == null || !user.IsAdmin && !user.IsModerator) context.Fail();
|
||||||
|
logger.LogInformation("Admin/Moderator {uid} authenticated", uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Succeed(requirement);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace MareSynchronosServer.RequirementHandlers;
|
||||||
|
|
||||||
|
public enum UserRequirements
|
||||||
|
{
|
||||||
|
Identified = 0b00000001,
|
||||||
|
Moderator = 0b00000010,
|
||||||
|
Administrator = 0b00000100
|
||||||
|
}
|
||||||
@@ -40,6 +40,11 @@ public class GrpcClientIdentificationService : IHostedService
|
|||||||
_metrics = metrics;
|
_metrics = metrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsOnCurrentServer(string uid)
|
||||||
|
{
|
||||||
|
return OnlineClients.ContainsKey(uid);
|
||||||
|
}
|
||||||
|
|
||||||
public string? GetCharacterIdentForUid(string uid)
|
public string? GetCharacterIdentForUid(string uid)
|
||||||
{
|
{
|
||||||
if (OnlineClients.TryGetValue(uid, out var ident))
|
if (OnlineClients.TryGetValue(uid, out var ident))
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ using System.Collections.Generic;
|
|||||||
using MareSynchronosServer.Services;
|
using MareSynchronosServer.Services;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using MareSynchronosServer.Utils;
|
using MareSynchronosServer.Utils;
|
||||||
|
using MareSynchronosServer.RequirementHandlers;
|
||||||
|
|
||||||
namespace MareSynchronosServer;
|
namespace MareSynchronosServer;
|
||||||
|
|
||||||
@@ -119,6 +120,7 @@ public class Startup
|
|||||||
});
|
});
|
||||||
|
|
||||||
services.AddSingleton<GrpcClientIdentificationService>();
|
services.AddSingleton<GrpcClientIdentificationService>();
|
||||||
|
services.AddTransient<IAuthorizationHandler, UserRequirementHandler>();
|
||||||
services.AddHostedService(p => p.GetService<GrpcClientIdentificationService>());
|
services.AddHostedService(p => p.GetService<GrpcClientIdentificationService>());
|
||||||
|
|
||||||
services.AddDbContextPool<MareDbContext>(options =>
|
services.AddDbContextPool<MareDbContext>(options =>
|
||||||
@@ -131,11 +133,32 @@ public class Startup
|
|||||||
options.EnableThreadSafetyChecks(false);
|
options.EnableThreadSafetyChecks(false);
|
||||||
}, mareConfig.GetValue("DbContextPoolSize", 1024));
|
}, mareConfig.GetValue("DbContextPoolSize", 1024));
|
||||||
|
|
||||||
services.AddAuthentication(options =>
|
services.AddAuthentication(SecretKeyGrpcAuthenticationHandler.AuthScheme)
|
||||||
|
.AddScheme<AuthenticationSchemeOptions, SecretKeyGrpcAuthenticationHandler>(SecretKeyGrpcAuthenticationHandler.AuthScheme, options => { options.Validate(); });
|
||||||
|
|
||||||
|
services.AddAuthorization(options =>
|
||||||
{
|
{
|
||||||
options.DefaultScheme = SecretKeyGrpcAuthenticationHandler.AuthScheme;
|
options.DefaultPolicy = new AuthorizationPolicyBuilder()
|
||||||
}).AddScheme<AuthenticationSchemeOptions, SecretKeyGrpcAuthenticationHandler>(SecretKeyGrpcAuthenticationHandler.AuthScheme, _ => { });
|
.AddAuthenticationSchemes(SecretKeyGrpcAuthenticationHandler.AuthScheme)
|
||||||
services.AddAuthorization(options => options.FallbackPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build());
|
.RequireAuthenticatedUser().Build();
|
||||||
|
options.AddPolicy("Authenticated", policy =>
|
||||||
|
{
|
||||||
|
policy.AddAuthenticationSchemes(SecretKeyGrpcAuthenticationHandler.AuthScheme);
|
||||||
|
policy.RequireAuthenticatedUser();
|
||||||
|
});
|
||||||
|
options.AddPolicy("Identified", policy =>
|
||||||
|
{
|
||||||
|
policy.AddRequirements(new UserRequirement(UserRequirements.Identified));
|
||||||
|
});
|
||||||
|
options.AddPolicy("Admin", policy =>
|
||||||
|
{
|
||||||
|
policy.AddRequirements(new UserRequirement(UserRequirements.Identified | UserRequirements.Administrator));
|
||||||
|
});
|
||||||
|
options.AddPolicy("Moderator", policy =>
|
||||||
|
{
|
||||||
|
policy.AddRequirements(new UserRequirement(UserRequirements.Identified | UserRequirements.Moderator | UserRequirements.Administrator));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
|
services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
|
||||||
|
|
||||||
|
|||||||
@@ -26,20 +26,21 @@ public class SecretKeyGrpcAuthenticationHandler : AuthenticationHandler<Authenti
|
|||||||
|
|
||||||
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||||
{
|
{
|
||||||
if(!Request.Headers.TryGetValue("Authorization", out var authHeader))
|
if (!Request.Headers.TryGetValue("Authorization", out var authHeader))
|
||||||
{
|
{
|
||||||
authHeader = string.Empty;
|
authHeader = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ip = _accessor.GetIpAddress();
|
var ip = _accessor.GetIpAddress();
|
||||||
|
|
||||||
var authResult = await _authClient.AuthorizeAsync(new AuthRequest() {Ip = ip, SecretKey = authHeader}).ConfigureAwait(false);
|
var authResult = await _authClient.AuthorizeAsync(new AuthRequest() { Ip = ip, SecretKey = authHeader }).ConfigureAwait(false);
|
||||||
|
|
||||||
if (!authResult.Success)
|
if (!authResult.Success)
|
||||||
{
|
{
|
||||||
return AuthenticateResult.Fail("Failed Authorization");
|
return AuthenticateResult.Fail("Failed Authorization");
|
||||||
}
|
}
|
||||||
|
|
||||||
string uid = authResult.Uid;
|
var uid = authResult.Uid;
|
||||||
|
|
||||||
var claims = new List<Claim>
|
var claims = new List<Claim>
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user