Skip to content

Commit

Permalink
docs: Add Web App example with SignOut
Browse files Browse the repository at this point in the history
  • Loading branch information
NikiforovAll committed May 11, 2024
1 parent 2d6b09d commit 0798a1d
Show file tree
Hide file tree
Showing 63 changed files with 39,777 additions and 1 deletion.
7 changes: 7 additions & 0 deletions KeycloakAuthorizationServicesDotNet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResourceAuthorization", "sa
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Keycloak.AuthServices.OpenTelemetry", "src\Keycloak.AuthServices.OpenTelemetry\Keycloak.AuthServices.OpenTelemetry.csproj", "{3FE98A91-BA4E-4D4F-A6A5-A43123644ACD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApp", "samples\WebApp\WebApp.csproj", "{4AF4CE52-F007-4FEE-9324-7E52314398FF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -166,6 +168,10 @@ Global
{3FE98A91-BA4E-4D4F-A6A5-A43123644ACD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3FE98A91-BA4E-4D4F-A6A5-A43123644ACD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3FE98A91-BA4E-4D4F-A6A5-A43123644ACD}.Release|Any CPU.Build.0 = Release|Any CPU
{4AF4CE52-F007-4FEE-9324-7E52314398FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4AF4CE52-F007-4FEE-9324-7E52314398FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4AF4CE52-F007-4FEE-9324-7E52314398FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4AF4CE52-F007-4FEE-9324-7E52314398FF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -193,6 +199,7 @@ Global
{BF2DCACD-E7C4-4B92-909F-CC535B70F94D} = {96857509-627A-4FD2-AC82-34387619A7B1}
{B060EE8C-C76D-48A4-B209-4646070A7E0D} = {AEBE10B1-96B1-4060-B8C1-1F9BFA7A586C}
{3FE98A91-BA4E-4D4F-A6A5-A43123644ACD} = {F9D5C5B8-9933-4AE0-ADAC-6B8C15F7552A}
{4AF4CE52-F007-4FEE-9324-7E52314398FF} = {AEBE10B1-96B1-4060-B8C1-1F9BFA7A586C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E1907BFD-C144-4B48-AA40-972F499D4E08}
Expand Down
1 change: 1 addition & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export default withMermaid({
{ text: 'Authorization', link: '/examples/authorization-getting-started' },
{ text: 'Resource Authorization ✨', link: '/examples/resource-authorization' },
{ text: 'Clean Architecture', link: '/examples/auth-clean-arch' },
{ text: 'Web App', link: '/examples/web-app-razor' },
{ text: 'Web API + Blazor', link: '/examples/web-api-blazor' }
]
}
Expand Down
7 changes: 7 additions & 0 deletions docs/examples/web-app-razor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# WebApp

<<< @/../samples/WebApp/Program.cs

<<< @/../samples/WebApp/Controllers/AccountController.cs

See sample source code: [keycloak-authorization-services-dotnet/tree/main/samples/WebApp](https://github.com/NikiforovAll/keycloak-authorization-services-dotnet/tree/main/samples/WebApp)
4 changes: 3 additions & 1 deletion samples/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<ItemGroup>
<PackageVersion Include="Duende.AccessTokenManagement" Version="2.1.2" />
<PackageVersion Include="Keycloak.AuthServices.Authentication" Version="1.7.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.29" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0"/>
<PackageVersion Include="MediatR" Version="12.2.0" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.29" />
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="6.0.29" />
Expand All @@ -21,4 +23,4 @@
<PackageVersion Include="Serilog.Sinks.SpectreConsole" Version="0.3.3" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
</Project>
</Project>
Empty file added samples/WebApp/.gitignore
Empty file.
37 changes: 37 additions & 0 deletions samples/WebApp/Controllers/AccountController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
namespace WebApp_OpenIDConnect_DotNet.Controllers;

Check warning on line 1 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

Remove the underscores from namespace name 'WebApp_OpenIDConnect_DotNet' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)

Check warning on line 1 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

Remove the underscores from namespace name 'WebApp_OpenIDConnect_DotNet' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)

Check warning on line 1 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

Remove the underscores from namespace name 'WebApp_OpenIDConnect_DotNet' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)

Check warning on line 1 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

Remove the underscores from namespace name 'WebApp_OpenIDConnect_DotNet' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)

