Skip to content

Commit

Permalink
Rework sample app
Browse files Browse the repository at this point in the history
  • Loading branch information
YuriyDurov committed Oct 17, 2024
1 parent a17e384 commit 15854f4
Show file tree
Hide file tree
Showing 39 changed files with 235 additions and 283 deletions.
4 changes: 2 additions & 2 deletions BitzArt.Blazor.Auth.sln
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BitzArt.Blazor.Auth", "src\
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{2E5D89F5-108F-4E1D-B9D7-D86A531130CE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleBlazorApp", "sample\SampleBlazorApp\SampleBlazorApp\SampleBlazorApp.csproj", "{914F51A6-4CA3-4038-BC22-89E697A9FD32}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BitzArt.Blazor.Auth.SampleApp", "sample\BitzArt.Blazor.Auth.SampleApp\BitzArt.Blazor.Auth.SampleApp\BitzArt.Blazor.Auth.SampleApp.csproj", "{914F51A6-4CA3-4038-BC22-89E697A9FD32}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleBlazorApp.Client", "sample\SampleBlazorApp\SampleBlazorApp.Client\SampleBlazorApp.Client.csproj", "{5EC410B2-F3BA-41F6-816F-EE4860531482}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BitzArt.Blazor.Auth.SampleApp.Client", "sample\BitzArt.Blazor.Auth.SampleApp\BitzArt.Blazor.Auth.SampleApp.Client\BitzArt.Blazor.Auth.SampleApp.Client.csproj", "{5EC410B2-F3BA-41F6-816F-EE4860531482}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BitzArt.Blazor.Auth.Client", "src\BitzArt.Blazor.Auth.Client\BitzArt.Blazor.Auth.Client.csproj", "{B8A8813E-FA02-416A-8694-F39388756C5B}"
EndProject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<Nullable>enable</Nullable>
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
<StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
<RootNamespace>BitzArt.Blazor.Auth.SampleApp</RootNamespace>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@inject NavigationManager NavigationManager
@namespace BitzArt.Blazor.Auth.SampleApp
@inject NavigationManager NavigationManager

@code {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<Router AppAssembly="typeof(Program).Assembly">
@namespace BitzArt.Blazor.Auth.SampleApp

<Router AppAssembly="typeof(Client.Program).Assembly">
<Found Context="routeData">
<AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)">
<NotAuthorized>
<Redirect To="/auth" />
<Redirect To="/" />
</NotAuthorized>
</AuthorizeRouteView>
<FocusOnNavigate RouteData="routeData" Selector="h1" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace BitzArt.Blazor.Auth.SampleApp;

public class SignInPayload
{
public string? MyData { get; set; }

public SignInPayload() { }

public SignInPayload(string myData)
{
MyData = myData;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@namespace BitzArt.Blazor.Auth.SampleApp
@page "/auth-required"

@* This attribute makes the page require authorization. Also check `Routes.razor` *@
@attribute [Authorize]

<PageTitle>Auth Required Page | Blazor.Auth</PageTitle>

Congrats, you are authorized to see this page!
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
@namespace BitzArt.Blazor.Auth.SampleApp
@page "/"
@rendermode InteractiveAuto

<PageTitle>Home Page | Blazor.Auth</PageTitle>

<h5 style="margin-bottom:2rem;">
This page is currently using @(OperatingSystem.IsBrowser() ? "WebAssembly rendering" : "server-side rendering")
</h5>

<AuthorizeView>

<NotAuthorized>
<div>
<h4>
You are not authenticated.
</h4>

<div style="margin-top:2rem;">
<button type="submit" class="btn btn-lg btn-primary" @onclick="SignInAsync">Sign In</button>
</div>
</div>
</NotAuthorized>

<Authorized>
<div>
<h4>
You are authenticated.
</h4>

<div style="margin-top:2rem;">
<button type="submit" class="btn btn-lg btn-primary" @onclick="SignOutAsync">Sign Out</button>
</div>
</div>
</Authorized>

</AuthorizeView>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Microsoft.AspNetCore.Components;

namespace BitzArt.Blazor.Auth.SampleApp;

public partial class HomePage
{
[Inject] NavigationManager NavigationManager { get; set; } = null!;
[Inject] IUserService UserService { get; set; } = null!;

private async Task SignInAsync()
{
var payload = new SignInPayload("some data");
var authenticationResult = await UserService.SignInAsync(payload);
NavigationManager.NavigateTo("/", true);
}

private async Task SignOutAsync()
{
await UserService.SignOutAsync();
NavigationManager.NavigateTo("/", true);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@inherits LayoutComponentBase
@namespace BitzArt.Blazor.Auth.SampleApp
@inherits LayoutComponentBase

<div class="page">
<div class="sidebar">
Expand All @@ -7,15 +8,6 @@

<main>
<div class="top-row px-4">
Platform: @(OperatingSystem.IsBrowser() ? "Wasm" : "Server") |
<AuthorizeView>
<NotAuthorized>
You are not authenticated
</NotAuthorized>
<Authorized>
You are authenticated
</Authorized>
</AuthorizeView>
</div>

<article class="content px-4">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<div class="top-row ps-3 navbar navbar-dark">
@namespace BitzArt.Blazor.Auth.SampleApp

<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">SampleBlazorApp</a>
</div>
Expand All @@ -15,20 +17,7 @@
</div>

<AuthorizeView>
<NotAuthorized>
<div class="nav-item px-3">
<NavLink class="nav-link" href="auth">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Sign In
</NavLink>
</div>
</NotAuthorized>

<Authorized>
<div class="nav-item px-3">
<NavLink class="nav-link" href="sign-out">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Sign Out
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="auth-required">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Auth Required
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using BitzArt.Blazor.Auth;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;

namespace BitzArt.Blazor.Auth.SampleApp.Client;

internal class Program
{
private static async Task Main(string[] args)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
@using System.Net.Http
@namespace BitzArt.Blazor.Auth.SampleApp.Client

@using System.Net.Http
@using System.Net.Http.Json
@using System.Text.Json

@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization

@using BitzArt.Blazor.Auth
@using SampleBlazorApp
@using SampleBlazorApp.Client
@using SampleBlazorApp.Client.Components
@using SampleBlazorApp.Client.Components.Layout

@using static Microsoft.AspNetCore.Components.Web.RenderMode
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Blazor.Auth": "Debug"
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
<!DOCTYPE html>
@namespace BitzArt.Blazor.Auth.SampleApp

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />

<link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="SampleBlazorApp.styles.css" />
<link rel="stylesheet" href="BitzArt.Blazor.Auth.SampleApp.styles.css" />

<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet @rendermode="InteractiveAuto" />

<HeadOutlet/>
</head>

<body>
<Routes @rendermode="InteractiveAuto" />
<Routes/>
<script src="_framework/blazor.web.js"></script>
</body>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>BitzArt.Blazor.Auth.SampleApp</RootNamespace>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\BitzArt.Blazor.Auth.Server\BitzArt.Blazor.Auth.Server.csproj" />
<ProjectReference Include="..\BitzArt.Blazor.Auth.SampleApp.Client\BitzArt.Blazor.Auth.SampleApp.Client.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.2" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using BitzArt.Blazor.Auth;
using SampleBlazorApp.Components;
using SampleBlazorApp.Services;
using BitzArt.Blazor.Auth.SampleApp.Services;

namespace SampleBlazorApp;
namespace BitzArt.Blazor.Auth.SampleApp;

internal class Program
{
Expand All @@ -20,17 +18,7 @@ private static void Main(string[] args)

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseWebAssemblyDebugging();
}
else
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseWebAssemblyDebugging();

app.UseHttpsRedirection();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:62230",
"sslPort": 44328
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;

namespace BitzArt.Blazor.Auth.SampleApp.Services;

public class JwtService
{
private readonly JwtSecurityTokenHandler _tokenHandler;
private readonly SigningCredentials _signingCredentials;
private static readonly TimeSpan _accessTokenDuration = new(0, 1, 0);
private static readonly TimeSpan _refreshTokenDuration = new(1, 0, 0);

public JwtService()
{
var options = new JwtOptions
{
PublicKey = "MIIBCgKCAQEA12zIJKpaIuNNk2yAdQ4e/EsT7al1hozyi/qFeTduf7BJFS4niFK7k9OL4VJFoUbpDt18y7Yqlz0nsEyinu/7wZJjf646yYymA8jBib/4kxQw6zH7C3qaam283k72pxb+aZOeJ6iU9KNkwTbfMHxKuTHoxySS6VH0vt3Sn0FYWryp8BVdPFlbuJp6K5otksTbdFOPgzgvwNreoI3TgA0e2clRKaEv+FGwhmY6WqR/hp/ebo0mflL2hPwJI1PLzjXdlx1sPHmYYfDTA02eJWkGYVti4oUZ9UTI5pZeRMNItSu1IyjHi45iLDQ+kRaPsx2bL/YZ7NXJu/g+dk7Lb4KdfQIDAQAB",
PrivateKey = "MIIEogIBAAKCAQEA12zIJKpaIuNNk2yAdQ4e/EsT7al1hozyi/qFeTduf7BJFS4niFK7k9OL4VJFoUbpDt18y7Yqlz0nsEyinu/7wZJjf646yYymA8jBib/4kxQw6zH7C3qaam283k72pxb+aZOeJ6iU9KNkwTbfMHxKuTHoxySS6VH0vt3Sn0FYWryp8BVdPFlbuJp6K5otksTbdFOPgzgvwNreoI3TgA0e2clRKaEv+FGwhmY6WqR/hp/ebo0mflL2hPwJI1PLzjXdlx1sPHmYYfDTA02eJWkGYVti4oUZ9UTI5pZeRMNItSu1IyjHi45iLDQ+kRaPsx2bL/YZ7NXJu/g+dk7Lb4KdfQIDAQABAoIBAE6nMQvyBqbmRtSksOIMHdQPtV74mChgHc5t0X3Id1e3jXdmOpjTXBlFC7VgzHtt4HnE9GOMR1Cgy3TbBiTxigHK6PkdK+maqKKJEeCxbpiErrewr/Ao+2gQWPzx56xqAMmbVAs2yevoHElPN34EY2PqjQrol5sIiUuGwffTa+b0f5fuhPuqsvjBRcHhZX8aCCpqrvoblwVVjWKZKsFv7oWH3+KMdm9iwmuuDdOqq51TNgqaJTSpdTl+luHq8bv7hjkx3omF8R8/JHIc2UTP5a6FA0wO77448WriyIjsUpAN4fROBVOS4a4tuHy8lEQr3udxQ1KWFj3sLBy7ls3+FiECgYEA4ZY5sJ2KmZ6xG/gwI96Skd6sc7jA+XZyo3gGeVHyh7yhooZ4JndyJZtjZ4kdiuRyuxrHOG7ZQo07DFJDDbjgRPqIcyiwbLTVkvV+FE7hPwhhN2OR2TUd4D7w9oY8eZ+C0ABXJwT2breS5XCcehAGgK+A31V3rLY4BdhIoOdNOOMCgYEA9HfVt0uz+6qZW22f4XihehELEBlwGJS8bDMoSjuDRHYDwxFErBVb+KlF0w6MLy1bv6Netdcr4aQtVzHDPpDI3MbG3/aNOq8+TXppIvDhMZTycoYzk3YGC8qbhppFH7/O4CX8Z5dd80Xni9sCVU7ePSFdk5BVi6XHTamq46WDfh8CgYAtWZz5Y4J0hZGHVOqgm2MNzh0PGoo43FYJhNyQUSgXn5VC7hODcCnTY5ylOMxmmqxx7t0z/BzTIz9Gp9bxEESNuWvq8rgc8nGpHI8fGAhyOoYIs4yjhOkfpqecd7n6nVWX6SmcH4RHF8KBO5VJeKVGA4I945mub+dtTWC0cCt3DwKBgAXplAif0xWGFblpWFGKqlUabmsQQm7FwhzXy+SntdAFDqg8Fa4XwiasaVzmYCuP7EUhPVwmfRAy+Um/kVpFBCaaxBqMivPdYyNaj4phywB4+rgcWMj7NMA6QTKrLnrLF8TCBm228nW8vhHa1R6dDrDpyqqT9g2vj7doIBLrYNe/AoGAObf5KfkjrpBBO5n//H1thZzR05g5U/hKDbwhCIzhVqP2RgJxtYkadsA3XA29RXOCD58MRsYH6nYpEw52JyP3tTp6jGSCxOM9ltYji2MEpd82yT3lOsVwJXwDL8uFFQNW2VV2xfFV41mk+5B2VqPjPZa7ewFUKluSkXy1oN8Wg1w=",
};

_tokenHandler = new JwtSecurityTokenHandler();

var privateRsa = RSA.Create();
var privateKey = Convert.FromBase64String(options.PrivateKey!);
privateRsa.ImportRSAPrivateKey(privateKey, out _);

var privateSecurityKey = new RsaSecurityKey(privateRsa);

_signingCredentials = new SigningCredentials(privateSecurityKey, SecurityAlgorithms.RsaSha256);
}

public JwtPair BuildJwtPair()
{
var now = DateTime.UtcNow;

var accessTokenExpiresAt = now + _accessTokenDuration;
var accessToken = _tokenHandler.WriteToken(new JwtSecurityToken(
claims:
[
new Claim("myClaim", "My claim data")
],
notBefore: now,
expires: accessTokenExpiresAt,
signingCredentials: _signingCredentials
));

var refreshTokenExpiresAt = now + _refreshTokenDuration;
var refreshToken = _tokenHandler.WriteToken(new JwtSecurityToken(
notBefore: now,
expires: refreshTokenExpiresAt,
signingCredentials: _signingCredentials
));

return new JwtPair
{
AccessToken = accessToken,
RefreshToken = refreshToken,
AccessTokenExpiresAt = accessTokenExpiresAt,
RefreshTokenExpiresAt = refreshTokenExpiresAt
};
}
}

internal class JwtException(string errorMessage, Exception? innerException = null) : Exception(errorMessage, innerException);

internal class JwtOptions
{
public required string PublicKey { get; set; }
public required string PrivateKey { get; set; }
public TimeSpan AccessTokenDuration { get; set; }
public TimeSpan RefreshTokenDuration { get; set; }
}
Loading

0 comments on commit 15854f4

Please sign in to comment.