Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanJosipovic committed Nov 26, 2023
1 parent 8bcb652 commit ad2e683
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 26 deletions.
14 changes: 5 additions & 9 deletions src/oidc-guard/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@

public static class CustomHeaderNames
{
public static readonly string XOriginalMethod = "X-Original-Method";

public static readonly string XOriginalUrl = "X-Original-Url";

public static readonly string XForwardedProto = "X-Forwarded-Proto";

public static readonly string XForwardedHost = "X-Forwarded-Host";

public static readonly string XForwardedUri = "X-Forwarded-Uri";

public static readonly string XForwardedMethod = "X-Forwarded-Method";
public static readonly string XForwardedProto = "X-Forwarded-Proto";
public static readonly string XForwardedUri = "X-Forwarded-Uri";
public static readonly string XOriginalMethod = "X-Original-Method";
public static readonly string XOriginalProto = "X-Original-Proto";
public static readonly string XOriginalUrl = "X-Original-Url";
}

public static class QueryParameters
Expand Down
31 changes: 16 additions & 15 deletions src/oidc-guard/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public static void Main(string[] args)
{
string? authorization = context.Request.Headers.Authorization;

return settings.JWT.Enable && !string.IsNullOrEmpty(authorization) && authorization.StartsWith("Bearer ")
return settings.JWT.Enable && !string.IsNullOrEmpty(authorization) && authorization.StartsWith(JwtBearerDefaults.AuthenticationScheme + ' ')
? JwtBearerDefaults.AuthenticationScheme
: settings.Cookie.Enable
? CookieAuthenticationDefaults.AuthenticationScheme
Expand Down Expand Up @@ -213,15 +213,17 @@ public static void Main(string[] args)
context.Request.Headers.Authorization = JwtBearerDefaults.AuthenticationScheme + ' ' + context.Request.Headers.Authorization;
}

if (settings.JWT.EnableAccessTokenInQueryParameter &&
context.Request.Path.StartsWithSegments("/auth") &&
context.Request.Headers.TryGetValue(CustomHeaderNames.XOriginalUrl, out var originalUrlHeader) &&
Uri.TryCreate(originalUrlHeader, UriKind.RelativeOrAbsolute, out var uri))
if (settings.JWT.EnableAccessTokenInQueryParameter && context.Request.Path.StartsWithSegments("/auth"))
{
if (QueryHelpers.ParseQuery(uri.Query).TryGetValue(QueryParameters.AccessToken, out var token) &&
!context.Request.Headers.ContainsKey(HeaderNames.Authorization))
var originalUrl = GetOriginalUrl(context);

if (originalUrl != null && Uri.TryCreate(originalUrl, UriKind.RelativeOrAbsolute, out var uri))
{
context.Request.Headers.Authorization = JwtBearerDefaults.AuthenticationScheme + ' ' + token;
if (QueryHelpers.ParseQuery(uri.Query).TryGetValue(QueryParameters.AccessToken, out var token) &&
!context.Request.Headers.ContainsKey(HeaderNames.Authorization))
{
context.Request.Headers.Authorization = JwtBearerDefaults.AuthenticationScheme + ' ' + token;
}
}
}
}
Expand Down Expand Up @@ -261,7 +263,7 @@ public static void Main(string[] args)
(httpContext.Request.Query.TryGetValue(QueryParameters.SkipAuth, out var skipEquals) |
httpContext.Request.Query.TryGetValue(QueryParameters.SkipAuthNe, out var skipNotEquals)))
{
var originalUrl = GetOriginalUrl(httpContext.Request.Headers);
var originalUrl = GetOriginalUrl(httpContext);
var originalMethod = GetOriginalMethod(httpContext.Request.Headers);

if (skipEquals.Count > 0)
Expand Down Expand Up @@ -458,17 +460,16 @@ public static void Main(string[] args)
app.Run();
}