Check warning on line 1 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

Remove the underscores from namespace name 'WebApp_OpenIDConnect_DotNet' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)

Check warning on line 1 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

Remove the underscores from namespace name 'WebApp_OpenIDConnect_DotNet' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)

Check warning on line 1 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

Remove the underscores from namespace name 'WebApp_OpenIDConnect_DotNet' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)

Check warning on line 1 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

Remove the underscores from namespace name 'WebApp_OpenIDConnect_DotNet' (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1707)

using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

public class AccountController : Controller
{
public IActionResult SignIn()
{
if (!User.Identity.IsAuthenticated)

Check warning on line 14 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

Dereference of a possibly null reference.

Check warning on line 14 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

Dereference of a possibly null reference.

Check warning on line 14 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

Dereference of a possibly null reference.

Check warning on line 14 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

Dereference of a possibly null reference.

Check warning on line 14 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

Dereference of a possibly null reference.

Check warning on line 14 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

Dereference of a possibly null reference.

Check warning on line 14 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

Dereference of a possibly null reference.

Check warning on line 14 in samples/WebApp/Controllers/AccountController.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

Dereference of a possibly null reference.
{
return this.Challenge(OpenIdConnectDefaults.AuthenticationScheme);
}

return this.RedirectToAction("Index", "Home");
}

[Authorize]
public async Task<IActionResult> SignOutAsync()
{
var idToken = await this.HttpContext.GetTokenAsync("id_token");

return this.SignOut(
new AuthenticationProperties
{
RedirectUri = "/",
Items = { { "id_token_hint", idToken } }
},
CookieAuthenticationDefaults.AuthenticationScheme,
OpenIdConnectDefaults.AuthenticationScheme
);
}
}
27 changes: 27 additions & 0 deletions samples/WebApp/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace WebApp_OpenIDConnect_DotNet.Controllers;

using System.Diagnostics;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using WebApp_OpenIDConnect_DotNet.Models;

[Authorize]
public class HomeController : Controller
{
public IActionResult Index() => this.View();

public IActionResult Privacy() => this.View();

[AllowAnonymous]
public IActionResult Public() => this.View();

[AllowAnonymous]
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error() =>
this.View(
new ErrorViewModel
{
RequestId = Activity.Current?.Id ?? this.HttpContext.TraceIdentifier
}
);
}
75 changes: 75 additions & 0 deletions samples/WebApp/KeycloakConfiguration/test-client.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"clientId": "test-client",
"name": "",
"description": "",
"rootUrl": "",
"adminUrl": "",
"baseUrl": "",
"surrogateAuthRequired": false,
"enabled": true,
"alwaysDisplayInConsole": false,
"clientAuthenticatorType": "client-secret",
"redirectUris": [
"*"
],
"webOrigins": [
"*"
],
"notBefore": 0,
"bearerOnly": false,
"consentRequired": false,
"standardFlowEnabled": true,
"implicitFlowEnabled": true,
"directAccessGrantsEnabled": true,
"serviceAccountsEnabled": false,
"publicClient": true,
"frontchannelLogout": true,
"protocol": "openid-connect",
"attributes": {
"oidc.ciba.grant.enabled": "false",
"backchannel.logout.session.required": "false",
"post.logout.redirect.uris": "*",
"oauth2.device.authorization.grant.enabled": "false",
"display.on.consent.screen": "false",
"backchannel.logout.revoke.offline.tokens": "false"
},
"authenticationFlowBindingOverrides": {},
"fullScopeAllowed": true,
"nodeReRegistrationTimeout": -1,
"protocolMappers": [
{
"name": "realm_access",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-realm-role-mapper",
"consentRequired": false,
"config": {
"introspection.token.claim": "true",
"multivalued": "true",
"userinfo.token.claim": "true",
"id.token.claim": "true",
"lightweight.claim": "false",
"access.token.claim": "true",
"claim.name": "realm_roles",
"jsonType.label": "String"
}
}
],
"defaultClientScopes": [
"web-origins",
"acr",
"profile",
"roles",
"email"
],
"optionalClientScopes": [
"address",
"phone",
"offline_access",
"microprofile-jwt"
],
"access": {
"view": true,
"configure": true,
"manage": true
}
}
9 changes: 9 additions & 0 deletions samples/WebApp/Models/ErrorViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace WebApp_OpenIDConnect_DotNet.Models
{
public class ErrorViewModel
{
public string RequestId { get; set; }

Check warning on line 5 in samples/WebApp/Models/ErrorViewModel.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

Non-nullable property 'RequestId' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 5 in samples/WebApp/Models/ErrorViewModel.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

Non-nullable property 'RequestId' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 5 in samples/WebApp/Models/ErrorViewModel.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

Non-nullable property 'RequestId' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 5 in samples/WebApp/Models/ErrorViewModel.cs

View workflow job for this annotation

GitHub Actions / Build-ubuntu-latest

Non-nullable property 'RequestId' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 5 in samples/WebApp/Models/ErrorViewModel.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

Non-nullable property 'RequestId' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 5 in samples/WebApp/Models/ErrorViewModel.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

Non-nullable property 'RequestId' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 5 in samples/WebApp/Models/ErrorViewModel.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

Non-nullable property 'RequestId' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Check warning on line 5 in samples/WebApp/Models/ErrorViewModel.cs

View workflow job for this annotation

GitHub Actions / Build-windows-latest

Non-nullable property 'RequestId' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
}
72 changes: 72 additions & 0 deletions samples/WebApp/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using Keycloak.AuthServices.Authentication;
using Keycloak.AuthServices.Authorization.AuthorizationServer;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;

var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
});

