Skip to content

Instantly share code, notes, and snippets.

@rbrayb
Created August 28, 2018 19:35
Show Gist options
  • Save rbrayb/2dcfa1da3b6a1691f0036abf7d6c614e to your computer and use it in GitHub Desktop.
Save rbrayb/2dcfa1da3b6a1691f0036abf7d6c614e to your computer and use it in GitHub Desktop.
Connecting two instances of IdentityServer 4 using the ComponentSpace SAML v2.0 for .NET Core stack
{
"Name": "https://IdentityServer4",
"Description": "IdentityServer4",
"SignAuthnRequest": true,
"SingleSignOnServiceUrl": "http://localhost:6000/SAML/SingleSignOnService",
"SingleLogoutServiceUrl": "http://localhost:6000/SAML/SingleLogoutService",
"PartnerCertificates": [
{
"FileName": "certificates/idp.cer"
}
}
"SAML": {
"$schema": "https://www.componentspace.com/schemas/saml-config-schema-v1.0.json",
"Configurations": [
{
"LocalIdentityProviderConfiguration": {
"Description": "IdentityServer4",
"LocalCertificates": [
{
"FileName": "certificates/idp.pfx",
"Password": "password"
}
],
"Name": "https://IdentityServer4",
"SingleLogoutServiceUrl": "http://localhost:6000/SAML/SingleLogoutService",
"SingleSignOnServiceUrl": "http://localhost:6000/SAML/SingleSignOnService"
},
"LocalServiceProviderConfiguration": {
"AssertionConsumerServiceUrl": "http://localhost:6000/SAML/AssertionConsumerService",
"Description": "IdentityServer4",
"LocalCertificates": [
{
"FileName": "certificates/sp.pfx",
"Password": "password"
}
],
"Name": "https://IdentityServer4",
"SingleLogoutServiceUrl": "http://localhost:6000/SAML/SingleLogoutService"
},
"PartnerIdentityProviderConfigurations": [
{
"Description": "IdentityServer4-2",
"Name": "https://IdentityServer4-2",
"PartnerCertificates": [
{
"FileName": "certificates/idp.cer"
}
],
"SignAuthnRequest": true,
"SingleLogoutServiceUrl": "http://localhost:7000/SAML/SingleLogoutService",
"SingleSignOnServiceUrl": "http://localhost:7000/SAML/SingleSignOnService"
}
],
"PartnerServiceProviderConfigurations": [
{
"AssertionConsumerServiceUrl": "https://localhost:44360/SAML/AssertionConsumerService",
"Description": "Example Service Provider",
"Name": "https://ExampleServiceProvider",
"PartnerCertificates": [
{
"FileName": "certificates/sp.cer"
}
],
"SignSamlResponse": true,
"SingleLogoutServiceUrl": "https://localhost:44360/SAML/SingleLogoutService",
"WantAuthnRequestSigned": true
}
]
}
]
},
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using System;
using Microsoft.IdentityModel.Tokens;
using IdentityServer4;
using IdentityServer4.Quickstart.UI;
using Microsoft.Extensions.Configuration;
using IdentityServer4.Services;
using IdentityServer4.Stores;
using IdentityServer4.Models;
namespace Host
{
public class Startup
{
private readonly IConfiguration _config;
public Startup(IConfiguration config)
{
_config = config;
}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_1);
services.Configure<IISOptions>(iis =>
{
iis.AuthenticationDisplayName = "Windows";
iis.AutomaticAuthentication = false;
});
services.AddIdentityServer(options =>
{
options.Events.RaiseSuccessEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
})
.AddInMemoryClients(Configuration.Clients.Get())
//.AddInMemoryClients(_config.GetSection("Clients"))
.AddInMemoryIdentityResources(Configuration.Resources.GetIdentityResources())
.AddInMemoryApiResources(Configuration.Resources.GetApiResources())
.AddDeveloperSigningCredential()
.AddExtensionGrantValidator<Extensions.ExtensionGrantValidator>()
.AddExtensionGrantValidator<Extensions.NoSubjectExtensionGrantValidator>()
.AddJwtBearerClientAuthentication()
.AddAppAuthRedirectUriValidator()
.AddTestUsers(TestUsers.Users);
services.AddExternalIdentityProviders();
// Add SAML SSO services.
services.AddSaml(_config.GetSection("SAML"));
// Add SAML Middleware
services.AddSamlMiddleware();
services.AddAuthentication()
.AddSaml(options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.PartnerName = () => _config["PartnerName"];
});
return services.BuildServiceProvider(validateScopes: true);
}
public void Configure(IApplicationBuilder app)
{
app.UseMiddleware<Logging.RequestLoggerMiddleware>();
app.UseDeveloperExceptionPage();
app.UseIdentityServer();
// Use SAML middleware.
app.UseSaml();
// Specify the display name and return URL for logout.
app.Use(async (context, next) =>
{
if (context.Request.Path.Value.Equals("/Account/Logout", StringComparison.OrdinalIgnoreCase) &&
string.IsNullOrEmpty(context.Request.Query["logoutId"]))
{
var identityServerInteractionService =
context.RequestServices.GetRequiredService<IIdentityServerInteractionService>();
var logoutMessageStore =
context.RequestServices.GetRequiredService < IMessageStore < LogoutMessage >> ();
var logoutMessage = new Message<LogoutMessage>(new LogoutMessage
{
ClientName = "SAML Service Provider",
PostLogoutRedirectUri = "/SAML/SingleLogoutServiceCompletion"
},
DateTime.UtcNow);
var logoutId = await logoutMessageStore.WriteAsync(logoutMessage);
context.Request.QueryString = context.Request.QueryString.Add("logoutId", logoutId);
}
await next();
});
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
}
public static class ServiceExtensions
{
public static IServiceCollection AddExternalIdentityProviders(this IServiceCollection services)
{
// configures the OpenIdConnect handlers to persist the state parameter into the server-side IDistributedCache.
services.AddOidcStateDataFormatterCache("aad", "demoidsrv");
services.AddAuthentication()
.AddGoogle("Google", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.ClientId = "708996912208-9m4dkjb5hscn7cjrn5u0r4tbgkbj1fko.apps.googleusercontent.com";
options.ClientSecret = "wdfPY6t8H8cecgjlxud__4Gh";
})
.AddOpenIdConnect("demoidsrv", "IdentityServer", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.Authority = "https://demo.identityserver.io/";
options.ClientId = "implicit";
options.ResponseType = "id_token";
options.SaveTokens = true;
options.CallbackPath = "/signin-idsrv";
options.SignedOutCallbackPath = "/signout-callback-idsrv";
options.RemoteSignOutPath = "/signout-idsrv";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
})
.AddSaml("idsrv4", "IdentityServer4", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.AssertionConsumerServicePath = "http://localhost:7000/SAML/AssertionConsumerService";
options.PartnerName = () => "https://IdentityServer4-2";
})
.AddOpenIdConnect("aad", "Azure AD", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.Authority = "https://login.windows.net/4ca9cb4c-5e5f-4be9-b700-c532992a3705";
options.ClientId = "96e3c53e-01cb-4244-b658-a42164cb67a9";
options.ResponseType = "id_token";
options.CallbackPath = "/signin-aad";
options.SignedOutCallbackPath = "/signout-callback-aad";
options.RemoteSignOutPath = "/signout-aad";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
})
.AddOpenIdConnect("adfs", "ADFS", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.Authority = "https://adfs.leastprivilege.vm/adfs";
options.ClientId = "c0ea8d99-f1e7-43b0-a100-7dee3f2e5c3c";
options.ResponseType = "id_token";
options.CallbackPath = "/signin-adfs";
options.SignedOutCallbackPath = "/signout-callback-adfs";
options.RemoteSignOutPath = "/signout-adfs";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
})
.AddWsFederation("adfs-wsfed", "ADFS with WS-Fed", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.MetadataAddress = "https://adfs4.local/federationmetadata/2007-06/federationmetadata.xml";
options.Wtrealm = "urn:test";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
return services;
}
}
}
// As above
.AddSaml("idsrv4", "IdentityServer4", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.AssertionConsumerServicePath = "http://localhost:7000/SAML/AssertionConsumerService";
options.PartnerName = () => "https://IdentityServer4-2";
})
"SAML": {
"$schema": "https://www.componentspace.com/schemas/saml-config-schema-v1.0.json",
"Configurations": [
{
"LocalIdentityProviderConfiguration": {
"Description": "IdentityServer4-2",
"LocalCertificates": [
{
"FileName": "certificates/idp.pfx",
"Password": "password"
}
],
"Name": "https://IdentityServer4-2",
"SingleLogoutServiceUrl": "http://localhost:7000/SAML/SingleLogoutService",
"SingleSignOnServiceUrl": "http://localhost:7000/SAML/SingleSignOnService"
},
"PartnerServiceProviderConfigurations": [
{
"AssertionConsumerServiceUrl": "http://localhost:6000/SAML/AssertionConsumerService",
"Description": "IdentityServer4",
"Name": "https://IdentityServer4",
"PartnerCertificates": [
{
"FileName": "certificates/sp.cer"
}
],
"SignSamlResponse": true,
"SingleLogoutServiceUrl": "http://localhost:6000/SAML/SingleLogoutService",
"WantAuthnRequestSigned": true
}
]
}
]
},
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using System;
using Microsoft.IdentityModel.Tokens;
using IdentityServer4;
using IdentityServer4.Quickstart.UI;
using Microsoft.Extensions.Configuration;
using IdentityServer4.Services;
using IdentityServer4.Stores;
using IdentityServer4.Models;
namespace Host
{
public class Startup
{
private readonly IConfiguration _config;
public Startup(IConfiguration config)
{
_config = config;
}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_1);
services.Configure<IISOptions>(iis =>
{
iis.AuthenticationDisplayName = "Windows";
iis.AutomaticAuthentication = false;
});
services.AddIdentityServer(options =>
{
options.Events.RaiseSuccessEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
})
.AddInMemoryClients(Configuration.Clients.Get())
//.AddInMemoryClients(_config.GetSection("Clients"))
.AddInMemoryIdentityResources(Configuration.Resources.GetIdentityResources())
.AddInMemoryApiResources(Configuration.Resources.GetApiResources())
.AddDeveloperSigningCredential()
.AddExtensionGrantValidator<Extensions.ExtensionGrantValidator>()
.AddExtensionGrantValidator<Extensions.NoSubjectExtensionGrantValidator>()
.AddJwtBearerClientAuthentication()
.AddAppAuthRedirectUriValidator()
.AddTestUsers(TestUsers.Users);
services.AddExternalIdentityProviders();
// Add SAML SSO services.
services.AddSaml(_config.GetSection("SAML"));
// Add SAML Middleware
services.AddSamlMiddleware();
services.AddAuthentication()
.AddSaml(options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.PartnerName = () => _config["PartnerName"];
});
return services.BuildServiceProvider(validateScopes: true);
}
public void Configure(IApplicationBuilder app)
{
app.UseMiddleware<Logging.RequestLoggerMiddleware>();
app.UseDeveloperExceptionPage();
app.UseIdentityServer();
// Use SAML middleware.
app.UseSaml();
// Specify the display name and return URL for logout.
app.Use(async (context, next) =>
{
if (context.Request.Path.Value.Equals("/Account/Logout", StringComparison.OrdinalIgnoreCase) &&
string.IsNullOrEmpty(context.Request.Query["logoutId"]))
{
var identityServerInteractionService =
context.RequestServices.GetRequiredService<IIdentityServerInteractionService>();
var logoutMessageStore =
context.RequestServices.GetRequiredService < IMessageStore < LogoutMessage >> ();
var logoutMessage = new Message<LogoutMessage>(new LogoutMessage
{
ClientName = "SAML Service Provider",
PostLogoutRedirectUri = "/SAML/SingleLogoutServiceCompletion"
},
DateTime.UtcNow);
var logoutId = await logoutMessageStore.WriteAsync(logoutMessage);
context.Request.QueryString = context.Request.QueryString.Add("logoutId", logoutId);
}
await next();
});
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
}
public static class ServiceExtensions
{
public static IServiceCollection AddExternalIdentityProviders(this IServiceCollection services)
{
// configures the OpenIdConnect handlers to persist the state parameter into the server-side IDistributedCache.
services.AddOidcStateDataFormatterCache("aad", "demoidsrv");
services.AddAuthentication()
.AddGoogle("Google", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.ClientId = "708996912208-9m4dkjb5hscn7cjrn5u0r4tbgkbj1fko.apps.googleusercontent.com";
options.ClientSecret = "wdfPY6t8H8cecgjlxud__4Gh";
})
.AddOpenIdConnect("demoidsrv", "IdentityServer", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.Authority = "https://demo.identityserver.io/";
options.ClientId = "implicit";
options.ResponseType = "id_token";
options.SaveTokens = true;
options.CallbackPath = "/signin-idsrv";
options.SignedOutCallbackPath = "/signout-callback-idsrv";
options.RemoteSignOutPath = "/signout-idsrv";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
})
.AddOpenIdConnect("aad", "Azure AD", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.Authority = "https://login.windows.net/4ca9cb4c-5e5f-4be9-b700-c532992a3705";
options.ClientId = "96e3c53e-01cb-4244-b658-a42164cb67a9";
options.ResponseType = "id_token";
options.CallbackPath = "/signin-aad";
options.SignedOutCallbackPath = "/signout-callback-aad";
options.RemoteSignOutPath = "/signout-aad";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
})
.AddOpenIdConnect("adfs", "ADFS", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.Authority = "https://adfs.leastprivilege.vm/adfs";
options.ClientId = "c0ea8d99-f1e7-43b0-a100-7dee3f2e5c3c";
options.ResponseType = "id_token";
options.CallbackPath = "/signin-adfs";
options.SignedOutCallbackPath = "/signout-callback-adfs";
options.RemoteSignOutPath = "/signout-adfs";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
})
.AddWsFederation("adfs-wsfed", "ADFS with WS-Fed", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.MetadataAddress = "https://adfs4.local/federationmetadata/2007-06/federationmetadata.xml";
options.Wtrealm = "urn:test";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
return services;
}
}
}