private static string? GetOriginalUrl(IHeaderDictionary headers)
private static string? GetOriginalUrl(HttpContext httpContext)
{
if (headers.TryGetValue(CustomHeaderNames.XOriginalUrl, out var xOriginalUrl))
if (httpContext.Request.Headers.TryGetValue(CustomHeaderNames.XOriginalUrl, out var xOriginalUrl))
{
return xOriginalUrl!;
}
else if (headers.TryGetValue(CustomHeaderNames.XForwardedProto, out var xForwardedProto) &&
headers.TryGetValue(CustomHeaderNames.XForwardedHost, out var xForwardedHost) &&
headers.TryGetValue(CustomHeaderNames.XForwardedUri, out var xForwardedUri))
else if (httpContext.Request.Headers.TryGetValue(HeaderNames.Host, out var host) &&
httpContext.Request.Headers.TryGetValue(CustomHeaderNames.XForwardedUri, out var xForwardedUri))
{
return $"{xForwardedProto}://{xForwardedHost}{xForwardedUri}";
return $"{httpContext.Request.Scheme}://{host}{xForwardedUri}";
}

return null;
Expand Down
35 changes: 34 additions & 1 deletion tests/oidc-guard-tests/AuthTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,19 @@ public static IEnumerable<object[]> GetTokenAsQueryParameterTests()
{CustomHeaderNames.XOriginalUrl, $"https://www.example.com?{QueryParameters.AccessToken}={FakeJwtIssuer.GenerateJwtToken(new List<Claim>{new Claim("tid", "22222222-2222-2222-2222-222222222222")})}" }
},
},

new object[] // Token Only in Query String
{
"",
new List<Claim>(),
HttpStatusCode.OK,
new Dictionary<string, string>()
{
{ CustomHeaderNames.XForwardedProto, "https" },
{ CustomHeaderNames.XForwardedHost, "www.example.com" },
{ CustomHeaderNames.XForwardedUri, $"?{QueryParameters.AccessToken}={FakeJwtIssuer.GenerateJwtToken(Enumerable.Empty<Claim>())}" }
}
},
};
}

Expand Down Expand Up @@ -547,6 +560,13 @@ public async Task UserInfoMulti()
[InlineData("?skip-auth-ne=test", "https://bob.com", "GET", HttpStatusCode.OK)]
[InlineData("?skip-auth-ne=test", "https://test.com", "GET", HttpStatusCode.Unauthorized)]
public async Task SkipAuth(string query, string Url, string httpMethod, HttpStatusCode status)
{
await SkipAuthNginx(query, Url, httpMethod, status);

await SkipAuthTraefik(query, Url, httpMethod, status);
}

private async Task SkipAuthNginx(string query, string Url, string httpMethod, HttpStatusCode status)
{
var _client = AuthTestsHelpers.GetClient();

Expand All @@ -557,6 +577,19 @@ public async Task SkipAuth(string query, string Url, string httpMethod, HttpStat
response.StatusCode.Should().Be(status);
}

private async Task SkipAuthTraefik(string query, string Url, string httpMethod, HttpStatusCode status)
{
var _client = AuthTestsHelpers.GetClient();

_client.DefaultRequestHeaders.TryAddWithoutValidation(CustomHeaderNames.XForwardedHost, new Uri(Url).Host);
_client.DefaultRequestHeaders.TryAddWithoutValidation(CustomHeaderNames.XForwardedMethod, httpMethod);
_client.DefaultRequestHeaders.TryAddWithoutValidation(CustomHeaderNames.XForwardedProto, new Uri(Url).Scheme);
_client.DefaultRequestHeaders.TryAddWithoutValidation(CustomHeaderNames.XForwardedUri, "/");

var response = await _client.GetAsync($"/auth{query}");
response.StatusCode.Should().Be(status);
}

[Fact]
public async Task SetHost()
{
Expand All @@ -578,7 +611,7 @@ public async Task JWKSAuth()
{
x.Cookie.Enable = false;
x.JWT.JWKSUrl = "https://inmemory.microsoft.com/common/discovery/keys";
x.JWT.ValidIssuers = new string[] { FakeJwtIssuer.Issuer };
x.JWT.ValidIssuers = [FakeJwtIssuer.Issuer];
});

_client.DefaultRequestHeaders.TryAddWithoutValidation(HeaderNames.Authorization, FakeJwtIssuer.GenerateBearerJwtToken(new List<Claim>()));
Expand Down
2 changes: 1 addition & 1 deletion tests/oidc-guard-tests/EndToEnd/oidc-guard-values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ settings:

# Accept token from the access_token Query Parameter
# https://datatracker.ietf.org/doc/html/rfc6750#section-2.3
enableAccessTokenInQueryParameter: false
enableAccessTokenInQueryParameter: true

# Prepend "Bearer " to the Authorization header if its missing
prependBearer: false
Expand Down

0 comments on commit ad2e683

Please sign in to comment.