diff --git a/Directory.Build.props b/Directory.Build.props
index 60875f4..a9a9d73 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -6,9 +6,8 @@
- $(MSBuildThisFileDirectory).artifacts\$(MSBuildProjectName)
- $(BaseProjectArtifactPath)\bin\
- $(BaseProjectArtifactPath)\obj\
+ true
+ $(MSBuildThisFileDirectory)_artifacts
diff --git a/Directory.Packages.props b/Directory.Packages.props
index e2dc5b0..c13396d 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -5,10 +5,10 @@
+
-
diff --git a/src/WebApp/Program.cs b/src/WebApp/Program.cs
index 8d92004..19a2def 100644
--- a/src/WebApp/Program.cs
+++ b/src/WebApp/Program.cs
@@ -1,7 +1,8 @@
using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
-using Microsoft.Identity.Web;
-using Microsoft.Identity.Web.UI;
+using Microsoft.IdentityModel.Protocols.OpenIdConnect;
+using Microsoft.IdentityModel.Tokens;
using ServerCheckupLibrary.Checks;
using ServerCheckupLibrary.Hubs;
using WebApp.Platform;
@@ -32,10 +33,29 @@
}
else
{
- // When running on the server, require an Azure AD login account (configured in the app settings file).
+ // When running on the server, require an OIDC login provider (configured in the appsettings file).
builder.Services
- .AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
- .AddMicrosoftIdentityWebApp(builder.Configuration);
+ .AddAuthentication(options =>
+ {
+ options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
+ options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
+ })
+ .AddCookie()
+ .AddOpenIdConnect(configureOptions: options =>
+ {
+ var configSection = builder.Configuration.GetSection("OIDC");
+
+ options.Authority = configSection["Authority"];
+ options.ClientId = configSection["ClientId"];
+ options.ClientSecret = configSection["ClientSecret"];
+ options.CallbackPath = configSection["CallbackPath"];
+
+ options.Scope.Add("email");
+ options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
+ options.ResponseType = OpenIdConnectResponseType.Code;
+ options.MapInboundClaims = false;
+ options.TokenValidationParameters = new TokenValidationParameters { NameClaimType = "email" };
+ });
}
builder.Services.AddAuthorization();
@@ -47,7 +67,7 @@
if (!isDevelopment) builder.Services.AddHsts(opts => opts.MaxAge = TimeSpan.FromDays(730));
// Configure the UI.
-builder.Services.AddRazorPages().AddMicrosoftIdentityUI();
+builder.Services.AddRazorPages();
builder.Services.AddWebOptimizer(minifyJavaScript: !isDevelopment);
// Add HttpClient (used by CheckExternalService)
diff --git a/src/WebApp/WebApp.csproj b/src/WebApp/WebApp.csproj
index 589f63e..8f7c0b4 100644
--- a/src/WebApp/WebApp.csproj
+++ b/src/WebApp/WebApp.csproj
@@ -6,7 +6,7 @@
-
+
@@ -15,10 +15,6 @@
-
- appsettings.json
- Never
-
Never
Never
diff --git a/src/WebApp/appsettings-example.json b/src/WebApp/appsettings-example.json
index b40006a..a3c51d8 100644
--- a/src/WebApp/appsettings-example.json
+++ b/src/WebApp/appsettings-example.json
@@ -58,6 +58,12 @@
"CheckDotnetVersionOptions": {
"Enabled": true
},
+ "OIDC": {
+ "CallbackPath": "/signin-oidc-duo",
+ "Authority ": "[Enter the Duo application endpoint: https://{duo-subdomain}.sso.duosecurity.com/oidc/{ClientId}]",
+ "ClientId": "[Enter the Duo Client ID]",
+ "ClientSecret": "[Enter the Duo Client Secret]"
+ },
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "qualified.domain.name",
diff --git a/src/WebApp/appsettings.json b/src/WebApp/appsettings.json
index 076de84..6874e56 100644
--- a/src/WebApp/appsettings.json
+++ b/src/WebApp/appsettings.json
@@ -19,6 +19,12 @@
"CheckDotnetVersionOptions": {
"Enabled": true
},
+ "OIDC": {
+ "CallbackPath": "/signin-oidc-duo",
+ "Authority ": "",
+ "ClientId": "",
+ "ClientSecret": ""
+ },
"AzureAd": {
"Instance": "",
"Domain": "",
diff --git a/src/WebApp/wwwroot/js/site.js b/src/WebApp/wwwroot/js/site.js
index 896e5c5..df50129 100644
--- a/src/WebApp/wwwroot/js/site.js
+++ b/src/WebApp/wwwroot/js/site.js
@@ -68,31 +68,34 @@ function getContextClass(context) {
function prepCheck(checkSectionId, endPoint) {
const checkEl = document.querySelector(`#${checkSectionId}`);
const buttonEl = checkEl.querySelector('button');
- const resultsEl = checkEl.querySelector('.check-results');
-
- buttonEl.addEventListener('click', function () {
- resultsEl.innerHTML = '';
- const messageListEl = document.createElement('ul');
- messageListEl.className = 'list-group';
- resultsEl.appendChild(messageListEl);
-
- setAsLoading(buttonEl);
- fetch(endPoint)
- .then(response => response.text())
- .then(result => {
- resetAsLoading(buttonEl);
- resultsEl.innerHTML = result;
- })
- .catch(error => {
- resetAsLoading(buttonEl);
- handleCheckResult(checkSectionId, 'An error occurred', error, 'Error');
- if (error instanceof Error) {
- rg4js('send', {error: error, tags: ['handled_promise_rejection']});
- } else {
- console.error(error);
- }
- });
- });
+
+ if (buttonEl) {
+ const resultsEl = checkEl.querySelector('.check-results');
+
+ buttonEl.addEventListener('click', function () {
+ resultsEl.innerHTML = '';
+ const messageListEl = document.createElement('ul');
+ messageListEl.className = 'list-group';
+ resultsEl.appendChild(messageListEl);
+
+ setAsLoading(buttonEl);
+ fetch(endPoint)
+ .then(response => response.text())
+ .then(result => {
+ resetAsLoading(buttonEl);
+ resultsEl.innerHTML = result;
+ })
+ .catch(error => {
+ resetAsLoading(buttonEl);
+ handleCheckResult(checkSectionId, 'An error occurred', error, 'Error');
+ if (error instanceof Error) {
+ rg4js('send', {error: error, tags: ['handled_promise_rejection']});
+ } else {
+ console.error(error);
+ }
+ });
+ });
+ }
}
function setAsLoading(btnEl) {