forked from NpgsqlRest/NpgsqlRest
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTokenRefreshAuth.cs
More file actions
86 lines (74 loc) · 3.19 KB
/
Copy pathTokenRefreshAuth.cs
File metadata and controls
86 lines (74 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
using System.Net;
using System.Text.Json.Nodes;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.Extensions.Options;
namespace NpgsqlRestClient;
public class BearerTokenConfig
{
public string? Scheme { get; set; }
public string? RefreshPath { get; set; }
}
public class TokenRefreshAuth
{
public TokenRefreshAuth(BearerTokenConfig? bearerTokenConfig, WebApplication app, ILogger? logger)
{
var tokenConfig = bearerTokenConfig;
if (bearerTokenConfig is null ||
string.IsNullOrEmpty(bearerTokenConfig.RefreshPath) is true ||
string.IsNullOrEmpty(bearerTokenConfig.Scheme) is true)
{
return;
}
// Use local variables from parameters - no instance references captured
var refreshPath = bearerTokenConfig.RefreshPath;
var scheme = bearerTokenConfig.Scheme;
app.Use(async (context, next) =>
{
if (context.Request.Path.Equals(refreshPath, StringComparison.OrdinalIgnoreCase) is false)
{
await next(context);
return;
}
if (string.Equals(context.Request.Method, "POST", StringComparison.OrdinalIgnoreCase) is false)
{
await next(context);
return;
}
var bearerTokenOptions = app.Services.GetRequiredService<IOptionsMonitor<Microsoft.AspNetCore.Authentication.BearerToken.BearerTokenOptions>>();
var refreshTokenProtector = bearerTokenOptions.Get(scheme).RefreshTokenProtector;
var timeProvider = app.Services.GetRequiredService<TimeProvider>();
string refreshToken;
IResult result;
try
{
using var reader = new StreamReader(context.Request.Body);
var body = await reader.ReadToEndAsync();
var node = JsonNode.Parse(string.IsNullOrWhiteSpace(body) ? "{}" : body);
refreshToken = node!["refresh"]?.ToString() ?? throw new ArgumentException("refresh token is null");
}
catch (Exception ex)
{
logger?.LogError(ex, "Failed to read refresh token from request body.");
result = Results.BadRequest(context.Response);
await result.ExecuteAsync(context);
return;
}
var refreshTicket = refreshTokenProtector.Unprotect(refreshToken);
if (
(refreshTicket?.Properties?.ExpiresUtc is not { } expiresUtc || timeProvider.GetUtcNow() >= expiresUtc) ||
context.User.Identity?.IsAuthenticated is false)
{
result = Results.Challenge();
await result.ExecuteAsync(context);
return;
}
if (Results.SignIn(principal: context.User, authenticationScheme: scheme) is not SignInHttpResult signInResult)
{
logger?.LogError("Failed in constructing user identity for authentication.");
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return;
}
await signInResult.ExecuteAsync(context);
});
}
}