diff --git a/source-code/Pages/SP/AssertionConsumer.cshtml.cs b/source-code/Pages/SP/AssertionConsumer.cshtml.cs
index d1570b1..04fb61f 100755
--- a/source-code/Pages/SP/AssertionConsumer.cshtml.cs
+++ b/source-code/Pages/SP/AssertionConsumer.cshtml.cs
@@ -11,29 +11,29 @@ namespace SAMLTEST.Pages.SP
///
/// This is the Assertion Consumer Page Model
/// This page will be posted to from outside this application
- /// thuys the Ignore Anti Forgery Token below
+ /// thus the Ignore Anti Forgery Token below
///
[IgnoreAntiforgeryToken(Order = 1001)]
public class AssertionConsumerModel : PageModel
{
- public String SessionId { get; private set; }
+ public string SessionId { get; private set; }
- public String SAMLResponse { get; private set; }
- public Dictionary attrsandvals { get; private set; }
+ public string SAMLResponse { get; private set; }
+ public Dictionary Attrsandvals { get; private set; }
- public String TenantId { get; private set; }
- public String PolicyId { get; private set; }
- public String NameId { get; private set; }
+ public string TenantId { get; private set; }
+ public string PolicyId { get; private set; }
+ public string NameId { get; private set; }
- public String DCInfo { get; private set; }
- public String Issuer { get; private set; }
+ public string DCInfo { get; private set; }
+ public string Issuer { get; private set; }
- public IActionResult OnPost(string SAMLResponse, string RelayState)
+ public IActionResult OnPost(string samlResponse, string relayState)
{
//Get Tenant, Policy, Issuer and DCInfo from RelayState
- if (!String.IsNullOrWhiteSpace(RelayState))
+ if (!string.IsNullOrWhiteSpace(relayState))
{
- string[] RelayStateBits = RelayState.Split(".");
+ string[] RelayStateBits = relayState.Split(".");
this.TenantId = SAMLHelper.fromB64(RelayStateBits[0]);
this.PolicyId = SAMLHelper.fromB64(RelayStateBits[1]);
this.Issuer = SAMLHelper.fromB64(RelayStateBits[2]);
@@ -48,10 +48,10 @@ public IActionResult OnPost(string SAMLResponse, string RelayState)
}
}
- byte[] ENcSAMLByteArray = Convert.FromBase64String(SAMLResponse);
- String sml = System.Text.ASCIIEncoding.ASCII.GetString(ENcSAMLByteArray);
- XmlDocument doc = new XmlDocument();
- XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
+ byte[] ENcSAMLByteArray = Convert.FromBase64String(samlResponse);
+ var sml = System.Text.ASCIIEncoding.ASCII.GetString(ENcSAMLByteArray);
+ var doc = new XmlDocument();
+ var nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion");
nsmgr.AddNamespace("samlp", "urn:oasis:names:tc:SAML:2.0:protocol");
doc.LoadXml(sml);
@@ -64,30 +64,31 @@ public IActionResult OnPost(string SAMLResponse, string RelayState)
return Redirect("/Error?ErrorMessage=" + statusMessage);
}
- XmlNodeList nodes = root.SelectNodes("/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute", nsmgr);
- this.attrsandvals = new Dictionary();
+ XmlNodeList nodes = root.SelectNodes("/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute", nsmgr);
+ this.Attrsandvals = new Dictionary();
foreach (XmlNode node in nodes)
{
- String attrname = node.Attributes["Name"].Value;
- String val = "";
+ var attributeName = node.Attributes["Name"].Value;
+ var val = string.Empty;
if (node.HasChildNodes && node.ChildNodes.Count > 1)
{
var values = node.ChildNodes.Cast()
- .Select(item => item.InnerText).ToList();
+ .Select(item => item.InnerText)
+ .ToList();
val = string.Join(" ", values);
}
else
{
val = node.InnerText;
}
- this.attrsandvals.Add(attrname, val);
+ this.Attrsandvals.Add(attributeName, val);
}
this.SAMLResponse = sml;
this.SessionId = root.SelectSingleNode("/samlp:Response/saml:Assertion/saml:AuthnStatement/@SessionIndex", nsmgr).Value;
this.NameId = root.SelectSingleNode("/samlp:Response/saml:Assertion/saml:Subject/saml:NameID", nsmgr).InnerText;
return Page();
-
+
}
}
}
\ No newline at end of file
diff --git a/source-code/Pages/SP/Index.cshtml.cs b/source-code/Pages/SP/Index.cshtml.cs
index 5255af5..c240f61 100755
--- a/source-code/Pages/SP/Index.cshtml.cs
+++ b/source-code/Pages/SP/Index.cshtml.cs
@@ -1,7 +1,8 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
-using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Options;
+using SAMLTEST.Models;
using SAMLTEST.SAMLObjects;
using System;
using System.ComponentModel;
@@ -19,112 +20,124 @@ public class IndexModel : PageModel
[DisplayName("Tenant Name"), Required]
- public string Tenant { get; set; } = "azureadb2ctests";
+ public string Tenant { get; set; }
[DisplayName("Host Name"), Required]
- public string HostName { get; set; } = "azureadb2ctests.b2clogin.com";
+ public string HostName { get; set; }
- [DisplayName("B2C Policy"),Required]
- public string Policy { get; set; } = "B2C_1A_SignUpOrSignin_SamlApp_Local";
-
+ [DisplayName("B2C Policy"), Required]
+ public string Policy { get; set; }
[DisplayName("Issuer")]
- public string Issuer { get; set; } = "https://azureadb2ctests.onmicrosoft.com/samlAPPUITest";
+ public string Issuer { get; set; }
[DisplayName("DCInfo")]
- public string DCInfo { get; set; } = "";
+ public string DCInfo { get; set; }
- private readonly IConfiguration _configuration;
+ private readonly AzureAdB2C _azureAdB2C;
///
/// This Constructor is used to retrieve the Appsettings data
///
- public IndexModel(IConfiguration configuration)
+ public IndexModel(IOptions options)
{
- _configuration = configuration;
+ _azureAdB2C = options.Value;
+ Tenant = _azureAdB2C.Tenant;
+ HostName = _azureAdB2C.HostName;
+ Policy = _azureAdB2C.Policy;
+ Issuer = _azureAdB2C.Issuer;
+ DCInfo = _azureAdB2C.DCInfo;
}
- public IActionResult OnGet(string Tenant, string HostName, string Policy, string Issuer)
+ public IActionResult OnGet(string tenant, string hostName, string policy, string issuer)
{
- this.Tenant = HttpContext.Session.GetString("Tenant");
- this.HostName = HttpContext.Session.GetString("HostName");
- this.Policy = HttpContext.Session.GetString("Policy");
- this.Issuer = HttpContext.Session.GetString("Issuer");
- if (!string.IsNullOrEmpty(Tenant)) {
- this.Tenant = Tenant;
+ // Try to get values from the sessions, if none then use the default values
+ this.Tenant = string.IsNullOrEmpty(HttpContext.Session.GetString("Tenant")) ? this.Tenant : HttpContext.Session.GetString("Tenant");
+ this.HostName = string.IsNullOrEmpty(HttpContext.Session.GetString("HostName")) ? this.HostName : HttpContext.Session.GetString("HostName");
+ this.Policy = string.IsNullOrEmpty(HttpContext.Session.GetString("Policy")) ? this.Policy : HttpContext.Session.GetString("Policy");
+ this.Issuer = string.IsNullOrEmpty(HttpContext.Session.GetString("Issuer")) ? this.Issuer : HttpContext.Session.GetString("Issuer");
+ // Override the values with the query string values
+ if (!string.IsNullOrEmpty(tenant))
+ {
+ this.Tenant = tenant;
}
- if (!string.IsNullOrEmpty(HostName))
+ if (!string.IsNullOrEmpty(hostName))
{
- this.HostName = HostName;
+ this.HostName = hostName;
}
// if still null, build up hostname yourtenant.b2clogin.com from tenant name yourtenant.onmicrosoft.com
- if (string.IsNullOrEmpty(this.HostName) )
+ if (string.IsNullOrEmpty(this.HostName))
{
string TenantName = this.Tenant.ToLower()?.Replace(".onmicrosoft.com", "");
this.HostName = TenantName + ".b2clogin.com";
}
- if (!string.IsNullOrEmpty(Policy)) {
- this.Policy = Policy;
+ if (!string.IsNullOrEmpty(policy))
+ {
+ this.Policy = policy;
}
- if (!string.IsNullOrEmpty(Issuer)) {
- this.Issuer = Issuer;
+ if (!string.IsNullOrEmpty(issuer))
+ {
+ this.Issuer = issuer;
}
- if ( null != this.Tenant) HttpContext.Session.SetString("Tenant", this.Tenant);
- if ( null != this.HostName) HttpContext.Session.SetString("HostName", this.HostName);
- if ( null != this.Policy) HttpContext.Session.SetString("Policy", this.Policy);
- if ( null != this.Issuer ) HttpContext.Session.SetString("Issuer", this.Issuer);
+ // Save the values to the session for the future use
+ if (null != this.Tenant) HttpContext.Session.SetString("Tenant", this.Tenant);
+ if (null != this.HostName) HttpContext.Session.SetString("HostName", this.HostName);
+ if (null != this.Policy) HttpContext.Session.SetString("Policy", this.Policy);
+ if (null != this.Issuer) HttpContext.Session.SetString("Issuer", this.Issuer);
return Page();
}
///
/// This Post Action is used to Generate the AuthN Request and redirect to the B2C Login endpoint
///
- public IActionResult OnPost(string Tenant, string HostName, string Policy, string Issuer, string DCInfo, bool IsAzureAD)
+ public IActionResult OnPost(string tenant, string hostName, string policy, string issuer, string dcInfo, bool isAzureAD)
{
- if (string.IsNullOrEmpty(Policy) || IsAzureAD)
+ if (string.IsNullOrEmpty(policy) || isAzureAD)
{
- return SendAzureAdRequest(Tenant);
+ return SendAzureAdRequest(tenant);
}
- string SamlRequest = string.Empty;
- string b2cloginurl = HostName.ToLower();
- if (!String.IsNullOrEmpty(HostName))
+ string b2cloginurl = hostName.ToLower();
+ if (!string.IsNullOrEmpty(hostName))
{
- b2cloginurl = HostName;
+ b2cloginurl = hostName;
}
- else if (!String.IsNullOrEmpty(this.Tenant) && this.Tenant.EndsWith(".onmicrosoft.com"))
+ else if (!string.IsNullOrEmpty(this.Tenant) && this.Tenant.EndsWith(".onmicrosoft.com"))
{
- string TenantName = Tenant.ToLower()?.Replace(".onmicrosoft.com", "");
+ string TenantName = tenant.ToLower()?.Replace(".onmicrosoft.com", "");
b2cloginurl = TenantName + ".b2clogin.com";
}
- Policy = Policy.StartsWith("B2C_1A_") ? Policy : "B2C_1A_" + Policy;
- //Tenant = (Tenant.ToLower().Contains("onmicrosoft.com") || Tenant.ToLower().Contains(".net")) ? Tenant : Tenant + ".onmicrosoft.com";
- DCInfo = string.IsNullOrWhiteSpace(DCInfo) ? string.Empty : "&" + DCInfo;
- Issuer = string.IsNullOrWhiteSpace(Issuer) ? SAMLHelper.GetThisURL(this) : Issuer;
+ policy = policy.StartsWith("B2C_1A_") ? policy : "B2C_1A_" + policy;
+ tenant = (tenant.Contains("onmicrosoft.com", StringComparison.OrdinalIgnoreCase)
+ || tenant.Contains(".net", StringComparison.OrdinalIgnoreCase))
+ ? tenant
+ : $"{tenant}.onmicrosoft.com";
+ dcInfo = string.IsNullOrWhiteSpace(dcInfo) ? string.Empty : $"&{dcInfo}";
+ issuer = string.IsNullOrWhiteSpace(issuer) ? SAMLHelper.GetThisURL(this) : issuer;
- if (null != Tenant) HttpContext.Session.SetString("Tenant", Tenant);
+ if (null != tenant) HttpContext.Session.SetString("Tenant", tenant);
if (null != b2cloginurl) HttpContext.Session.SetString("HostName", b2cloginurl);
- if (null != Policy) HttpContext.Session.SetString("Policy", Policy);
- if (null != Issuer) HttpContext.Session.SetString("Issuer", Issuer);
+ if (null != policy) HttpContext.Session.SetString("Policy", policy);
+ if (null != issuer) HttpContext.Session.SetString("Issuer", issuer);
- string RelayState = SAMLHelper.toB64(Tenant) + "." + SAMLHelper.toB64(Policy) + "." + SAMLHelper.toB64(Issuer);
+ string RelayState = $"{SAMLHelper.toB64(tenant)}.{SAMLHelper.toB64(policy)}.{SAMLHelper.toB64(issuer)}";
- if (!string.IsNullOrEmpty(DCInfo))
+ if (!string.IsNullOrEmpty(dcInfo))
{
- RelayState = RelayState + "." + SAMLHelper.toB64(DCInfo);
+ RelayState = $"{RelayState}.{SAMLHelper.toB64(dcInfo)}";
}
AuthnRequest AuthnReq;
- string URL = "https://" + b2cloginurl + "/" + Tenant + "/" + Policy + "/samlp/sso/login?" + DCInfo;
- AuthnReq = new AuthnRequest(URL, SAMLHelper.GetThisURL(this), Issuer);
+ string URL = $"https://{b2cloginurl}/{tenant}/{policy}/samlp/sso/login?{dcInfo}";
+ AuthnReq = new AuthnRequest(URL, SAMLHelper.GetThisURL(this), issuer);
string cdoc = SAMLHelper.Compress(AuthnReq.ToString());
- URL = URL + "&SAMLRequest=" + System.Web.HttpUtility.UrlEncode(cdoc) + "&RelayState=" + System.Web.HttpUtility.UrlEncode(RelayState);
+ URL = $"{URL}&SAMLRequest={System.Web.HttpUtility.UrlEncode(cdoc)}&RelayState={System.Web.HttpUtility.UrlEncode(RelayState)}";
return Redirect(URL);
}
- public IActionResult SendAzureAdRequest(string Tenant)
+ public IActionResult SendAzureAdRequest(string tenant)
{
AuthnRequest AuthnReq;
AuthnReq = new AuthnRequest("https://login.microsoftonline.com/00000000-0000-0000-0000-000000000000/saml2", SAMLHelper.GetThisURL(this), string.Empty);
diff --git a/source-code/Pages/_Layout.cshtml b/source-code/Pages/_Layout.cshtml
index 5ccbca3..9e5a074 100755
--- a/source-code/Pages/_Layout.cshtml
+++ b/source-code/Pages/_Layout.cshtml
@@ -30,7 +30,7 @@
- @*- Identity Provider
*@
+ - Identity Provider
- Service Provider
@*- B2C Policy
*@
- @Html.Raw("Metadata")
diff --git a/source-code/Program.cs b/source-code/Program.cs
index ef0f764..8aee2b2 100755
--- a/source-code/Program.cs
+++ b/source-code/Program.cs
@@ -1,19 +1,45 @@
-using Microsoft.AspNetCore;
-using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Rewrite;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using SAMLTEST.Models;
-namespace SAMLTEST
-{
- public class Program
- {
- public static void Main(string[] args)
- {
- BuildWebHost(args).Run();
- }
+var builder = WebApplication.CreateBuilder(args);
+// Configure JSON logging to the console.
+builder.Logging.AddJsonConsole();
+
+// Add services to the container.
+builder.Services.AddRazorPages();
+builder.Services.AddSession();
+builder.Services.Configure(builder.Configuration.GetSection(AzureAdB2C.ConfigurationName));
- public static IWebHost BuildWebHost(string[] args) =>
- WebHost.CreateDefaultBuilder(args)
- .UseStartup()
- .Build();
+var app = builder.Build();
- }
+// Configure the HTTP request pipeline.
+if (app.Environment.IsDevelopment())
+{
+ // Use Developer page error handling for development.
+ app.UseDeveloperExceptionPage();
+ //app.UseBrowserLink();
}
+else
+{
+ app.UseExceptionHandler("/Error");
+ // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
+ app.UseHsts();
+ var options = new RewriteOptions().AddRedirectToHttpsPermanent();
+ app.UseRewriter(options);
+}
+
+// Use Status Code error handling to our custom page.
+app.UseStatusCodePagesWithRedirects("/Error?StatusCode={0}");
+app.UseHttpsRedirection();
+// For the wwwroot folder
+app.UseStaticFiles();
+app.UseRouting();
+app.UseSession();
+app.MapRazorPages();
+app.MapControllers();
+
+app.Run();
diff --git a/source-code/SAMLTEST.csproj b/source-code/SAMLTEST.csproj
index 7956fdc..ddf16cd 100755
--- a/source-code/SAMLTEST.csproj
+++ b/source-code/SAMLTEST.csproj
@@ -1,18 +1,18 @@
- netcoreapp2.0
+ net8.0
A simple DotNet Core2 SAML Identity / Service Provider for B2C Training or Testing purposes only
SAML
https://github.com/
GitHub
39ec726f-b878-4431-bb2a-c02b66a55583
+ true
-
-
+
@@ -20,4 +20,7 @@
+
+
+
diff --git a/source-code/Startup.cs b/source-code/Startup.cs
deleted file mode 100755
index 67106c3..0000000
--- a/source-code/Startup.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Rewrite;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-
-namespace SAMLTEST
-{
- public class Startup
- {
- public static bool IsDevelopment { get; set; }
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddMvc();
- services.AddSession();
- }
-
- public void Configure(IApplicationBuilder app, IHostingEnvironment env)
- {
- if (env.IsDevelopment())
- {
- IsDevelopment = true;
- // Use Developer page error handling for development.
- app.UseDeveloperExceptionPage();
- app.UseBrowserLink();
- }
- else
- {
- IsDevelopment = false;
- // For Production use Custom error handling and ensure it uses HTTPS
- app.UseExceptionHandler("/Error");
- var options = new RewriteOptions().AddRedirectToHttpsPermanent();
- app.UseRewriter(options);
- }
-
- // Use Status Code error handling to our custom page.
- app.UseStatusCodePagesWithRedirects("/Error?StatusCode={0}");
- // For the wwwroot folder
- app.UseStaticFiles();
- app.UseSession();
- app.UseMvc();
- }
-
- }
-}
diff --git a/source-code/appsettings.json b/source-code/appsettings.json
index e2f27d2..bfacc05 100755
--- a/source-code/appsettings.json
+++ b/source-code/appsettings.json
@@ -13,6 +13,12 @@
"UID": "bdown"
},
"b2cloginurl": "login.microsoftonline.com"
+ },
+ "AzureAdB2C": {
+ "Tenant": "",
+ "HostName": ".b2clogin.com",
+ "Policy": "B2C_1A_SIGNUP_SIGNINSAML",
+ "Issuer": "https://.onmicrosoft.com",
+ "DCInfo": ""
}
-
- }
+}
diff --git a/source-code/obj/Debug/netcoreapp2.0/SAMLTEST.AssemblyInfo.cs b/source-code/obj/Debug/netcoreapp2.0/SAMLTEST.AssemblyInfo.cs
deleted file mode 100644
index 5825c3e..0000000
--- a/source-code/obj/Debug/netcoreapp2.0/SAMLTEST.AssemblyInfo.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-// Runtime Version:4.0.30319.42000
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-using System;
-using System.Reflection;
-
-[assembly: Microsoft.Extensions.Configuration.UserSecrets.UserSecretsIdAttribute("39ec726f-b878-4431-bb2a-c02b66a55583")]
-[assembly: System.Reflection.AssemblyCompanyAttribute("SAMLTEST")]
-[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
-[assembly: System.Reflection.AssemblyDescriptionAttribute("A simple DotNet Core2 SAML Identity / Service Provider for B2C Training or Testin" +
- "g purposes only")]
-[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
-[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
-[assembly: System.Reflection.AssemblyProductAttribute("SAMLTEST")]
-[assembly: System.Reflection.AssemblyTitleAttribute("SAMLTEST")]
-[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
-
-// Generated by the MSBuild WriteCodeFragment class.
-
diff --git a/source-code/obj/Debug/netcoreapp2.0/SAMLTEST.AssemblyInfoInputs.cache b/source-code/obj/Debug/netcoreapp2.0/SAMLTEST.AssemblyInfoInputs.cache
deleted file mode 100644
index 63e077a..0000000
--- a/source-code/obj/Debug/netcoreapp2.0/SAMLTEST.AssemblyInfoInputs.cache
+++ /dev/null
@@ -1 +0,0 @@
-ed95fcd85841be10142a7b2488204600041ac888
|