Skip to content

Commit

Permalink
UserName route logic implemented and added check empty header
Browse files Browse the repository at this point in the history
  • Loading branch information
antoineatstariongroup committed Jan 22, 2025
1 parent 9361b98 commit d9b44f7
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ namespace CometServer.Tests.Authentication.Basic
using CDP4Authentication;

using CometServer.Authentication;
using CometServer.Authentication.Anonymous;
using CometServer.Authentication.Basic;
using CometServer.Configuration;
using CometServer.Exceptions;
Expand Down Expand Up @@ -143,7 +142,7 @@ public async Task VerifyAuthenticationFailsBasedOnConfig()
}

[Test]
public async Task VerifyAuthenticationNotSucceedNorFailedWithEmptyHeader()
public async Task VerifyAuthenticationFailsWithEmptyHeader()
{
var context = new DefaultHttpContext
{
Expand All @@ -160,7 +159,7 @@ public async Task VerifyAuthenticationNotSucceedNorFailedWithEmptyHeader()

await this.handler.ChallengeAsync(result.Properties);

Assert.That(context.Response.StatusCode, Is.EqualTo(200));
Assert.That(context.Response.StatusCode, Is.EqualTo(401));
}

[Test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ namespace CometServer.Tests.Authentication.Bearer
using CDP4Authentication;

using CometServer.Authentication;
using CometServer.Authentication.Basic;
using CometServer.Authentication.Bearer;
using CometServer.Configuration;
using CometServer.Health;
Expand Down Expand Up @@ -228,5 +227,26 @@ public async Task VerifyAuthenticationSuccessWithValidToken()

Assert.That(result.Succeeded, Is.True);
}

[Test]
public async Task VerifyAuthenticationFailsWithEmptyHeader()
{
var context = new DefaultHttpContext
{
RequestServices = this.requestService.Object
};

this.cometHasStartedService.Setup(x => x.GetHasStartedAndIsReady()).Returns(new ServerStatus(true, DateTime.Now));
await this.handler.InitializeAsync(new AuthenticationScheme(JwtBearerDefaults.LocalAuthenticationScheme, "", typeof(JwtBearerAuthenticationHandler)), context);

this.appConfigService.Setup(x => x.IsAuthenticationSchemeEnabled(this.handler.Scheme.Name)).Returns(true);
var result = await this.handler.AuthenticateAsync();

Assert.That(result.Succeeded, Is.False);

await this.handler.ChallengeAsync(result.Properties);

Assert.That(context.Response.StatusCode, Is.EqualTo(401));
}
}
}
10 changes: 10 additions & 0 deletions CometServer/Authentication/Basic/BasicAuthenticationHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,16 @@ protected override async Task HandleChallengeAsync(AuthenticationProperties prop

return;
}

var authorizationHeader = this.Request.Headers.Authorization;

if (string.IsNullOrEmpty(authorizationHeader))
{
this.Response.ContentType = "application/json";
this.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await this.Response.AsJson("Missing Authorization Header");
return;
}

if (!this.Request.DoesAuthorizationHeaderMatches(this.Scheme.Name))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,17 @@ protected override async Task HandleChallengeAsync(AuthenticationProperties prop

return;
}

var authorizationHeader = this.Request.Headers.Authorization;

if (string.IsNullOrEmpty(authorizationHeader))
{
this.Response.ContentType = "application/json";
this.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await this.Response.AsJson("Missing Authorization Header");
return;
}

if (!this.Request.DoesAuthorizationHeaderMatches(this.Scheme.Name))
{
return;
Expand Down Expand Up @@ -143,6 +153,14 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
return AuthenticateResult.NoResult();
}

var authorizationHeader = this.Request.Headers.Authorization;

if (string.IsNullOrEmpty(authorizationHeader))
{
this.Logger.LogInformation("no Authorization header provided");
return AuthenticateResult.NoResult();
}

