Skip to content

Testing Security Utilities

Dennis C. Mitchell edited this page Apr 22, 2019 · 4 revisions

At some point in the development process, developers add security to their applications. Because this added security can present additional hurdles during focused testing, developers sometimes wait until relatively late in the development process to add the security. Other times, developers toggle between commented and uncommented security code. Either way, testing with security in place can be awkward or annoying.

EDennis.AspNetCore.Base provides two middleware classes that are designed to improve the testing experience when security is in place. AutoLoginMiddleware is provided to automatically build a user principal from a set of predefined users with configured claims. MockClientAuthorizationMiddleware is provided to automatically retrieve an access token (for an API) from an Identity Server instance, using a client from a set of predefined clients with configured claims. These middleware classes can be configured to work with different launch profiles for test users or clients with different claims.

AutoLoginMiddleware

AutoLoginMiddleware is ASP.NET Core middleware that builds a user principal with one or more claims. Each mock user is configured in appsettings.Development.json. Optionally, the developer can setup separate launch profiles for each mock user.

IConfiguration

The appsettings.Development.json file must contain an "AutoLogin" section in which one or more mock users are defined. Each user must have a "Claims" property, which holds an array of MockClaim objects (properties = Type, Value). If more than one mock user is defined and no AutoLogin launch settings are active, then the mock user having the property "Default" equal to true is selected.

Example

{
  "AutoLogin": {
    "alice": {
      "Default": true,
      "Claims": [
        {
          "Type": "role",
          "Value": "admin"
        }
      ]
    },
    "bob": {
      "Claims": [
        {
          "Type": "role",
          "Value": "readonly"
        }
      ]
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

Startup.Configure

The current library has an IApplicationBuilder extension method named UseAutoLogin that registers the AutoLoginMiddleware in the application pipeline. The call to this method must be placed before the call to UseAuthentication in the Configure method of the application's Startup class.

Example

public void Configure(IApplicationBuilder app, IHostingEnvironment env) {

    //...
    //some code omitted

    app.UseCookiePolicy();

    if (env.IsDevelopment()) {
        app.UseAutoLogin();
    }

    app.UseAuthentication();
    app.UseMvc();
}

Optional Launch Profile Configuration

Often, an application will have multiple user roles. To facilitate testing of these roles, the current library supports configuration of AutoLogin users as separate launch profiles in launchSettings.json. The launch profile configuration requires the inclusion of a commandLineArgs property, where the argument AutoLogin is set to the name of one of the mock users defined in appsettings.Development.json.

Example

  "profiles": {
    "AutoLogin=bob": {
      "commandName": "Project",
      "launchBrowser": true,
      "commandLineArgs": "AutoLogin=bob",
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "AutoLogin=alice": {
      "commandName": "Project",
      "launchBrowser": true,
      "commandLineArgs": "AutoLogin=alice",
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

MockClientAuthorizationMiddleware

MockClientAuthorizationMiddleware is ASP.NET Core middleware that requests an access token from an Identity Server for a particular client and a specific scope (or set of scopes). Each mock client is configured in appsettings.Development.json. Optionally, the developer can setup separate launch profiles for each mock client.

IConfiguration

The appsettings.Development.json file must contain a "MockClient" section in which one or more mock clients are defined. Each mock client is a section whose key corresponds to the ClientId configured in Identity Server. Each mock client section must have a Secret property whose value is set to the Client's secret that is stored in Identity Server. Finally, each mock client must have a Scopes property that is an array of scope claim values that correspond to the scopes defined in Identity Server (for both the Client and the ApiResource). In order for the mock client to access a defined API, the API must be configured in the Apis section of appsettings.Development.json and be defined as an ApiResource in Identity Server.

{
  "ConnectionStrings": {
    "HrContext": "Server=(localdb)\\mssqllocaldb;Database=Hr;Trusted_Connection=True;",
    "HrHistoryContext": "Server=(localdb)\\mssqllocaldb;Database=Hr;Trusted_Connection=True;"
  },
  "Apis": {
    "IdentityServer": {
      "ProjectName": "IdentityServer",
      "SolutionName": "EDennis.AspNetCore.Base",
      "BaseAddress": null,
      "Secret": null
    }
  },
  "MockClient": {
    "Client1": {
      "Secret": "secret",
      "Scopes": [
        "EDennis.Samples.Hr.InternalApi1"
      ]
    },
    "Client2": {
      "Secret": "secret",
      "Scopes": [
        "EDennis.Samples.Hr.InternalApi1.Employee"
      ]
    },
    "Client3": {
      "Secret": "secret",
      "Scopes": [
        "EDennis.Samples.Hr.InternalApi1.Employee.GetEmployee",
        "EDennis.Samples.Hr.InternalApi1.Employee.GetEmployees"
      ]
    }
  },
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

Startup.Configure

The current library has an IApplicationBuilder extension method named UseMockClientAuthorization that registers the AutoLoginMiddleware in the application pipeline. The call to this method must be placed before the call to UseAuthentication in the Configure method of the application's Startup class.

Example

public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
    if (env.IsDevelopment()) {
        app.UseMockClientAuthorization();
       //...
       //some code omitted
    }

    app.UseAuthentication();
    app.UseMvc();
}

Optional Launch Profile Configuration (launchSettings.json)

Example

To facilitate testing of multiple clients, the current library supports configuration of mock clients as separate launch profiles in launchSettings.json. The launch profile configuration requires the inclusion of a commandLineArgs property, where the argument MockClient is set to the name of one of the mock clients defined in appsettings.Development.json.

{
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "iisSettings": {
    "windowsAuthentication": false, 
    "anonymousAuthentication": true, 
    "iisExpress": {
      "applicationUrl": "http://localhost:5000",
      "sslPort": 0
    }
  },
  "profiles": {
    "MockClient=Client1": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "applicationUrl": "http://localhost:5006",
      "commandLineArgs": "MockClient=Client1",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "MockClient=Client2": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "applicationUrl": "http://localhost:5006",
      "commandLineArgs": "MockClient=Client2",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "MockClient=Client3": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "applicationUrl": "http://localhost:5006",
      "commandLineArgs": "MockClient=Client3",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

Clone this wiki locally