I'm dipping into Alba over the next couple work days to add some improvements that we want at MedeAnalytics to test HTTP APIs that are going to be secured with JWT Bearer Token authentication that's ultimately backed up by IdentityServer5. I've done some proof of concepts off to the side on how to deal with that in Alba tests with or without the actual identity server up and running, so I know it's possible.
However, when I started looking into how to build a more formal "JWT Token" add on to Alba and catching up with GitHub issues on Alba, it's led me to the conclusion that it's time for a little overhaul of Alba as part of the JWT work that's turning into a proposed Alba v5 release.
Here's what I'm thinking:
Ditch all support < .Net 5.0 just because that makes things easier on me maintaining Alba. Selfishness FTW.
New Alba extension model, more on this below
Revamp the Alba bootstrapping so that it's just an extension method hanging off the end of IHostBuilder that will create a new ITestingHost interface for the existing SystemUnderTest class. More on this below.
Decouple Alba's JSON facilities from Newtonsoft.Json. A couple folks have asked if you can use System.Text.Json with Alba so far, so this time around we'll try to dig into the application itself and find the JSON formatter from the system and make all the JSON serialization "just" use that instead of recreating anything
Enable easy testing of GPRC endpoints like we do for classic JSON services
DevOps changes
Replace the Rake build script with Bullseye
Move the documentation website from stdocs to VitePress with a similar set up as the new Marten website
Retire the existing AppVeyor CI (that works just fine), and move to GitHub actions for CI, but add a new action for publishing Nugets
Bootstrapping Changes
Today you use code like this to bootstrap Alba against your ASP.Net Core application:
var system = new SystemUnderTest(WebApi.Program.CreateHostBuilder(new string[0]));
where Alba's SystemUnderTest intercepts an IHostBuilder, adds some additional configuration, swaps out Kestrel for the ASP.Net Core TestServer, and starts the underlying IHost.
In Alba v5, I'd like to change this a little bit to being an extension method hanging off of IHostBuilder so you'd have something more like this:
var host = WebApi.Program.CreateHostBuilder(new string[0]).StartAlbaHost();
// or
var host = await WebApi.Program.CreateHostBuilder(new string[0]).StartAlbaHostAsync();
The host above would be this new interface (still the old SystemUnderTest under the covers):
public interface IAlbaHost : IHost
{
Task<ScenarioResult> Scenario(Action<Scenario> configure);
// various methods to register actions to run before or after any scenario is executed
}
Extension Model
Right now the only extension I have in mind is one for JWT tokens, but it probably goes into a separate Nuget, so here you go.
public interface ITestingHostExtension : IDisposable, IAsyncDisposable
{
// Make any necessary registrations to the actual application
IHostBuilder Configure(IHostBuilder builder);
// Spin it up if necessary before any scenarios are run, also gives
// an extension a chance to add any BeforeEach() / AfterEach() kind
// of hooks to the Scenario or HttpContext
ValueTask Start(ITestingHost host);
}
My thought is that ITestingHostExtension objects would be passed into the StartAlbaHost(params ITestingHostExtension[] extensions) method from above.
JWT Bearer Token Extension
This will probably need to be in a separate Alba.JwtTokens Nuget library.
Extension method on Scenario to add a bearer token to the Authorization header. Small potatoes.
Helper of some sort to fetch JWT tokens from an external identity server and use that token on further scenario runs. I've got this prototyped already
a new Alba extension that acts as a stubbed identity server. More below:
For the stubbed in identity server, what I'm thinking is that a registered IdentityServerStub extension would:
Spin up a small fake OIDC web application hosted in memory w/ Kestrel that responds to the basic endpoints to validate JWT tokens.
With this extension, Alba will quietly stick a JWT token into the Authorization header of each request so you can test API endpoints that are secured by bearer tokens
Reaches into the system under test's IHostBuilder and sets the authority url to the local Url of the stubbed OIDC server (I've already successfully prototyped this one)
Also reaches into the system under test to find the JwtBearerOptions as configured and uses the signing keys that are already configured for the application for the JWT generation. That should make the setup of this quite a bit simpler
The new JWT stub extension can be configured with baseline claims that would be part of any generated JWT
A new extension method on Scenario to add or override claims in the JWT tokens on a per-scenario basis to support fine-grained authorization testing in your API tests
An extension method on Scenario to disable the JWT header altogether so you can test out authentication failures
Probably need a facility of some sort to override the JWT expiration time as well
I'm dipping into Alba over the next couple work days to add some improvements that we want at MedeAnalytics to test HTTP APIs that are going to be secured with JWT Bearer Token authentication that's ultimately backed up by IdentityServer5. I've done some proof of concepts off to the side on how to deal with that in Alba tests with or without the actual identity server up and running, so I know it's possible.
However, when I started looking into how to build a more formal "JWT Token" add on to Alba and catching up with GitHub issues on Alba, it's led me to the conclusion that it's time for a little overhaul of Alba as part of the JWT work that's turning into a proposed Alba v5 release.
Here's what I'm thinking:
IHostBuilder
that will create a newITestingHost
interface for the existingSystemUnderTest
class. More on this below.DevOps changes
Bootstrapping Changes
Today you use code like this to bootstrap Alba against your ASP.Net Core application:
where Alba's
SystemUnderTest
intercepts anIHostBuilder
, adds some additional configuration, swaps out Kestrel for the ASP.Net CoreTestServer
, and starts the underlyingIHost
.In Alba v5, I'd like to change this a little bit to being an extension method hanging off of
IHostBuilder
so you'd have something more like this:The
host
above would be this new interface (still the oldSystemUnderTest
under the covers):Extension Model
Right now the only extension I have in mind is one for JWT tokens, but it probably goes into a separate Nuget, so here you go.
My thought is that
ITestingHostExtension
objects would be passed into theStartAlbaHost(params ITestingHostExtension[] extensions)
method from above.JWT Bearer Token Extension
This will probably need to be in a separate
Alba.JwtTokens
Nuget library.Scenario
to add a bearer token to theAuthorization
header. Small potatoes.For the stubbed in identity server, what I'm thinking is that a registered
IdentityServerStub
extension would:Authorization
header of each request so you can test API endpoints that are secured by bearer tokensIHostBuilder
and sets the authority url to the local Url of the stubbed OIDC server (I've already successfully prototyped this one)JwtBearerOptions
as configured and uses the signing keys that are already configured for the application for the JWT generation. That should make the setup of this quite a bit simplerScenario
to add or override claims in the JWT tokens on a per-scenario basis to support fine-grained authorization testing in your API tests