if (!this.Request.DoesAuthorizationHeaderMatches(this.Scheme.Name))
{
Expand Down
2 changes: 2 additions & 0 deletions CometServer/Authorization/ICredentialsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ namespace CometServer.Authorization
using System;
using System.Threading.Tasks;

using CDP4Common.DTO;

using Npgsql;

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion CometServer/Modules/10-25/ApiBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ApiBase.cs" company="Starion Group S.A.">
// Copyright (c) 2015-2024 Starion Group S.A.
//
Expand Down
13 changes: 11 additions & 2 deletions CometServer/Modules/Authentication/AuthenticationModule.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="AuthenticationModule.cs" company="Starion Group S.A.">
// Copyright (c) 2015-2024 Starion Group S.A.
//
Expand Down Expand Up @@ -26,6 +26,7 @@ namespace CometServer.Modules
{
using System;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

using Carter;
Expand All @@ -52,8 +53,16 @@ public class AuthenticationModule : CarterModule
/// </param>
public override void AddRoutes(IEndpointRouteBuilder app)
{
app.MapPost("/login", async (LoginUser loginUser, HttpResponse res, IAuthenticationPersonAuthenticator authenticationPersonAuthenticator, IJwtTokenService jwtTokenService) =>
app.MapPost("/login", async (LoginUser loginUser, HttpResponse res, IAuthenticationPersonAuthenticator authenticationPersonAuthenticator, IJwtTokenService jwtTokenService
, IAppConfigService appConfigService) =>
{
if (!appConfigService.IsAuthenticationSchemeEnabled(JwtBearerDefaults.LocalAuthenticationScheme))
{
res.StatusCode = (int)HttpStatusCode.Forbidden;
await res.WriteAsync("Local JWT Authentication is disable.");
return;
}

var authenticationPerson = await authenticationPersonAuthenticator.Authenticate(loginUser.UserName, loginUser.Password);

if (authenticationPerson != null)
Expand Down
105 changes: 100 additions & 5 deletions CometServer/Modules/Authentication/UsernameModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,96 @@

namespace CometServer.Modules
{
using System;
using System.Linq;
using System.Net;
using System.Security.Claims;

using Carter;
using Carter.Response;

using CDP4DalCommon.Tasks;

using CometServer.Authentication.Basic;
using CDP4ServicesMessaging.Services.BackgroundMessageProducers;

using CometServer.Authentication.Bearer;
using CometServer.Authorization;
using CometServer.Configuration;
using CometServer.Enumerations;
using CometServer.Exceptions;
using CometServer.Extensions;
using CometServer.Health;
using CometServer.Services;
using CometServer.Tasks;

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

using Npgsql;

/// <summary>
/// handle request on the logged-in users
/// </summary>
public class UsernameModule : CarterModule
public class UsernameModule : ApiBase
{
/// <summary>
/// The (injected) <see cref="ILogger{UsernameModule}"/> instance
/// </summary>
private readonly ILogger<UsernameModule> logger;

/// <summary>
/// Initializes a new instance of the <see cref="ApiBase"/> class
/// </summary>
/// <param name="appConfigService">
/// The (injected) <see cref="IAppConfigService"/>
/// </param>
/// <param name="cometHasStartedService">
/// The (injected) <see cref="ICometHasStartedService"/> that is used to check whether CDP4-COMET is ready to start
/// acceptng requests
/// </param>
/// <param name="tokenGeneratorService">
/// The (injected) <see cref="ITokenGeneratorService"/> used generate HTTP request tokens
/// </param>
/// <param name="loggerFactory">
/// The (injected) <see cref="ILoggerFactory"/> used to create typed loggers
/// </param>
/// <param name="thingsMessageProducer">
/// The (injected) <see cref="IBackgroundThingsMessageProducer"/> used to schedule things messages to be sent
/// </param>
/// <param name="cometTaskService">
/// The (injected) <see cref="ICometTaskService"/> used to register and access running <see cref="CometTask"/>s
/// </param>
public UsernameModule(IAppConfigService appConfigService, ICometHasStartedService cometHasStartedService, ITokenGeneratorService tokenGeneratorService, ILoggerFactory loggerFactory, IBackgroundThingsMessageProducer thingsMessageProducer, ICometTaskService cometTaskService) :
base(appConfigService, cometHasStartedService, tokenGeneratorService, loggerFactory, thingsMessageProducer, cometTaskService)
{
this.logger = loggerFactory == null ? NullLogger<UsernameModule>.Instance : loggerFactory.CreateLogger<UsernameModule>();
}

/// <summary>
/// Initializes a new instance of the <see cref="ApiBase"/> class
/// </summary>
/// <param name="appConfigService">
/// The (injected) <see cref="IAppConfigService"/>
/// </param>
/// <param name="cometHasStartedService">
/// The (injected) <see cref="ICometHasStartedService"/> that is used to determine whether the servre
/// is ready to accept incoming requests
/// </param>
/// <param name="tokenGeneratorService">
/// The (injected) <see cref="ITokenGeneratorService"/> used generate HTTP request tokens
/// </param>
/// <param name="loggerFactory">
/// The (injected) <see cref="ILoggerFactory"/> used to create typed loggers
/// </param>
public UsernameModule(IAppConfigService appConfigService, ICometHasStartedService cometHasStartedService, ITokenGeneratorService tokenGeneratorService, ILoggerFactory loggerFactory) :
base(appConfigService, cometHasStartedService, tokenGeneratorService, loggerFactory)
{
this.logger = loggerFactory == null ? NullLogger<UsernameModule>.Instance : loggerFactory.CreateLogger<UsernameModule>();
}

/// <summary>
/// Add the routes to the <see cref="IEndpointRouteBuilder"/>
/// </summary>
Expand All @@ -45,10 +122,28 @@ public class UsernameModule : CarterModule
/// </param>
public override void AddRoutes(IEndpointRouteBuilder app)
{
app.MapGet("/username", async (HttpRequest req, HttpResponse res) =>
app.MapGet("/username", async (HttpRequest req, HttpResponse res, IAppConfigService appConfigService, ICredentialsService credentialsService) =>
{
await res.WriteAsync(res.HttpContext.User.Identity.Name);
}).RequireAuthorization(new[] { BasicAuthenticationDefaults.AuthenticationScheme });
if (!await this.IsServerReady(res))
{
return;
}

var identity = req.HttpContext.User.Identity!.Name;

try
{
identity = await this.Authorize(appConfigService, credentialsService, req);
await res.WriteAsync(credentialsService.Credentials.UserName);
}
catch (AuthorizationException)
{
this.logger.LogWarning("The GET UserName was not authorized for {Identity}", identity);

res.UpdateWithNotAutherizedSettings();
await res.AsJson("not authorized");
}
}).RequireAuthorization(ApiBase.AuthenticationSchemes);
}
}
}

0 comments on commit d9b44f7

Please sign in to comment.