Skip to content
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

Very Minimal Restructuring of Project #4

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
421 changes: 418 additions & 3 deletions .gitignore

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions Services/DiscoveryDocument.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;

namespace YarpAuthProxy.BffLibrary.Middleware;

public static class GatewayEndpoints
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using YarpAuthProxy.BffLibrary.Services;

namespace YarpAuthProxy.BffLibrary.Middleware;

public static class GatewayPipeline
{
public static void UseGatewayPipeline(this IReverseProxyApplicationBuilder pipeline)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using YarpAuthProxy.BffLibrary.Services;
using YarpAuthProxy.BffLibrary.Utils.Config;

namespace YarpAuthProxy.BffLibrary.Middleware;

public static class GatewaySetup
{
private static readonly string ENV_GATEWAY_CONFIG = "GATEWAY_CONFIG";
private static readonly string ENV_GATEWAY_CONFIG = "GATEWAY_CONFIG";

public static void AddConfigFiles(this WebApplicationBuilder builder)
{
Expand All @@ -21,28 +29,31 @@ public static void AddConfigFiles(this WebApplicationBuilder builder)
}
}

private static void AddTokenExchangeService(this WebApplicationBuilder builder, GatewayConfig config) {
private static void AddTokenExchangeService(this WebApplicationBuilder builder, GatewayConfig config)
{
var strategy = config.TokenExchangeStrategy;
if (string.IsNullOrEmpty(strategy)) {
if (string.IsNullOrEmpty(strategy))
{
strategy = "none";
}

switch(strategy.ToLower()) {
switch (strategy.ToLower())
{
case "none":
builder.Services.AddSingleton<ITokenExchangeService, NullTokenExchangeService>();
break;
builder.Services.AddSingleton<ITokenExchangeService, NullTokenExchangeService>();
break;

case "azuread":
builder.Services.AddSingleton<ITokenExchangeService, AzureAdTokenExchangeService>();
break;
builder.Services.AddSingleton<ITokenExchangeService, AzureAdTokenExchangeService>();
break;

case "default":
builder.Services.AddSingleton<ITokenExchangeService, TokenExchangeService>();
break;
builder.Services.AddSingleton<ITokenExchangeService, TokenExchangeService>();
break;

default:
throw new ArgumentException($"Unsupported TokenExchangeStrategy in config found: {config.TokenExchangeStrategy}. Possible values: none, AzureAd, default");

}
}

Expand All @@ -53,7 +64,7 @@ public static void AddGateway(this WebApplicationBuilder builder, GatewayConfig

builder.Services.AddSingleton<DiscoveryDocument>(disco);
builder.Services.AddSingleton<GatewayConfig>(config);

builder.Services.AddSingleton<TokenRefreshService>();
builder.AddTokenExchangeService(config);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using YarpAuthProxy.BffLibrary.Utils.Config;

public static class LogoutHandler {
namespace YarpAuthProxy.BffLibrary.Middleware;

public static class LogoutHandler
{
public static void HandleLogout(RedirectContext context, GatewayConfig config)
{
if (!string.IsNullOrEmpty(config.LogoutUrl))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
public class SessionKeys {
namespace YarpAuthProxy.BffLibrary.Middleware;

public class SessionKeys
{
public const string ACCESS_TOKEN = "accessToken";
public const string ID_TOKEN = "idToken";
public const string REFRESH_TOKEN = "refreshToken";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

public class TokenHandler {
namespace YarpAuthProxy.BffLibrary.Middleware;

public class TokenHandler
{

private ILogger<TokenHandler> logger;

public TokenHandler(ILogger<TokenHandler> logger) {
public TokenHandler(ILogger<TokenHandler> logger)
{
this.logger = logger;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using YarpAuthProxy.BffLibrary.Utils.Config;

namespace YarpAuthProxy.BffLibrary.Middleware;

public static class XsrfMiddleware
{
public static void UseXsrfCookie(this WebApplication app) {
public static void UseXsrfCookie(this WebApplication app)
{
app.UseXsrfCookieCreator();
app.UseXsrfCookieChecks();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
public class ApiTokenService {
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using YarpAuthProxy.BffLibrary.Middleware;
using YarpAuthProxy.BffLibrary.Utils.Config;

namespace YarpAuthProxy.BffLibrary.Services;

public class ApiTokenService
{

private ITokenExchangeService tokenExchangeService;
private ILogger<ApiTokenService> logger;

public ApiTokenService(
ITokenExchangeService tokenExchangeService,
ILogger<ApiTokenService> logger
) {
)
{
this.tokenExchangeService = tokenExchangeService;
this.logger = logger;
}
Expand All @@ -16,22 +25,27 @@ public void InvalidateApiTokens(HttpContext ctx)
ctx.Session.Remove(SessionKeys.API_ACCESS_TOKEN);
}

private TokenExchangeResponse? GetCachedApiToken(HttpContext ctx, ApiConfig apiConfig) {
private TokenExchangeResponse? GetCachedApiToken(HttpContext ctx, ApiConfig apiConfig)
{
var cache = ctx.Session.GetObject<Dictionary<string, TokenExchangeResponse>>(SessionKeys.API_ACCESS_TOKEN);
if (cache == null) {
if (cache == null)
{
return null;
}

if (!cache.ContainsKey(apiConfig.ApiPath)) {
if (!cache.ContainsKey(apiConfig.ApiPath))
{
return null;
}

return cache[apiConfig.ApiPath];
}

private void SetCachedApiToken(HttpContext ctx, ApiConfig apiConfig, TokenExchangeResponse response) {
private void SetCachedApiToken(HttpContext ctx, ApiConfig apiConfig, TokenExchangeResponse response)
{
var cache = ctx.Session.GetObject<Dictionary<string, TokenExchangeResponse>>(SessionKeys.API_ACCESS_TOKEN);
if (cache == null) {
if (cache == null)
{
cache = new Dictionary<string, TokenExchangeResponse>();
}

Expand All @@ -44,7 +58,8 @@ public async Task<string> LookupApiToken(HttpContext ctx, ApiConfig apiConfig, s
{
var apiToken = GetCachedApiToken(ctx, apiConfig);

if (apiToken != null) {
if (apiToken != null)
{
// TODO: Perform individual token refresh
return apiToken.access_token;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System.Net.Http.Json;
using YarpAuthProxy.BffLibrary.Utils.Config;

namespace YarpAuthProxy.BffLibrary.Services;

public class AzureAdTokenExchangeService : ITokenExchangeService
{
Expand Down
6 changes: 6 additions & 0 deletions src/YarpAuthProxy.BffLibrary/Services/DiscoveryDocument.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace YarpAuthProxy.BffLibrary.Services;

public class DiscoveryDocument
{
public string token_endpoint { get; set; } = "";
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
public class DiscoveryService {
using System.Net.Http.Json;

namespace YarpAuthProxy.BffLibrary.Services;

public class DiscoveryService
{

private readonly string DISCO_URL = ".well-known/openid-configuration";

public async Task<DiscoveryDocument> loadDiscoveryDocument(string authority) {
var httpClient = new HttpClient();
public async Task<DiscoveryDocument> loadDiscoveryDocument(string authority)
{
var httpClient = new HttpClient();

var url = UrlUtils.CombineUrls(authority, DISCO_URL);

var doc = await httpClient.GetFromJsonAsync<DiscoveryDocument>(url);

if (doc == null) {

if (doc == null)
{
throw new Exception("error loading discovery document from " + url);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using YarpAuthProxy.BffLibrary.Middleware;
using YarpAuthProxy.BffLibrary.Utils.Config;

namespace YarpAuthProxy.BffLibrary.Services;

public class GatewayService
{
private TokenRefreshService tokenRefreshService;
Expand All @@ -10,8 +17,9 @@ public GatewayService(
GatewayConfig config,
ApiTokenService apiTokenService,
ILogger<GatewayService> logger
) {
this.tokenRefreshService = tokenRefreshService;
)
{
this.tokenRefreshService = tokenRefreshService;
this.config = config;
this.apiTokenService = apiTokenService;
this.logger = logger;
Expand Down Expand Up @@ -98,9 +106,9 @@ public async Task AddToken(HttpContext ctx)
if (!string.IsNullOrEmpty(token) && apiConfig != null)
{
var apiToken = await GetApiToken(ctx, apiTokenService, token, apiConfig);

logger.LogDebug($"---- Adding Token for reqeuest ----\n{currentUrl}\n\n{apiToken}\n--------");

ctx.Request.Headers.Add("Authorization", "Bearer " + apiToken);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
using YarpAuthProxy.BffLibrary.Utils.Config;

namespace YarpAuthProxy.BffLibrary.Services;

public interface ITokenExchangeService
{
Task<TokenExchangeResponse> Exchange(string accessToken, ApiConfig apiConfig);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
using YarpAuthProxy.BffLibrary.Utils.Config;

namespace YarpAuthProxy.BffLibrary.Services;

public class NullTokenExchangeService : ITokenExchangeService
{
public Task<TokenExchangeResponse> Exchange(string accessToken, ApiConfig apiConfig)
{
var result = new TokenExchangeResponse {
var result = new TokenExchangeResponse
{
access_token = "",
expires_in = 0,
refresh_token = "",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
public class RefreshResponse {
namespace YarpAuthProxy.BffLibrary.Services;

public class RefreshResponse
{
public string access_token { get; set; } = "";
public string id_token { get; set; } = "";
public string refresh_token { get; set; } = "";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
public class TokenExchangeResponse {
namespace YarpAuthProxy.BffLibrary.Services;

public class TokenExchangeResponse
{
public string access_token { get; set; } = "";
public string refresh_token { get; set; } = "";
public long expires_in { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
using System.Net.Http.Json;
using YarpAuthProxy.BffLibrary.Utils.Config;

namespace YarpAuthProxy.BffLibrary.Services;

public class TokenExchangeService : ITokenExchangeService
{
private DiscoveryDocument disco;
Expand Down
Loading