builder
.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddKeycloakWebApp(
builder.Configuration.GetSection(KeycloakAuthorizationServerOptions.Section),
configureOpenIdConnectOptions: options =>
{
// used for front-channel logout
options.SaveTokens = true;
options.Events = new OpenIdConnectEvents
{
OnSignedOutCallbackRedirect = context =>
{
context.Response.Redirect("/Home/Public");
context.HandleResponse();
return Task.CompletedTask;
}
};
// NOTE, the source for claims is id_token and not access token.
// By default, id_token doesn't contain realm_roles claim
// and you will need to create a mapper for that
options.ClaimActions.MapUniqueJsonKey("realm_access", "realm_access");
}
);

builder.Services.PostConfigure<OpenIdConnectOptions>(options => { });

builder.Services.AddControllersWithViews();

builder.Services.AddRazorPages();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}")
.RequireAuthorization();
app.MapRazorPages();

app.Run();
20 changes: 20 additions & 0 deletions samples/WebApp/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://localhost:44321/",
"sslPort": 44321
}
},
"profiles": {
"WebApp_OpenIDConnect_DotNet": {
"commandName": "Project",
"launchBrowser": false,
"applicationUrl": "https://localhost:44321;http://localhost:3110",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
7 changes: 7 additions & 0 deletions samples/WebApp/Properties/serviceDependencies.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"dependencies": {
"secrets1": {
"type": "secrets"
}
}
}
7 changes: 7 additions & 0 deletions samples/WebApp/Properties/serviceDependencies.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"dependencies": {
"secrets1": {
"type": "secrets.user"
}
}
}
5 changes: 5 additions & 0 deletions samples/WebApp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# An ASP.NET Core Web app signing-in users with Keycloak.AuthServices

## Scenario

This sample shows how to build a .NET Core MVC Web app that uses OpenID Connect to sign in users.
11 changes: 11 additions & 0 deletions samples/WebApp/Views/Home/Index.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@{
ViewData["Title"] = "Home Page";
}

<h1>
ASP.NET Core web app signing-in users in your organization
</h1>
<p>
This sample shows how to build a .NET Core MVC Web app that uses OpenID Connect to sign in users in your
organization.
</p>
6 changes: 6 additions & 0 deletions samples/WebApp/Views/Home/Privacy.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@{
ViewData["Title"] = "Privacy Policy";
}
<h2>@ViewData["Title"]</h2>

<p>Use this page to detail your site's privacy policy.</p>
6 changes: 6 additions & 0 deletions samples/WebApp/Views/Home/Public.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@{
ViewData["Title"] = "Public Page";
}
<h2>@ViewData["Title"]</h2>

<p>Public Page</p>
25 changes: 25 additions & 0 deletions samples/WebApp/Views/Shared/Error.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@model ErrorViewModel
@{
ViewData["Title"] = "Error";
}

<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>

@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}

<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>
Loading

0 comments on commit 0798a1d

Please sign in to comment.