-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/fusion auth #13
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,74 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
namespace Argon.Api.Features.Jwt; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.AspNetCore.Authentication.JwtBearer; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.Extensions.DependencyInjection; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.IdentityModel.Tokens; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using System.Text; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.Extensions.Options; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.AspNetCore.Authentication; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
using Microsoft.Extensions.DependencyInjection.Extensions; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public record JwtOptions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public required string Issuer { get; set; } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public required string Audience { get; set; } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// TODO use cert in production | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public required string Key { get; set; } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public required TimeSpan Expires { get; set; } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public void Deconstruct(out string issuer, out string audience, out string key) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
audience = this.Audience; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
issuer = this.Issuer; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
key = this.Key; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+19
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix the parameter assignment order in the Deconstruct method The assignments in the Apply this diff to correct the assignment order: public void Deconstruct(out string issuer, out string audience, out string key)
{
- audience = this.Audience;
- issuer = this.Issuer;
+ issuer = this.Issuer;
+ audience = this.Audience;
key = this.Key;
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public static class JwtFeature | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public static IServiceCollection AddJwt(this WebApplicationBuilder builder) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
builder.Services.Configure<JwtOptions>(builder.Configuration.GetSection("Jwt")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
builder.Services.AddKeyedSingleton(JwtBearerDefaults.AuthenticationScheme, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(services, _) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var options = services.GetRequiredService<IOptions<JwtOptions>>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var (issuer, audience, key) = options.Value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return new TokenValidationParameters | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ValidateIssuer = true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ValidateAudience = true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ValidateIssuerSigningKey = true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ValidIssuer = issuer, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ValidAudience = audience, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ClockSkew = TimeSpan.Zero | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
builder.Services.AddAuthentication(options => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}).AddJwtBearer(o => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
o.Events = new JwtBearerEvents | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
OnMessageReceived = ctx => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (ctx.Request.Headers.TryGetValue("x-argon-token", out var value)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ctx.Token = value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Task.CompletedTask; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ctx.Response.StatusCode = 401; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Task.CompletedTask; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+59
to
+69
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid setting the response status code in the OnMessageReceived event Modifying the response status code within the Apply this diff to remove the manual status code assignment: OnMessageReceived = ctx =>
{
if (ctx.Request.Headers.TryGetValue("x-argon-token", out var value))
{
ctx.Token = value;
return Task.CompletedTask;
}
- ctx.Response.StatusCode = 401;
return Task.CompletedTask;
} 📝 Committable suggestion
Suggested change
🛠️ Refactor suggestion Consider supporting the standard Authorization header alongside the custom header To improve interoperability and adhere to HTTP standards, consider extracting the token from the standard Update the OnMessageReceived = ctx =>
{
+ if (ctx.Request.Headers.TryGetValue("Authorization", out var authHeader))
+ {
+ var token = authHeader.ToString().Split(' ').Last();
+ ctx.Token = token;
+ return Task.CompletedTask;
+ }
if (ctx.Request.Headers.TryGetValue("x-argon-token", out var value))
{
ctx.Token = value;
return Task.CompletedTask;
}
return Task.CompletedTask;
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return builder.Services; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,57 @@ | ||||||
namespace Argon.Api.Features.Rpc; | ||||||
|
||||||
using ActualLab.Rpc.Infrastructure; | ||||||
using ActualLab.Rpc; | ||||||
using MemoryPack; | ||||||
using Microsoft.Extensions.Caching.Distributed; | ||||||
using ActualLab; | ||||||
using ActualLab.Reflection; | ||||||
using Grains; | ||||||
using Grains.Persistence.States; | ||||||
using Microsoft.AspNetCore.Authorization; | ||||||
using Orleans; | ||||||
|
||||||
public class FusionAuthorizationMiddleware(IServiceProvider Services, IGrainFactory GrainFactory) : RpcInboundMiddleware(Services) | ||||||
{ | ||||||
public AsyncLocal<string> Token = new AsyncLocal<string>(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unused field The field Apply this diff to remove the unused field: -public AsyncLocal<string> Token = new AsyncLocal<string>(); 📝 Committable suggestion
Suggested change
|
||||||
public override async Task OnBeforeCall(RpcInboundCall call) | ||||||
{ | ||||||
var existAttribute = call.MethodDef.Method.GetAttributes<AuthorizeAttribute>(true, true).Count != 0; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Use Improve readability by using Apply this diff to refactor the code: -var existAttribute = call.MethodDef.Method.GetAttributes<AuthorizeAttribute>(true, true).Count != 0;
+var authorizeAttributeExists = call.MethodDef.Method.GetAttributes<AuthorizeAttribute>(true, true).Any(); 📝 Committable suggestion
Suggested change
|
||||||
|
||||||
if (!existAttribute) | ||||||
{ | ||||||
await base.OnBeforeCall(call); | ||||||
return; | ||||||
} | ||||||
|
||||||
var grain = GrainFactory.GetGrain<IFusionSession>(call.Context.Peer.Id); | ||||||
|
||||||
Comment on lines
+27
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add null checks for To prevent potential Consider adding null checks: if (call.Context?.Peer?.Id == null)
{
call.Cancel();
return;
}
var grain = GrainFactory.GetGrain<IFusionSession>(call.Context.Peer.Id); |
||||||
var state = await grain.GetState(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle exceptions when calling Ensure that any exceptions thrown by Consider wrapping the call in a try-catch block: FusionSession state;
try
{
state = await grain.GetState();
}
catch (Exception ex)
{
// Handle exception appropriately, e.g., log the error and cancel the call
call.Cancel();
return;
} |
||||||
if (state.IsAuthorized) | ||||||
{ | ||||||
await base.OnBeforeCall(call); | ||||||
return; | ||||||
} | ||||||
|
||||||
call.Cancel(); | ||||||
return; | ||||||
} | ||||||
} | ||||||
|
||||||
public class FusionServiceContext(IGrainFactory GrainFactory) : IFusionServiceContext | ||||||
{ | ||||||
public ValueTask<FusionSession> GetSessionState() | ||||||
{ | ||||||
var current = RpcInboundContext.GetCurrent(); | ||||||
var peerId = current.Peer.Id; | ||||||
Comment on lines
+45
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ensure To avoid a Modify the code as follows: var current = RpcInboundContext.GetCurrent();
if (current?.Peer?.Id == null)
{
// Handle null case appropriately, e.g., throw an exception or return a default value
throw new InvalidOperationException("Current RPC context or peer ID is not available.");
}
var peerId = current.Peer.Id; |
||||||
|
||||||
var grain = GrainFactory.GetGrain<IFusionSession>(peerId); | ||||||
|
||||||
return grain.GetState(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle exceptions from Ensure that exceptions thrown by Consider adding exception handling: try
{
return await grain.GetState();
}
catch (Exception ex)
{
// Handle exception, e.g., log the error and throw a custom exception
throw new InvalidOperationException("Failed to retrieve session state.", ex);
} |
||||||
} | ||||||
} | ||||||
|
||||||
public interface IFusionServiceContext | ||||||
{ | ||||||
ValueTask<FusionSession> GetSessionState(); | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
namespace Argon.Api.Grains.Persistence.States; | ||
|
||
using Argon.Sfu; | ||
using MemoryPack; | ||
|
||
[GenerateSerializer] | ||
[Serializable] | ||
[MemoryPackable] | ||
[Alias(nameof(FusionSession))] | ||
public partial class FusionSession | ||
{ | ||
[Id(0)] public required Guid Id { get; set; } = Guid.Empty; | ||
[Id(1)] public required bool IsAuthorized { get; set; } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
namespace Argon.Api.Grains; | ||
|
||
using System.IdentityModel.Tokens.Jwt; | ||
using Microsoft.IdentityModel.Tokens; | ||
using Persistence.States; | ||
|
||
public class FusionGrain( | ||
[PersistentState("sessions", "OrleansStorage")] | ||
IPersistentState<FusionSession> sessionStorage, | ||
TokenValidationParameters JwtParameters) : Grain, IFusionSession | ||
{ | ||
public async ValueTask<bool> AuthorizeAsync(string token) | ||
{ | ||
var tokenHandler = new JwtSecurityTokenHandler(); | ||
tokenHandler.ValidateToken(token, JwtParameters, out SecurityToken validatedToken); | ||
var jwt = (JwtSecurityToken)validatedToken; | ||
|
||
sessionStorage.State.Id = Guid.Parse(jwt.Id); | ||
sessionStorage.State.IsAuthorized = true; | ||
Comment on lines
+18
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle invalid GUIDs when parsing JWT ID When converting Apply this diff to safely parse the JWT ID: - sessionStorage.State.Id = Guid.Parse(jwt.Id);
+ if (Guid.TryParse(jwt.Id, out var sessionId))
+ {
+ _sessionStorage.State.Id = sessionId;
+ }
+ else
+ {
+ // Invalid GUID in JWT ID
+ return false;
+ }
|
||
await sessionStorage.WriteStateAsync(); | ||
return true; | ||
} | ||
Comment on lines
+12
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add exception handling in In the Consider wrapping the token validation in a try-catch block and returning public async ValueTask<bool> AuthorizeAsync(string token)
{
var tokenHandler = new JwtSecurityTokenHandler();
- tokenHandler.ValidateToken(token, JwtParameters, out SecurityToken validatedToken);
+ SecurityToken validatedToken;
+ try
+ {
+ tokenHandler.ValidateToken(token, _jwtParameters, out validatedToken);
+ }
+ catch (Exception)
+ {
+ // Token validation failed
+ return false;
+ }
var jwt = (JwtSecurityToken)validatedToken;
- sessionStorage.State.Id = Guid.Parse(jwt.Id);
- sessionStorage.State.IsAuthorized = true;
- await sessionStorage.WriteStateAsync();
+ if (Guid.TryParse(jwt.Id, out var sessionId))
+ {
+ _sessionStorage.State.Id = sessionId;
+ _sessionStorage.State.IsAuthorized = true;
+ await _sessionStorage.WriteStateAsync();
+ return true;
+ }
+ else
+ {
+ // Invalid GUID in JWT ID
+ return false;
+ }
- return true;
} This change also incorporates safe parsing of
|
||
|
||
public async ValueTask<FusionSession> GetState() | ||
{ | ||
await sessionStorage.ReadStateAsync(); | ||
return sessionStorage.State; | ||
} | ||
Comment on lines
+24
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Optimize state retrieval in In the Consider checking if the state is already loaded before reading it again: public async ValueTask<FusionSession> GetState()
{
- await sessionStorage.ReadStateAsync();
+ if (!_sessionStorage.RecordExists)
+ {
+ await _sessionStorage.ReadStateAsync();
+ }
return _sessionStorage.State;
} This change checks if the state exists before reading it, which can improve performance by avoiding unnecessary I/O operations.
|
||
|
||
} | ||
|
||
|
||
public interface IFusionSession : IGrainWithGuidKey | ||
{ | ||
[Alias("AuthorizeAsync")] | ||
ValueTask<bool> AuthorizeAsync(string token); | ||
|
||
[Alias("GetState")] | ||
ValueTask<FusionSession> GetState(); | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,8 +1,12 @@ | ||||||
using ActualLab.Fusion; | ||||||
using ActualLab.Fusion.Extensions; | ||||||
using ActualLab.Rpc; | ||||||
using ActualLab.Rpc.Infrastructure; | ||||||
using ActualLab.Rpc.Server; | ||||||
using Argon.Api.Entities; | ||||||
using Argon.Api.Extensions; | ||||||
using Argon.Api.Features.Jwt; | ||||||
using Argon.Api.Features.Rpc; | ||||||
using Argon.Api.Filters; | ||||||
using Argon.Api.Migrations; | ||||||
using Argon.Api.Services; | ||||||
|
@@ -11,6 +15,7 @@ | |||||
|
||||||
var builder = WebApplication.CreateBuilder(args); | ||||||
|
||||||
builder.AddJwt(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Security concern: JWT implementation needs improvements The JWT configuration has several security considerations that need to be addressed:
Recommendations:
🔗 Analysis chainVerify JWT configuration implementation. The JWT configuration is added, but we should verify the security settings in the implementation. Let's check the JWT configuration implementation: 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Description: Verify JWT configuration implementation
# Look for JWT configuration settings like token validation parameters,
# key management, and security settings
# Check JWT options configuration
ast-grep --pattern 'class JwtOptions {
$$$
}'
# Check for secure key management
rg -l "SecurityKey|SigningKey|IssuerSigningKey" --type cs
Length of output: 221 Script: #!/bin/bash
# Let's try a different approach to find JWT-related configurations
# Search for JWT-related files and configurations
rg -l "JWT|JsonWebToken" --type cs
# Look for AddJwt extension method implementation
ast-grep --pattern 'AddJwt($$$) {
$$$
}'
# Search for token validation parameters
rg "TokenValidationParameters" -A 5 --type cs
# Look for authentication/JWT middleware setup
rg "UseAuthentication|UseJwtBearer" --type cs
Length of output: 1233 Script: #!/bin/bash
# Let's examine the JWT configuration implementation in more detail
# Check the complete JwtOptions class implementation
cat src/Argon.Api/Features/Jwt/JwtOptions.cs
# Look for the AddJwt extension method implementation
rg -A 10 "AddJwt" --type cs
# Check for any security key configuration
rg "SecurityKey|SigningKey|IssuerSigningKey" -A 3 --type cs
Length of output: 6852 |
||||||
builder.AddServiceDefaults(); | ||||||
builder.AddRedisOutputCache("cache"); | ||||||
builder.AddRabbitMQClient("rmq"); | ||||||
|
@@ -19,12 +24,13 @@ | |||||
builder.Services.AddFusion(RpcServiceMode.Server, true) | ||||||
.Rpc.AddServer<IUserAuthorization, UserAuthorization>() | ||||||
.AddServer<IUserInteraction, UserInteractionService>() | ||||||
.AddInboundMiddleware<FusionAuthorizationMiddleware>() | ||||||
.AddWebSocketServer(true); | ||||||
builder.AddSwaggerWithAuthHeader(); | ||||||
builder.AddJwt(); | ||||||
builder.Services.AddAuthorization(); | ||||||
builder.AddSelectiveForwardingUnit(); | ||||||
builder.Services.AddTransient<UserManagerService>(); | ||||||
builder.Services.AddTransient<IFusionServiceContext, FusionServiceContext>(); | ||||||
builder.AddOrleans(); | ||||||
var app = builder.Build(); | ||||||
app.UseSwagger(); | ||||||
|
@@ -34,7 +40,8 @@ | |||||
app.UseAuthorization(); | ||||||
app.MapControllers(); | ||||||
app.MapDefaultEndpoints(); | ||||||
app.UseWebSockets(); | ||||||
app.MapRpcWebSocketServer(); | ||||||
var buildTime = File.GetLastWriteTimeUtc(typeof(Program).Assembly.Location); | ||||||
app.MapGet("/", () => new { buildTime }); | ||||||
await app.WarpUp<ApplicationDbContext>().RunAsync(); | ||||||
await app.WarpUp<ApplicationDbContext>().RunAsync(); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix typo in method name. There appears to be a typo in the method name: Apply this fix: -await app.WarpUp<ApplicationDbContext>().RunAsync();
+await app.WarmUp<ApplicationDbContext>().RunAsync(); 📝 Committable suggestion
Suggested change
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
не надо удалять, нам это для тестов понадобится