Skip to content
Merged
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
11 changes: 11 additions & 0 deletions docs/core.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,24 @@ var builder = WebApplication.CreateBuilder();
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddSystemWebAdapters()
<<<<<<< HEAD
.AddJsonSessionKeySerializer(options => ClassLibrary.SessionUtils.RegisterSessionKeys(options))
.AddRemoteClientApp(remote => remote
.Configure(options =>
{
options.RemoteApp = new(builder.Configuration["ReverseProxy:Clusters:fallbackCluster:Destinations:fallbackApp:Address"]);
options.ApiKey = ClassLibrary.SessionUtils.ApiKey;
})
.AddSession();
=======
.AddRemoteApp(options =>
{
options.RemoteAppUrl = new(builder.Configuration["ReverseProxy:Clusters:fallbackCluster:Destinations:fallbackApp:Address"]);
options.ApiKey = ClassLibrary.SessionUtils.ApiKey;
})
.AddRemoteAppSession()
.AddJsonSessionSerializer(options => ClassLibrary.SessionUtils.RegisterSessionKeys(options));
>>>>>>> origin/main

var app = builder.Build();

Expand Down
7 changes: 7 additions & 0 deletions docs/framework.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,16 @@ protected void Application_Start()

SystemWebAdapterConfiguration.AddSystemWebAdapters(this)
.AddProxySupport(options => options.UseForwardedHeaders = true)
<<<<<<< HEAD
.AddJsonSessionSerializer(options => ClassLibrary.RemoteServiceUtils.RegisterSessionKeys(options.KnownKeys))
.AddRemoteAppServer(remote => remote
.Configure(options => options.ApiKey = ClassLibrary.RemoteServiceUtils.ApiKey)
.AddSession());
=======
.AddRemoteApp(options => options.ApiKey = ClassLibrary.SessionUtils.ApiKey)
.AddRemoteAppSession()
.AddJsonSessionSerializer(options => ClassLibrary.SessionUtils.RegisterSessionKeys(options.KnownKeys));
>>>>>>> origin/main
}
```

Expand Down
24 changes: 24 additions & 0 deletions docs/remote-authentication/remote-authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ There are just a few small code changes needed to enable remote authentication i

### ASP.NET app configuration

<<<<<<< HEAD
First, the ASP.NET app needs to be configured to add the authentication endpoint. This is done by calling the `AddRemoteAppServer` extension method on the `ISystemWebAdapterBuilder`:

```CSharp
SystemWebAdapterConfiguration.AddSystemWebAdapters(this)
.AddRemoteAppServer(remote => remote
.Configure(options => options.ApiKey = ClassLibrary.RemoteServiceUtils.ApiKey)
.AddAuthentication());
=======
First, the ASP.NET app needs to be configured to add the authentication endpoint. This is done by calling the `AddRemoteApp` extension method on the `ISystemWebAdapterBuilder` to configure receiving remote calls, and by calling `AddRemoteAuthentication` to set up the HTTP module that will watch for requests to the authentication endpoint. Note that remote authentication scenarios typically want to add proxy support, as well, so that any auth-related redirects will correctly route to the ASP.NET Core app rather than the ASP.NET one.

```CSharp
Expand All @@ -18,12 +27,26 @@ SystemWebAdapterConfiguration.AddSystemWebAdapters(this)
options.ApiKey = "MySecretKey";
})
.AddRemoteAppAuthentication();
>>>>>>> origin/main
```

In the options configuration method passed to the `AddRemoteApp` call, you must specify an API key which is used to secure the endpoint so that only trusted callers can make requests to it (this same API key will be provided to the ASP.NET Core app when it is configured).

### ASP.NET Core app configuration

<<<<<<< HEAD
Next, the ASP.NET Core app needs to be configured to enable the authentication handler that will authenticate users by making an HTTP request to the ASP.NET app. This is done by calling `AddRemoteAppClient` when registering System.Web adapters services:

```CSharp
builder.Services.AddSystemWebAdapters()
.AddRemoteAppClient(remote => remote
.Configure(options =>
{
options.RemoteAppUrl = new(builder.Configuration["ReverseProxy:Clusters:fallbackCluster:Destinations:fallbackApp:Address"]);
options.ApiKey = "MySecretKey";
})
.AddAuthentication(true));
=======
Next, the ASP.NET Core app needs to be configured to enable the authentication handler that will authenticate users by making an HTTP request to the ASP.NET app. Again, this is done by calling `AddRemoteApp` and `AddRemoteAppAuthentication` when registering System.Web adapters services:

```CSharp
Expand All @@ -34,6 +57,7 @@ builder.Services.AddSystemWebAdapters()
options.ApiKey = "MySecretKey";
})
.AddRemoteAppAuthentication(true);
>>>>>>> origin/main
```

The `AddRemoteApp` call is used to configure the remote app's URL and the shared secret API key.
Expand Down
21 changes: 21 additions & 0 deletions docs/session-state/remote-session.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ Configuration for ASP.NET Core would look similar to the following:

```csharp
builder.Services.AddSystemWebAdapters()
<<<<<<< HEAD
.AddRemoteAppClient(remote => remote
.Configure(options =>
{
options.RemoteAppUrl = new(builder.Configuration["ReverseProxy:Clusters:fallbackCluster:Destinations:fallbackApp:Address"]);
options.ApiKey = ClassLibrary.RemoteServiceUtils.ApiKey;
})
.AddSession())
=======
.AddRemoteApp(options =>
{
// Provide the URL for the remote app that has enabled session querying
Expand All @@ -34,6 +43,7 @@ builder.Services.AddSystemWebAdapters()
options.ApiKey = "strong-api-key";
})
.AddRemoteAppSession()
>>>>>>> origin/main
.AddJsonSessionSerializer(options =>
{
// Serialization/deserialization requires each session key to be registered to a type
Expand Down Expand Up @@ -65,15 +75,26 @@ The framework equivalent would look like the following change in `Global.asax.cs

```csharp
SystemWebAdapterConfiguration.AddSystemWebAdapters(this)
<<<<<<< HEAD
.AddProxySupport(options => options.UseForwardedHeaders = true)
=======
// Provide a strong API key that will be used to authenticate the request on the remote app for querying the session
.AddRemoteApp(options => options.ApiKey = "strong-api-key")
.AddRemoteAppSession()
>>>>>>> origin/main
.AddJsonSessionSerializer(options =>
{
// Serialization/deserialization requires each session key to be registered to a type
options.RegisterKey<int>("test-value");
options.RegisterKey<SessionDemoModel>("SampleSessionItem");
<<<<<<< HEAD
})
.AddRemoteAppServer(remote => remote
.Configure(options => options.ApiKey = ClassLibrary.RemoteServiceUtils.ApiKey)
.AddSession());
=======
});
>>>>>>> origin/main
```
# Protocol

Expand Down
10 changes: 4 additions & 6 deletions samples/MvcApp/Global.asax.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ protected void Application_Start()

SystemWebAdapterConfiguration.AddSystemWebAdapters(this)
.AddProxySupport(options => options.UseForwardedHeaders = true)
.AddRemoteApp(options =>
{
options.ApiKey = ClassLibrary.RemoteServiceUtils.ApiKey;
})
.AddRemoteAppSession()
.AddJsonSessionSerializer(options => ClassLibrary.RemoteServiceUtils.RegisterSessionKeys(options.KnownKeys))
.AddRemoteAppAuthentication();
.AddRemoteAppServer(remote => remote
.Configure(options => options.ApiKey = ClassLibrary.RemoteServiceUtils.ApiKey)
.AddAuthentication()
.AddSession());
}
}
}
17 changes: 9 additions & 8 deletions samples/MvcCoreApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddSystemWebAdapters()
.AddRemoteApp(options =>
{
options.RemoteAppUrl = new(builder.Configuration["ReverseProxy:Clusters:fallbackCluster:Destinations:fallbackApp:Address"]);
options.ApiKey = ClassLibrary.RemoteServiceUtils.ApiKey;
})
.AddRemoteAppSession()
.AddJsonSessionSerializer(options => ClassLibrary.RemoteServiceUtils.RegisterSessionKeys(options.KnownKeys))
.AddRemoteAppAuthentication(true);
.AddRemoteAppClient(remote => remote
.Configure(options =>
{
options.RemoteAppUrl = new(builder.Configuration["ReverseProxy:Clusters:fallbackCluster:Destinations:fallbackApp:Address"]);
options.ApiKey = ClassLibrary.RemoteServiceUtils.ApiKey;
})
.AddAuthentication(true)
.AddSession())
.AddJsonSessionSerializer(options => ClassLibrary.RemoteServiceUtils.RegisterSessionKeys(options.KnownKeys));

var app = builder.Build();

Expand Down
15 changes: 8 additions & 7 deletions samples/RemoteAuth/Bearer/RemoteBearer/Global.asax.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ protected void Application_Start()
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

SystemWebAdapterConfiguration.AddSystemWebAdapters(this)
.AddRemoteApp(options =>
{
// A real application would not hard code this, but load it
// securely from environment or configuration
options.ApiKey = "TopSecretString";
})
.AddRemoteAppAuthentication();
.AddRemoteAppServer(remote => remote
.Configure(options =>
{
// A real application would not hard code this, but load it
// securely from environment or configuration
options.ApiKey = "TopSecretString";
})
.AddAuthentication());
}
}
}
28 changes: 15 additions & 13 deletions samples/RemoteAuth/Bearer/RemoteBearerCore/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@
builder.Services.AddControllers();

builder.Services.AddSystemWebAdapters()
.AddRemoteApp(options =>
{
options.RemoteAppUrl = new(builder.Configuration["ReverseProxy:Clusters:fallbackCluster:Destinations:fallbackApp:Address"]);

// A real application would not hard code this, but load it
// securely from environment or configuration
options.ApiKey = "TopSecretString";
})
// This registers the remote app authentication handler. The boolean argument indicates whether remote app auth
// should be the default scheme. If it is set to false, HTTP requests to authenticate will only be made for
// endpoints that actually need that behavior, but it is then necessary to annotate endpoints requiring remote app
// auth with [Authorize(AuthenticationSchemes = RemoteAppAuthenticationDefaults.AuthenticationScheme)] or something similar.
.AddRemoteAppAuthentication(isDefaultScheme: true);
.AddRemoteAppClient(remote => remote
.Configure(options =>
{
options.RemoteAppUrl = new(builder.Configuration["ReverseProxy:Clusters:fallbackCluster:Destinations:fallbackApp:Address"]);

// A real application would not hard code this, but load it
// securely from environment or configuration
options.ApiKey = "TopSecretString";
})

// This registers the remote app authentication handler. The boolean argument indicates whether remote app auth
// should be the default scheme. If it is set to false, HTTP requests to authenticate will only be made for
// endpoints that actually need that behavior, but it is then necessary to annotate endpoints requiring remote app
// auth with [Authorize(AuthenticationSchemes = RemoteAppAuthenticationDefaults.AuthenticationScheme)] or something similar.
.AddAuthentication(isDefaultScheme: true));

var app = builder.Build();

Expand Down
11 changes: 6 additions & 5 deletions samples/RemoteAuth/Forms/FormsAuth/Global.asax.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ void Application_Start(object sender, EventArgs e)

SystemWebAdapterConfiguration.AddSystemWebAdapters(this)
.AddProxySupport(options => options.UseForwardedHeaders = true)
.AddRemoteApp(options =>
{
options.ApiKey = "FormsAuthSampleKey";
})
.AddRemoteAppAuthentication();
.AddRemoteAppServer(remote => remote
.Configure(options =>
{
options.ApiKey = "FormsAuthSampleKey";
})
.AddAuthentication());
}
}
}
14 changes: 7 additions & 7 deletions samples/RemoteAuth/Forms/FormsAuthCore/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Microsoft.AspNetCore.SystemWebAdapters;
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddReverseProxy().LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
Expand All @@ -8,12 +7,13 @@

// Add System.Web adapter services, including registering remote app authentication
builder.Services.AddSystemWebAdapters()
.AddRemoteApp(options =>
{
options.RemoteAppUrl = new(builder.Configuration["ReverseProxy:Clusters:fallbackCluster:Destinations:fallbackApp:Address"]);
options.ApiKey = "FormsAuthSampleKey";
})
.AddRemoteAppAuthentication(true);
.AddRemoteAppClient(remote => remote
.Configure(options =>
{
options.RemoteAppUrl = new(builder.Configuration["ReverseProxy:Clusters:fallbackCluster:Destinations:fallbackApp:Address"]);
options.ApiKey = "FormsAuthSampleKey";
})
.AddAuthentication(true));

var app = builder.Build();

Expand Down
8 changes: 3 additions & 5 deletions samples/RemoteAuth/OIDC/OIDCAuth/Global.asax.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
Expand All @@ -19,8 +16,9 @@ protected void Application_Start()

SystemWebAdapterConfiguration.AddSystemWebAdapters(this)
.AddProxySupport(options => options.UseForwardedHeaders = true)
.AddRemoteApp(options => options.ApiKey = "test-key")
.AddRemoteAppAuthentication();
.AddRemoteAppServer(remote => remote
.Configure(options => options.ApiKey = "test-key")
.AddAuthentication());

}
}
Expand Down
14 changes: 7 additions & 7 deletions samples/RemoteAuth/OIDC/OIDCAuthCore/Program.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSystemWebAdapters()
.AddRemoteApp(options =>
{
options.RemoteAppUrl =
new(builder.Configuration["ReverseProxy:Clusters:fallbackCluster:Destinations:fallbackApp:Address"]);
options.ApiKey = "test-key";
})
.AddRemoteAppAuthentication(true);
.AddRemoteAppClient(remote => remote
.Configure(options =>
{
options.RemoteAppUrl = new(builder.Configuration["ReverseProxy:Clusters:fallbackCluster:Destinations:fallbackApp:Address"]);
options.ApiKey = "test-key";
})
.AddAuthentication(true));

builder.Services.AddReverseProxy().LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace System.Web;

public static class RemoteAppSessionStateExtensions
{
public static ISystemWebAdapterBuilder AddRemoteAppSession(this ISystemWebAdapterBuilder builder, Action<RemoteAppSessionStateOptions>? configureRemote = null)
public static ISystemWebAdapterRemoteServerAppBuilder AddSession(this ISystemWebAdapterRemoteServerAppBuilder builder, Action<RemoteAppSessionStateServerOptions>? configureRemote = null)
{
if (builder is null)
{
Expand All @@ -23,7 +23,7 @@ public static ISystemWebAdapterBuilder AddRemoteAppSession(this ISystemWebAdapte
builder.Services.AddOptions<SessionSerializerOptions>()
// We don't want to throw by default on the .NET Framework side as then the error won't be easily visible in the ASP.NET Core app
.Configure(options => options.ThrowOnUnknownSessionKey = false);
var options = builder.Services.AddOptions<RemoteAppSessionStateOptions>();
var options = builder.Services.AddOptions<RemoteAppSessionStateServerOptions>();

if (configureRemote is not null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ namespace Microsoft.AspNetCore.SystemWebAdapters.SessionState.RemoteSession;
internal sealed class RemoteSessionModule : IHttpModule
{
private readonly RemoteAppOptions _remoteAppOptions;
private readonly RemoteAppSessionStateOptions _sessionOptions;
private readonly RemoteAppSessionStateServerOptions _sessionOptions;
private readonly ReadOnlySessionHandler _readonlyHandler;
private readonly GetWriteableSessionHandler _writeableHandler;
private readonly StoreSessionStateHandler _saveHandler;

public RemoteSessionModule(IOptions<RemoteAppSessionStateOptions> sessionOptions, IOptions<RemoteAppOptions> remoteAppOptions, ILockedSessionCache cache, ISessionSerializer serializer)
public RemoteSessionModule(IOptions<RemoteAppSessionStateServerOptions> sessionOptions, IOptions<RemoteAppOptions> remoteAppOptions, ILockedSessionCache cache, ISessionSerializer serializer)
{
_sessionOptions = sessionOptions?.Value ?? throw new ArgumentNullException(nameof(sessionOptions));
_remoteAppOptions = remoteAppOptions?.Value ?? throw new ArgumentNullException(nameof(remoteAppOptions));
Expand Down Expand Up @@ -78,5 +78,5 @@ public void Dispose()
}

private static bool GetIsReadonly(HttpRequestBase request)
=> bool.TryParse(request.Headers.Get(RemoteAppSessionStateOptions.ReadOnlyHeaderName), out var result) && result;
=> bool.TryParse(request.Headers.Get(SessionConstants.ReadOnlyHeaderName), out var result) && result;
}
Loading