Skip to content

Commit 9accb13

Browse files
authored
Merge pull request #41 from RockSolidKnowledge/feature/SLO
Add OIDC and SAML SLO Sample
2 parents ab3d40a + 1b0c10f commit 9accb13

File tree

306 files changed

+269662
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

306 files changed

+269662
-1
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net7.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
9+
</Project>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace Common;
2+
3+
public static class TestConstants
4+
{
5+
public static string LicenseKey = "eyJTb2xkRm9yIjowLjAsIktleVByZXNldCI6NiwiU2F2ZUtleSI6ZmFsc2UsIkxlZ2FjeUtleSI6ZmFsc2UsIlJlbmV3YWxTZW50VGltZSI6IjAwMDEtMDEtMDFUMDA6MDA6MDAiLCJhdXRoIjoiREVNTyIsImV4cCI6IjIwMjMtMDUtMTlUMDE6MDA6MDAuNzA3NTI2NiswMDowMCIsImlhdCI6IjIwMjMtMDQtMTlUMDE6MDA6MDAiLCJvcmciOiJERU1PIiwiYXVkIjoyfQ==.TOLSabk8Uf3jNF908d6r3jj9NzRPNExgZ1qqZMyBWkJ0Fpi+RESseOs7Dj8xtSdxt9SoCn4VnomVZnWA4alV3gDnAKIIatMgT8YzCr5Y/IrgEmJmRTb7jNDd5azBrgjCDNmjI8clx5UzGwLfuL1+K72KjsAq1R6DvAZdFiJ0Ggtw4sCocGfhjKrPbDo6izyc3A6EOtgOL0TDLuqxsPm0vPkHB/NRxUsVAGaiLwhu65Wz9iLMGx9BJIIpTr5frGAfrpmv4brjCe92jZcBuCMWgQPVxJKbGzZqNhK8m1uqiLvSdvdoymsvccLaKeVa8APeaq0KROJu9KqPKNg0R/anSYfwBz88L9CgqszLNYRynK4pcSm52POd3g4ulhtZ5vcvRDDI3W3rgw6LO4Et8iQ6SXU/JEhSIjbmqAbKCnQErUDYT8/k2qpIy5W9Sy14F4OkueW1i19R6UcLQVcRztbGUFz7rGRUwbStWS+Eb1sFjDjFzoEGxQhgy/GW/MNUGFF39KVUfZaYTWuz9MvgsXc7exrmT/zKsTjC6GB0wSFcRK5I34T7aIymC95rPHwAqFzfOr2FNt6DvJXogS7VWS+tJkVAHxVYB/stXT3+eBLU9Qa3Su2nZ36YdrYAMIBJmFwiQMq52QAi2/1/2a2e0nrKFTQJh3tdnQGtG2ZjXRtvdWo=";
6+
public static string Licensee = "DEMO";
7+
}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
using System.Security.Cryptography.X509Certificates;
2+
using Duende.IdentityServer;
3+
using Duende.IdentityServer.Models;
4+
using IdentityModel;
5+
using Rsk.Saml;
6+
using Rsk.Saml.Models;
7+
using ServiceProvider = Rsk.Saml.Models.ServiceProvider;
8+
9+
namespace IdentityServer;
10+
11+
public static class Config
12+
{
13+
public static IEnumerable<IdentityResource> IdentityResources =>
14+
new List<IdentityResource>
15+
{
16+
new IdentityResources.OpenId(),
17+
new IdentityResources.Profile(),
18+
new IdentityResource()
19+
{
20+
Name = "verification",
21+
UserClaims = new List<string>
22+
{
23+
JwtClaimTypes.Email,
24+
JwtClaimTypes.EmailVerified
25+
}
26+
}
27+
};
28+
29+
public static IEnumerable<ApiScope> ApiScopes =>
30+
new List<ApiScope>
31+
{
32+
new ApiScope("api1", "MyAPI")
33+
};
34+
35+
public static IEnumerable<ApiResource> ApiResources =>
36+
new List<ApiResource>
37+
{
38+
};
39+
40+
public static IEnumerable<Client> Clients =>
41+
new List<Client>
42+
{
43+
// machine-to-machine client (from quickstart 1)
44+
new Client
45+
{
46+
ClientId = "client",
47+
ClientSecrets = { new Secret("secret".Sha256()) },
48+
49+
AllowedGrantTypes = GrantTypes.ClientCredentials,
50+
// scopes that client has access to
51+
AllowedScopes = { "api1" },
52+
},
53+
// interactive ASP.NET Core Web App
54+
new Client
55+
{
56+
ClientId = "web",
57+
ClientSecrets = { new Secret("secret".Sha256()) },
58+
59+
AllowedGrantTypes = GrantTypes.Code,
60+
61+
// where to redirect after login
62+
RedirectUris = { "https://localhost:5002/signin-oidc" },
63+
64+
// where to redirect after logout
65+
PostLogoutRedirectUris = { "https://localhost:5002/signout-callback-oidc" },
66+
67+
AllowedScopes = new List<string>
68+
{
69+
IdentityServerConstants.StandardScopes.OpenId,
70+
IdentityServerConstants.StandardScopes.Profile,
71+
"verification"
72+
}
73+
},
74+
new Client()
75+
{
76+
ClientId = "https://localhost:5002",
77+
ProtocolType = IdentityServerConstants.ProtocolTypes.Saml2p,
78+
RedirectUris = new List<string>()
79+
{
80+
"https://localhost:5002/signin-saml"
81+
},
82+
83+
AllowedScopes = new List<string>
84+
{
85+
IdentityServerConstants.StandardScopes.OpenId,
86+
IdentityServerConstants.StandardScopes.Profile,
87+
}
88+
},
89+
new Client()
90+
{
91+
ClientId = "https://localhost:5003",
92+
ProtocolType = IdentityServerConstants.ProtocolTypes.Saml2p,
93+
RedirectUris = new List<string>()
94+
{
95+
"https://localhost:5003/signin-saml"
96+
},
97+
98+
AllowedScopes = new List<string>
99+
{
100+
IdentityServerConstants.StandardScopes.OpenId,
101+
IdentityServerConstants.StandardScopes.Profile,
102+
}
103+
},
104+
new Client()
105+
{
106+
ClientId = "https://localhost:5004",
107+
ProtocolType = IdentityServerConstants.ProtocolTypes.Saml2p,
108+
RedirectUris = new List<string>()
109+
{
110+
"https://localhost:5004/signin-saml"
111+
},
112+
113+
AllowedScopes = new List<string>
114+
{
115+
IdentityServerConstants.StandardScopes.OpenId,
116+
IdentityServerConstants.StandardScopes.Profile,
117+
}
118+
}
119+
};
120+
121+
public static IEnumerable<ServiceProvider> ServiceProvider => new List<ServiceProvider>()
122+
{
123+
new ServiceProvider()
124+
{
125+
EntityId = "https://localhost:5002",
126+
AssertionConsumerServices = new List<Service>()
127+
{
128+
new Service(SamlConstants.BindingTypes.HttpPost, "https://localhost:5002/signin-saml")
129+
},
130+
SingleLogoutServices = new List<Service>()
131+
{
132+
new Service(SamlConstants.BindingTypes.HttpPost, "https://localhost:5002/signout-saml")
133+
},
134+
SigningCertificates = new List<X509Certificate2>()
135+
{
136+
new X509Certificate2("Resources/testclient.cer")
137+
}
138+
},
139+
new ServiceProvider()
140+
{
141+
EntityId = "https://localhost:5003",
142+
AssertionConsumerServices = new List<Service>()
143+
{
144+
new Service(SamlConstants.BindingTypes.HttpPost, "https://localhost:5003/signin-saml")
145+
},
146+
SingleLogoutServices = new List<Service>()
147+
{
148+
new Service(SamlConstants.BindingTypes.HttpPost, "https://localhost:5003/signout-saml")
149+
},
150+
SigningCertificates = new List<X509Certificate2>()
151+
{
152+
new X509Certificate2("Resources/testclient.cer")
153+
}
154+
},
155+
new ServiceProvider()
156+
{
157+
EntityId = "https://localhost:5004",
158+
AssertionConsumerServices = new List<Service>()
159+
{
160+
new Service(SamlConstants.BindingTypes.HttpPost, "https://localhost:5004/signin-saml")
161+
},
162+
SingleLogoutServices = new List<Service>()
163+
{
164+
new Service(SamlConstants.BindingTypes.HttpPost, "https://localhost:5004/signout-saml")
165+
},
166+
SigningCertificates = new List<X509Certificate2>()
167+
{
168+
new X509Certificate2("Resources/testclient.cer")
169+
}
170+
}
171+
};
172+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using Common;
2+
using Duende.IdentityServer;
3+
using Duende.IdentityServer.Configuration;
4+
using IdentityServerHost;
5+
using Microsoft.EntityFrameworkCore;
6+
using Microsoft.IdentityModel.Tokens;
7+
using Rsk.Saml.Configuration;
8+
using Serilog;
9+
10+
namespace IdentityServer;
11+
12+
internal static class HostingExtensions
13+
{
14+
public static WebApplication ConfigureServices(this WebApplicationBuilder builder)
15+
{
16+
builder.Services.AddRazorPages();
17+
18+
builder.Services.AddIdentityServer(options =>
19+
{
20+
options.KeyManagement.Enabled = true;
21+
22+
//Required to use the SAML plugin with Key Management
23+
options.KeyManagement.SigningAlgorithms = new[]
24+
{
25+
new SigningAlgorithmOptions("RS256")
26+
{
27+
UseX509Certificate = true
28+
}
29+
};
30+
})
31+
.AddInMemoryIdentityResources(Config.IdentityResources)
32+
.AddInMemoryApiScopes(Config.ApiScopes)
33+
.AddInMemoryClients(Config.Clients)
34+
.AddTestUsers(TestUsers.Users)
35+
.AddSamlPlugin(options =>
36+
{
37+
options.Licensee = TestConstants.Licensee;
38+
options.LicenseKey = TestConstants.LicenseKey;
39+
40+
//Use Iterative SLO
41+
options.UseIFramesForSlo = false;
42+
})
43+
.AddInMemoryServiceProviders(Config.ServiceProvider)
44+
.AddInMemoryPersistedGrants();
45+
46+
return builder.Build();
47+
}
48+
49+
public static WebApplication ConfigurePipeline(this WebApplication app)
50+
{
51+
app.UseSerilogRequestLogging();
52+
if (app.Environment.IsDevelopment())
53+
{
54+
app.UseDeveloperExceptionPage();
55+
}
56+
57+
app.UseStaticFiles();
58+
app.UseRouting();
59+
60+
app.UseIdentityServer()
61+
.UseIdentityServerSamlPlugin();
62+
63+
app.UseAuthorization();
64+
app.MapRazorPages().RequireAuthorization();
65+
66+
return app;
67+
}
68+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
<PropertyGroup>
3+
<TargetFramework>net7.0</TargetFramework>
4+
<ImplicitUsings>enable</ImplicitUsings>
5+
<UserSecretsId>38ced442-cf32-4289-bb08-57d4a78831b3</UserSecretsId>
6+
</PropertyGroup>
7+
<ItemGroup>
8+
<PackageReference Include="AspNetCore.ReCaptcha" Version="1.7.0" />
9+
<PackageReference Include="Duende.IdentityServer.EntityFramework" Version="6.2.3" />
10+
<PackageReference Include="Microsoft.AspNetCore.Authentication.WsFederation" Version="7.0.4" />
11+
<PackageReference Include="Microsoft.AspNetCore.DataProtection" Version="7.0.4" />
12+
<PackageReference Include="Microsoft.AspNetCore.DataProtection.EntityFrameworkCore" Version="7.0.4" />
13+
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.4" />
14+
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="7.0.4" />
15+
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="7.0.4" />
16+
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
17+
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="3.21.90" />
18+
<PackageReference Include="Rsk.Saml.DuendeIdentityServer" Version="7.0.3" />
19+
<PackageReference Include="Rsk.Saml.DuendeIdentityServer.EntityFramework" Version="7.0.1" />
20+
<PackageReference Include="Serilog.AspNetCore" Version="6.1.0" />
21+
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="7.0.4" />
22+
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
23+
<PackageReference Include="Serilog.Sinks.MSSqlServer" Version="6.3.0" />
24+
<PackageReference Include="System.ServiceModel.Http" Version="4.10.2" />
25+
<PackageReference Include="System.ServiceModel.Primitives" Version="4.10.2" />
26+
</ItemGroup>
27+
<ItemGroup>
28+
<None Update="Resources\testclient.cer">
29+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
30+
</None>
31+
</ItemGroup>
32+
<ItemGroup>
33+
<ProjectReference Include="..\Common\Common.csproj" />
34+
</ItemGroup>
35+
<ItemGroup>
36+
<_ContentIncludedByDefault Remove="Pages\Ciba\All.cshtml" />
37+
<_ContentIncludedByDefault Remove="Pages\Ciba\Consent.cshtml" />
38+
<_ContentIncludedByDefault Remove="Pages\Ciba\Index.cshtml" />
39+
<_ContentIncludedByDefault Remove="Pages\Ciba\_ScopeListItem.cshtml" />
40+
<_ContentIncludedByDefault Remove="Pages\Device\Index.cshtml" />
41+
<_ContentIncludedByDefault Remove="Pages\Device\Success.cshtml" />
42+
<_ContentIncludedByDefault Remove="Pages\Device\_ScopeListItem.cshtml" />
43+
<_ContentIncludedByDefault Remove="Pages\Diagnostics\Index.cshtml" />
44+
<_ContentIncludedByDefault Remove="Pages\Grants\Index.cshtml" />
45+
<_ContentIncludedByDefault Remove="Pages\ExternalLogin\Callback.cshtml" />
46+
<_ContentIncludedByDefault Remove="Pages\ExternalLogin\Challenge.cshtml" />
47+
</ItemGroup>
48+
</Project>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@page
2+
@model IdentityServerHost.Pages.Account.AccessDeniedModel
3+
@{
4+
}
5+
<div class="row">
6+
<div class="col">
7+
<h1>Access Denied</h1>
8+
<p>You do not have permission to access that resource.</p>
9+
</div>
10+
</div>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using Microsoft.AspNetCore.Mvc.RazorPages;
3+
4+
namespace IdentityServerHost.Pages.Account;
5+
6+
public class AccessDeniedModel : PageModel
7+
{
8+
public void OnGet()
9+
{
10+
}
11+
}

0 commit comments

Comments
 (0)