diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Admin.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Admin.cs index e4305e3..a910470 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Admin.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Admin.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading.Tasks; using MareSynchronos.API; -using MareSynchronosShared.Authentication; using MareSynchronosShared.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.SignalR; @@ -12,16 +11,11 @@ namespace MareSynchronosServer.Hubs; 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 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) { - if (!IsAdmin) return; var user = await _dbContext.Users.SingleOrDefaultAsync(u => u.UID == uid).ConfigureAwait(false); if (user == null) return; @@ -32,10 +26,10 @@ public partial class MareHub await Clients.Users(user.UID).Client_AdminForcedReconnect().ConfigureAwait(false); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Moderator")] public async Task AdminDeleteBannedUser(BannedUserDto dto) { - if (!IsModerator || string.IsNullOrEmpty(dto.CharacterHash)) return; + if (string.IsNullOrEmpty(dto.CharacterHash)) return; var existingUser = 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); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Admin")] public async Task AdminDeleteForbiddenFile(ForbiddenFileDto dto) { - if (!IsAdmin || string.IsNullOrEmpty(dto.Hash)) return; + if (string.IsNullOrEmpty(dto.Hash)) return; var existingFile = 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); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Moderator")] public async Task> AdminGetBannedUsers() { - if (!IsModerator) return null; - return await _dbContext.BannedUsers.AsNoTracking().Select(b => new BannedUserDto() { CharacterHash = b.CharacterIdentification, @@ -78,11 +70,9 @@ public partial class MareHub }).ToListAsync().ConfigureAwait(false); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Moderator")] public async Task> AdminGetForbiddenFiles() { - if (!IsModerator) return null; - return await _dbContext.ForbiddenUploadEntries.AsNoTracking().Select(b => new ForbiddenFileDto() { Hash = b.Hash, @@ -90,11 +80,9 @@ public partial class MareHub }).ToListAsync().ConfigureAwait(false); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Moderator")] public async Task> AdminGetOnlineUsers() { - if (!IsModerator) return null; - var users = await _dbContext.Users.AsNoTracking().ToListAsync().ConfigureAwait(false); return users.Where(c => !string.IsNullOrEmpty(_clientIdentService.GetCharacterIdentForUid(c.UID))).Select(b => new OnlineUserDto { @@ -105,10 +93,10 @@ public partial class MareHub }).ToList(); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Moderator")] public async Task AdminUpdateOrAddBannedUser(BannedUserDto dto) { - if (!IsModerator || string.IsNullOrEmpty(dto.CharacterHash)) return; + if (string.IsNullOrEmpty(dto.CharacterHash)) return; var existingUser = 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) { - if (!IsAdmin || string.IsNullOrEmpty(dto.Hash)) return; + if (string.IsNullOrEmpty(dto.Hash)) return; var existingForbiddenFile = await _dbContext.ForbiddenUploadEntries.SingleOrDefaultAsync(b => b.Hash == dto.Hash).ConfigureAwait(false); diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Files.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Files.cs index 9ae39ff..3056438 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Files.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Files.cs @@ -9,19 +9,16 @@ using Google.Protobuf; using Grpc.Core; using MareSynchronos.API; using MareSynchronosServer.Utils; -using MareSynchronosShared.Authentication; using MareSynchronosShared.Models; using MareSynchronosShared.Protos; using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.SignalR; using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; namespace MareSynchronosServer.Hubs; public partial class MareHub { - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task FilesAbortUpload() { _logger.LogCallInfo(); @@ -31,7 +28,7 @@ public partial class MareHub await _dbContext.SaveChangesAsync().ConfigureAwait(false); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task FilesDeleteAll() { _logger.LogCallInfo(); @@ -46,7 +43,7 @@ public partial class MareHub _ = await _fileServiceClient.DeleteFilesAsync(request, headers).ConfigureAwait(false); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task> FilesGetSizes(List hashes) { _logger.LogCallInfo(MareHubLogger.Args(hashes.Count.ToString())); @@ -83,7 +80,7 @@ public partial class MareHub return response; } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task FilesIsUploadFinished() { _logger.LogCallInfo(); @@ -92,7 +89,7 @@ public partial class MareHub .AnyAsync(f => f.Uploader.UID == userUid && !f.Uploaded).ConfigureAwait(false); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task> FilesSend(List fileListHashes) { var userSentHashes = new HashSet(fileListHashes.Distinct(StringComparer.Ordinal), StringComparer.Ordinal); @@ -142,7 +139,7 @@ public partial class MareHub return notCoveredFiles.Values.ToList(); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task FilesUploadStreamAsync(string hash, IAsyncEnumerable fileContent) { _logger.LogCallInfo(MareHubLogger.Args(hash)); diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Groups.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Groups.cs index 4823e9d..42ade3a 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Groups.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.Groups.cs @@ -16,7 +16,7 @@ namespace MareSynchronosServer.Hubs; public partial class MareHub { - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task GroupCreate() { _logger.LogCallInfo(); @@ -78,7 +78,7 @@ public partial class MareHub }; } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task> GroupsGetAll() { _logger.LogCallInfo(); @@ -96,7 +96,7 @@ public partial class MareHub }).ToList(); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task> GroupsGetUsersInGroup(string gid) { _logger.LogCallInfo(MareHubLogger.Args(gid)); @@ -117,7 +117,7 @@ public partial class MareHub }).ToList(); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task GroupChangeInviteState(string gid, bool enabled) { _logger.LogCallInfo(MareHubLogger.Args(gid, enabled.ToString())); @@ -138,7 +138,7 @@ public partial class MareHub }).ConfigureAwait(false); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task GroupDelete(string gid) { _logger.LogCallInfo(MareHubLogger.Args(gid)); @@ -162,7 +162,7 @@ public partial class MareHub await SendGroupDeletedToAll(groupPairs).ConfigureAwait(false); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task GroupJoin(string gid, string password) { _logger.LogCallInfo(MareHubLogger.Args(gid)); @@ -239,7 +239,7 @@ public partial class MareHub return true; } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task GroupLeave(string 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) { _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) { _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) { _logger.LogCallInfo(MareHubLogger.Args(gid, uid)); @@ -443,7 +443,7 @@ public partial class MareHub _logger.LogCallInfo(MareHubLogger.Args(gid, uid, "Success")); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task GroupUnbanUser(string gid, string uid) { _logger.LogCallInfo(MareHubLogger.Args(gid, uid)); @@ -484,7 +484,7 @@ public partial class MareHub return bannedGroupUsers; } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task GroupSetModerator(string gid, string uid, bool isGroupModerator) { _logger.LogCallInfo(MareHubLogger.Args(gid, uid, isGroupModerator)); @@ -517,7 +517,7 @@ public partial class MareHub _logger.LogCallInfo(MareHubLogger.Args(gid, uid, isGroupModerator, "Success")); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task GroupChangeOwnership(string gid, string uid) { _logger.LogCallInfo(MareHubLogger.Args(gid, uid)); @@ -567,7 +567,7 @@ public partial class MareHub }).ConfigureAwait(false); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task GroupChangePassword(string gid, string password) { _logger.LogCallInfo(MareHubLogger.Args(gid)); @@ -583,7 +583,7 @@ public partial class MareHub return true; } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task GroupChangePinned(string gid, string uid, bool isPinned) { _logger.LogCallInfo(MareHubLogger.Args(gid, uid, isPinned)); @@ -609,7 +609,7 @@ public partial class MareHub }).ConfigureAwait(false); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task GroupClear(string gid) { _logger.LogCallInfo(MareHubLogger.Args(gid)); diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs index b10a49a..f0f38b3 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.User.cs @@ -15,7 +15,7 @@ namespace MareSynchronosServer.Hubs; public partial class MareHub { - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task UserDelete() { _logger.LogCallInfo(); @@ -66,7 +66,7 @@ public partial class MareHub await _dbContext.SaveChangesAsync().ConfigureAwait(false); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task> UserGetOnlineCharacters() { _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(); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task> UserGetPairedClients() { _logger.LogCallInfo(); @@ -118,7 +118,7 @@ public partial class MareHub }).ToList(); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task UserPushData(CharacterCacheDto characterCache, List visibleCharacterIds) { _logger.LogCallInfo(MareHubLogger.Args(visibleCharacterIds.Count)); @@ -138,7 +138,7 @@ public partial class MareHub _mareMetrics.IncCounter(MetricsAPI.CounterUserPushDataTo, allPairedUsersDict.Count()); } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Identified")] public async Task UserAddPair(string 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) { _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) { _logger.LogCallInfo(MareHubLogger.Args(otherUserUid)); diff --git a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs index b1eb543..4ddfc17 100644 --- a/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs +++ b/MareSynchronosServer/MareSynchronosServer/Hubs/MareHub.cs @@ -18,6 +18,7 @@ using Microsoft.Extensions.Logging; namespace MareSynchronosServer.Hubs; +[Authorize] public partial class MareHub : Hub, IMareHub { private readonly MareMetrics _mareMetrics; @@ -54,7 +55,7 @@ public partial class MareHub : Hub, IMareHub _dbContext = mareDbContext; } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Authenticated")] public async Task Heartbeat(string characterIdentification) { _mareMetrics.IncCounter(MetricsAPI.CounterInitializedConnections); @@ -111,14 +112,12 @@ public partial class MareHub : Hub, IMareHub }; } - [Authorize(AuthenticationSchemes = SecretKeyGrpcAuthenticationHandler.AuthScheme)] + [Authorize(Policy = "Authenticated")] public async Task CheckClientHealth() { - var serverId = _clientIdentService.GetServerForUid(AuthenticatedUserId); - bool needsReconnect = false; - if (string.IsNullOrEmpty(serverId) || !string.Equals(serverId, _shardName, StringComparison.Ordinal)) + var needsReconnect = !_clientIdentService.IsOnCurrentServer(AuthenticatedUserId); + if (needsReconnect) { - needsReconnect = true; _logger.LogCallWarning(MareHubLogger.Args(needsReconnect)); } return needsReconnect; diff --git a/MareSynchronosServer/MareSynchronosServer/RequirementHandlers/UserRequirement.cs b/MareSynchronosServer/MareSynchronosServer/RequirementHandlers/UserRequirement.cs new file mode 100644 index 0000000..bb7442b --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/RequirementHandlers/UserRequirement.cs @@ -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; } +} diff --git a/MareSynchronosServer/MareSynchronosServer/RequirementHandlers/UserRequirementHandler.cs b/MareSynchronosServer/MareSynchronosServer/RequirementHandlers/UserRequirementHandler.cs new file mode 100644 index 0000000..caa51c1 --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/RequirementHandlers/UserRequirementHandler.cs @@ -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 +{ + private readonly GrpcClientIdentificationService identClient; + private readonly MareDbContext dbContext; + private readonly ILogger logger; + + public UserRequirementHandler(GrpcClientIdentificationService identClient, MareDbContext dbContext, ILogger 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); + } +} diff --git a/MareSynchronosServer/MareSynchronosServer/RequirementHandlers/UserRequirements.cs b/MareSynchronosServer/MareSynchronosServer/RequirementHandlers/UserRequirements.cs new file mode 100644 index 0000000..41415bf --- /dev/null +++ b/MareSynchronosServer/MareSynchronosServer/RequirementHandlers/UserRequirements.cs @@ -0,0 +1,8 @@ +namespace MareSynchronosServer.RequirementHandlers; + +public enum UserRequirements +{ + Identified = 0b00000001, + Moderator = 0b00000010, + Administrator = 0b00000100 +} diff --git a/MareSynchronosServer/MareSynchronosServer/Services/GrpcClientIdentificationService.cs b/MareSynchronosServer/MareSynchronosServer/Services/GrpcClientIdentificationService.cs index 7728b3f..690c402 100644 --- a/MareSynchronosServer/MareSynchronosServer/Services/GrpcClientIdentificationService.cs +++ b/MareSynchronosServer/MareSynchronosServer/Services/GrpcClientIdentificationService.cs @@ -40,6 +40,11 @@ public class GrpcClientIdentificationService : IHostedService _metrics = metrics; } + public bool IsOnCurrentServer(string uid) + { + return OnlineClients.ContainsKey(uid); + } + public string? GetCharacterIdentForUid(string uid) { if (OnlineClients.TryGetValue(uid, out var ident)) diff --git a/MareSynchronosServer/MareSynchronosServer/Startup.cs b/MareSynchronosServer/MareSynchronosServer/Startup.cs index 2838e6f..04e91d3 100644 --- a/MareSynchronosServer/MareSynchronosServer/Startup.cs +++ b/MareSynchronosServer/MareSynchronosServer/Startup.cs @@ -22,6 +22,7 @@ using System.Collections.Generic; using MareSynchronosServer.Services; using System.Net.Http; using MareSynchronosServer.Utils; +using MareSynchronosServer.RequirementHandlers; namespace MareSynchronosServer; @@ -119,6 +120,7 @@ public class Startup }); services.AddSingleton(); + services.AddTransient(); services.AddHostedService(p => p.GetService()); services.AddDbContextPool(options => @@ -131,11 +133,32 @@ public class Startup options.EnableThreadSafetyChecks(false); }, mareConfig.GetValue("DbContextPoolSize", 1024)); - services.AddAuthentication(options => + services.AddAuthentication(SecretKeyGrpcAuthenticationHandler.AuthScheme) + .AddScheme(SecretKeyGrpcAuthenticationHandler.AuthScheme, options => { options.Validate(); }); + + services.AddAuthorization(options => { - options.DefaultScheme = SecretKeyGrpcAuthenticationHandler.AuthScheme; - }).AddScheme(SecretKeyGrpcAuthenticationHandler.AuthScheme, _ => { }); - services.AddAuthorization(options => options.FallbackPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build()); + options.DefaultPolicy = new AuthorizationPolicyBuilder() + .AddAuthenticationSchemes(SecretKeyGrpcAuthenticationHandler.AuthScheme) + .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(); diff --git a/MareSynchronosServer/MareSynchronosShared/Authentication/SecretKeyGrpcAuthenticationHandler.cs b/MareSynchronosServer/MareSynchronosShared/Authentication/SecretKeyGrpcAuthenticationHandler.cs index 88d6218..62f8333 100644 --- a/MareSynchronosServer/MareSynchronosShared/Authentication/SecretKeyGrpcAuthenticationHandler.cs +++ b/MareSynchronosServer/MareSynchronosShared/Authentication/SecretKeyGrpcAuthenticationHandler.cs @@ -17,7 +17,7 @@ public class SecretKeyGrpcAuthenticationHandler : AuthenticationHandler options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { this._authClient = authClient; @@ -26,20 +26,21 @@ public class SecretKeyGrpcAuthenticationHandler : AuthenticationHandler HandleAuthenticateAsync() { - if(!Request.Headers.TryGetValue("Authorization", out var authHeader)) + if (!Request.Headers.TryGetValue("Authorization", out var authHeader)) { authHeader = string.Empty; } + 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) { return AuthenticateResult.Fail("Failed Authorization"); } - string uid = authResult.Uid; + var uid = authResult.Uid; var claims = new List {