From a7cf1c31d18a25aab1fc34477aa3358ef0b34909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20Can=20Karag=C3=B6z?= Date: Mon, 20 Apr 2026 16:25:40 +0300 Subject: [PATCH] Update 0.1.0-rc.1 --- .gitignore | 3 ++ Directory.Build.props | 2 +- docs/content/getting-started/quickstart.md | 49 ++++++++++++++++-- .../getting-started/real-world-setup.md | 38 +++++++++++++- .../CodeBeam.UltimateAuth.Sample.Seed.csproj | 15 ++++-- .../Extensions/UAuthSeedExtensions.cs | 16 ++++++ .../uauthlogo.png | Bin 0 -> 4954 bytes .../Program.cs | 5 +- .../Program.cs | 4 +- .../Program.cs | 5 +- .../Program.cs | 4 +- 11 files changed, 118 insertions(+), 23 deletions(-) create mode 100644 samples/CodeBeam.UltimateAuth.Sample.Seed/Extensions/UAuthSeedExtensions.cs create mode 100644 samples/CodeBeam.UltimateAuth.Sample.Seed/uauthlogo.png diff --git a/.gitignore b/.gitignore index 6786d1dc..049d5f46 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,9 @@ *.userosscache *.sln.docstates +*.db-shm +*.db-wal + # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs diff --git a/Directory.Build.props b/Directory.Build.props index 7b23949a..96fa6cdf 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - 0.1.0-preview.2 + 0.1.0-rc.1 $(NoWarn);1591 CodeBeam diff --git a/docs/content/getting-started/quickstart.md b/docs/content/getting-started/quickstart.md index 8d77e763..77853bb1 100644 --- a/docs/content/getting-started/quickstart.md +++ b/docs/content/getting-started/quickstart.md @@ -12,7 +12,7 @@ In this guide, you will set up UltimateAuth in a few minutes and perform your ** ## 1. Create a Project -Create a new Blazor Server web app: +Start by creating a new Blazor app: ```bash dotnet new blazorserver -n UltimateAuthDemo @@ -21,7 +21,7 @@ cd UltimateAuthDemo ## 2. Install Packages -Add UltimateAuth packages: +Install the required UltimateAuth packages: ```csharp dotnet add package CodeBeam.UltimateAuth.Server @@ -69,7 +69,46 @@ Replace `Routes.razor` with this code: ``` -## 8. Perform Your First Login +## 8. Recommended Setup (Optional) +Add these for better experience: + +For login page (Use this only once in your application) +```csharp +@attribute [UAuthLoginPage] +``` + +For protected pages +```csharp +@attribute [UAuthAuthorize] +``` + +For any page that you use UltimateAuth features like AuthState etc. +```csharp +@inherits UAuthFlowPageBase +``` + +## 9. Seed Data For QuickStart (Optional) +This code creates admin and user users with same password and admin role. + +For in memory +```csharp +builder.Services.AddUltimateAuthSampleSeed(); +``` + +For entity framework core: +```csharp +builder.Services.AddScopedUltimateAuthSampleSeed(); +``` + +In pipeline configuration +```csharp +if (app.Environment.IsDevelopment()) +{ + await app.SeedUltimateAuthAsync(); +} +``` + +## 10. Perform Your First Login Example using IUAuthClient: ```csharp [Inject] IUAuthClient UAuthClient { get; set; } = null!; @@ -78,8 +117,8 @@ private async Task Login() { await UAuthClient.Flows.LoginAsync(new LoginRequest { - Identifier = "demo", - Secret = "password" + Identifier = "admin", + Secret = "admin" }); } ``` diff --git a/docs/content/getting-started/real-world-setup.md b/docs/content/getting-started/real-world-setup.md index 574cf928..92afaeef 100644 --- a/docs/content/getting-started/real-world-setup.md +++ b/docs/content/getting-started/real-world-setup.md @@ -65,7 +65,7 @@ builder.Services.AddUltimateAuthServer(o => { }); ``` -## Blazor WASM Setup +## Blazor Standalone WASM Setup Blazor WASM applications run entirely on the client and cannot securely handle credentials. For this reason, UltimateAuth uses a dedicated Auth server called **UAuthHub**. @@ -91,6 +91,42 @@ app.MapUltimateAuthEndpoints(); app.MapUAuthHub(); ``` +## Blazor Web App Setup +A blazor web app contains two projects that includes host and client. You need to arrange them both. + +In the host project: +```csharp +builder.Services.AddUltimateAuthClientBlazor(o => +{ + o.Endpoints.BasePath = "https://localhost:6112/auth"; // UAuthHub URL + o.Pkce.ReturnUrl = "https://localhost:6132/home"; // Current application domain + path +}); + +// In pipeline configuration +app.MapRazorComponents() + .AddInteractiveWebAssemblyRenderMode() + .AddAdditionalAssemblies(UAuthAssemblies.BlazorClient().First()); +``` + +In the client project: +```csharp +builder.Services.AddUltimateAuthClientBlazor(o => +{ + o.Endpoints.BasePath = "https://localhost:6112/auth"; // UAuthHub URL + o.Pkce.ReturnUrl = "https://localhost:6132/home"; // Current application domain + path +}); + +builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); + +// Optional if you use external API calls in your client project. +builder.Services.AddHttpClient("resourceApi", client => +{ + client.BaseAddress = new Uri("https://localhost:6122"); +}); +``` + +> If you want to use embedded UAuthHub in host project, you can register server services as shown in quickstart. + > ℹ️ UltimateAuth automatically selects the appropriate authentication mode (PureOpaque, Hybrid, etc.) based on the client type. ## ResourceApi Setup diff --git a/samples/CodeBeam.UltimateAuth.Sample.Seed/CodeBeam.UltimateAuth.Sample.Seed.csproj b/samples/CodeBeam.UltimateAuth.Sample.Seed/CodeBeam.UltimateAuth.Sample.Seed.csproj index 92487581..cc80e9e8 100644 --- a/samples/CodeBeam.UltimateAuth.Sample.Seed/CodeBeam.UltimateAuth.Sample.Seed.csproj +++ b/samples/CodeBeam.UltimateAuth.Sample.Seed/CodeBeam.UltimateAuth.Sample.Seed.csproj @@ -1,13 +1,22 @@  - net10.0 - enable - enable + net8.0;net9.0;net10.0 + $(NoWarn);1591 + CodeBeam.UltimateAuth.Sample.Seed + + Minimal seeded data for UltimateAuth samples and quickstart projects. + + authentication;session;identity;auth-framework;seed;data + uauthlogo.png + + + + diff --git a/samples/CodeBeam.UltimateAuth.Sample.Seed/Extensions/UAuthSeedExtensions.cs b/samples/CodeBeam.UltimateAuth.Sample.Seed/Extensions/UAuthSeedExtensions.cs new file mode 100644 index 00000000..aeea00f2 --- /dev/null +++ b/samples/CodeBeam.UltimateAuth.Sample.Seed/Extensions/UAuthSeedExtensions.cs @@ -0,0 +1,16 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using CodeBeam.UltimateAuth.Core.Infrastructure; +using CodeBeam.UltimateAuth.Core.MultiTenancy; + +namespace CodeBeam.UltimateAuth.Sample.Seed.Extensions; + +public static class UAuthSeedExtensions +{ + public static async Task SeedUltimateAuthAsync(this WebApplication app, TenantKey? tenant = null, CancellationToken ct = default) + { + using var scope = app.Services.CreateScope(); + var runner = scope.ServiceProvider.GetRequiredService(); + await runner.RunAsync(tenant, ct); + } +} diff --git a/samples/CodeBeam.UltimateAuth.Sample.Seed/uauthlogo.png b/samples/CodeBeam.UltimateAuth.Sample.Seed/uauthlogo.png new file mode 100644 index 0000000000000000000000000000000000000000..911f2530a1353be33b73719b23571bd6edfb6e96 GIT binary patch literal 4954 zcmcgwWmFVEw8j;Xg(a76mW8EDLILSmU};dg1$nfzN~|mb0>UDKq##I2hf7FENJvPt zbgXnOpwe&s`ObOq@BNs$_sq;W_s-n8-*;!?j106X$yv#Xh=?e4;2I_bdHAo9krH|( z^Q{zu0Q$l${fUSu=>D}^V+-MzL_}baj)tmPNcLWiz9+pl>nr8aU3V2q?ymO^#*<)B?F#;?x@e z)9+HyW~+1-H>^+21!UDMn43PhYim1ss+97s&v|z{_gPU{`}uacB^V5LiuYr&7KZ%Y zj%}CMbjfWXr5Ov)jqUTIWr=IAd|3Ewaw=@teA$mBs_;Qg{X)|fkJ@|zX@;gt31kx8 zYLy<}u_i_8{>8*f4Z?k#@!Bi~8>WC2I>aQXVn;Mw{N}<1d2o*O;bw);ifkWEFe2Az z{|LX0MGD+o&H69uv>uZ8!NO7Z9$$7_0@voyIQ*Np#w3i?p>#2;s@vp5pnZ)GbMR*_p^5kW;p(5gU=xwOPizDcSd0L(2jk2RMw)n zi3{|3K+$8*Qew`hq7UdyonxPW3|d4^CDY6JOaSU`Fbxey=n40>Ptk2nB%M$B zlA)rlgPWH9`~*YGl6Q!@AFrIxW{N0V^Xts1WV%~%BX+E5{^_q0&lfAeOrF$?rdlgH zNZaSXZQCP?F9QzJ@PYG+#Pq)dd}^^`bfjdNoLsD_YYnOueN|$%w29qm87~+sN4ibK z80Sdk^kL#tn}_|{p*nWlV+pqaSD-6>l5;^Vk3mE;YhuSy^FbKXv)f8%cG%yUcvEV* zV>~)MUFtEsU-g5{O~1k8Z#0nc_VA0Sy{u~Dop1eQiq2uB0ZTWQ5sG=Ig?5ZX*Y?H$P_!;}T!_9t` zF6Z^E!>ueY!b)3=T(e;n)h`)v%;+ZrD=L@3;h@LkN{oZ%hiB;+l($x_J}qO$^h7@h zMI)EjfeHbU@OL{4Nbqo~BY{WE zB!~!}Wu|sg6LOV*3@f;CN~aP+IqkqG#AlGEn=d>4Bn3WD0ADDF0`|TK<`uD!gHtZ^ zJ4k35bm!XdZXZ5Y2n0;m9ZWF&jALzP4<3`J$8a0rj2_8<0WA~jz!CT;0F%l==}6T5 zab_+Pj9m&f{ftz}1p}706tf5@Gbg@9(g=F_kcVzNaD$Shkt{8K;Cj9sFw&J)PMDiU zil%(peKK9vFrW*4|3;0>y1raAF$~S|P2C zYnz?(am`z9|eu;IG) z^#{hUjTUHGO!}|`Sp<+s8o0!aGD?97zLXG!o_tMeNPLO7{WZ*()j3x%;R(g{8wxL; zEno6IW=rx(obAN$r^e&}fokU;ADqK0z0*E;krI3u`=88z?|VuUwAXy*9y65uNpyN2 zKVJaJ>tNinNX{KHqprJ<3BJ;u;! zd$Py^REEuG~?uGko+0-e@##uwc3eVNVqyuk96B5!|aM1 z7nxzf2f**&`(1iO!XY0ab#8*B1paUjVtdoU$5Y-~$ZoWpq7vGL`j^u5|Mz|R|5(yX zf#gcMT2T=u3+>(Px-&cvbR)LAUKJjg{>P(}jWi$E8jF-GEt|)-zxrz}6S!2WN*;FF zfIStSnp2N`?eWLEsI4}nlVa*1!_@T2Wbt%E%a&Y1GKBddNTAu$#SX)FSQ~&mSiFfI zf3ixv8AD(_LoeMw+ksPAo2eZO{;Eq(5oLCZ25h6ClO-rXkUP5YF}6Q}^onZA~%OP+1L6dPRLDkq9XoS^d~S z0B6C1pWi*A*rRoL@|N;%J|VB0L)9Pg>^(Jb5P|J&{SrXTe|r>< zj}v&Yd8tz@B;m* zUs)zAIdbYH%)qXQ6Uj;4hy4ZJD{IZ9w$<8>zh(-UtuWk$pRR#sv4ezi69N!6(= z8vpXTFjKyOYuo8=W9i>RF>WJ?(K#5~@Aj;7`5@sHFj$o&g+s$sa=f$TW!0JguYtAV z2#p&`$`jrb7{g|a=AFvzBQ=N8EZuU(iKDPfgz^1SrIZAIF=A&MqLHs<*CbS)^X7eT zcsc5><&FZrl`_gW^xW|gR_2jRu~C{o_;DPke|_?$-R0cluf%!+?*7b1OZbg}*TmV> zG}CMMY|?`=6Uce7?qSE!Qh4f4SK?p%*9fCU`BD4DF~vV0+pjh{YF=6ue^)?CHgC&w zX}MKWmv^>JLf#(O664FtJR^}`!=iUjWjY6&M?+laTCW3fI~MH)-CMrvIppVYLgpr` z+LY;QLW_(++R{evK9LODUMrF7CT}dOk4&Nq$*S9#t~7ee^&Z{3L2jJ(g9uP0{2_)< z7ymak!zwU9QcW4CH2){(Tx2Y1N49B0Z=Q zGv=MWTrF=kX>?oOdN0Dl?Q8sMD`08??w+S^NF8)mUucq4+S+#KkM1c*F$XFTl_0{< zpT&;7>&N;xFDsX6*Lk81-AWY4`Z)GS`craS>Zy}}I8Hjfgo3-VH}Cu6ua~jCm#%_e zJDdb0-*~S4y3;QC?hAqe{*uN5#Mf(+&^oD6uM(P<8j9RwC53Hm1dB(Jl2E2ZpvETUE)M`Z$OA z0-0qgzh$v(2jm>M$j&24i-f*vZS#7k7lk+An-L6nKm%?_3G|h>RZI=$?@a0dmb^BXC?3oZQSA?hzLO5X+4HG{M)Mw;A;!hjD|a2UT<$92^kV>qT^g&SgU2)93R7MY zi&UkCDL4vqv+2p@q&4eOWgC3q8t@?1b|5L@JsO~1bY0kzjk-7+Yn-mfJ1P5Y;>op_ zdu>{R>l_8gl9Ob-+)Ow5_S8* zQXf%jFEg$Pq)-mqVJQfzDr}s?ODM23JzxCp$~pS46PUWW&O^^Fm?h@rP@EmOxEHy;T<6bO_pnnliH&qVCedzoGo`&CM z@0GUNaYA7?8q*VCv1&_HS7P+4wR}IJYI`O)y|=H?bR(PsKKt{pI(Yfo;cluMva>^| zQdy~%!%G`z--_&z#2RZAgO)(`ZSI^g7hdAmZ4Bl#WC`|WVuM= zhmg;El5d3E*=aPKoTIO5`0kYy*7zOI7$UR+d_Rlqg-rHN5LZH(z%SQS^_;FantmXV zAMMJRBb?AT>q5T31Nqa{O6~2OqAu!%FqPJicQNo^5h;ZSLg|@@ON`9E~R8S>OC(HGiEN(ToR{?RiSdi!$K^&KIr__^@v)#f>>S13Zwwc zld}A<;70{vj{`d(Q}!Gw0EM=rkHl;*EOR-{z4~=b{r#TQpO5GP$Cfi-1YdS;Q;!1y zLzFJ~f6!Pkqkof+FEdJgF*w+JyZ4<+$^r*_i{5x<1_6jQzJ$svHk) zXYu%T3h}>zOaxx{Arj1-^Beq`$=QtG;A5g}`4e4-(A=k?ulhMr_1$kna)L`T?8i=y zJ|1!Hx;zk7%PeAavykDds+R&xgOhsg{g}W!S_!ZFv@2q>M$>M${Y(zY8gIn-p^`H? z61{vsao}}Zw3fHJdGQbTpFp4hQ{3IXl*U{eVuRRVnbU5MzSInqhN#_B4ihhpCwH32 z6>|vRO>Benv=M<)uk{u07`yB;MHc>TwnCTX$nQY#5tKsryrOqKTL_(); - await seedRunner.RunAsync(null); } + + await app.SeedUltimateAuthAsync(); } app.UseHttpsRedirection(); diff --git a/samples/UAuthHub/CodeBeam.UltimateAuth.Sample.UAuthHub/Program.cs b/samples/UAuthHub/CodeBeam.UltimateAuth.Sample.UAuthHub/Program.cs index 9784acb8..1182dcf7 100644 --- a/samples/UAuthHub/CodeBeam.UltimateAuth.Sample.UAuthHub/Program.cs +++ b/samples/UAuthHub/CodeBeam.UltimateAuth.Sample.UAuthHub/Program.cs @@ -63,9 +63,7 @@ app.MapOpenApi(); app.MapScalarApiReference(); - using var scope = app.Services.CreateScope(); - var seedRunner = scope.ServiceProvider.GetRequiredService(); - await seedRunner.RunAsync(null); + await app.SeedUltimateAuthAsync(); } app.UseHttpsRedirection(); diff --git a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer.EFCore/Program.cs b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer.EFCore/Program.cs index 377eb8b1..99fe67c7 100644 --- a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer.EFCore/Program.cs +++ b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer.EFCore/Program.cs @@ -89,12 +89,9 @@ using (var scope = app.Services.CreateScope()) { await UAuthDbInitializer.InitializeAsync(app.Services, reset: true); - - var seedRunner = scope.ServiceProvider.GetRequiredService(); - await seedRunner.RunAsync(null); } + await app.SeedUltimateAuthAsync(); } - app.UseForwardedHeaders(); app.UseHttpsRedirection(); diff --git a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Program.cs b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Program.cs index 7b54009b..074e07a3 100644 --- a/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Program.cs +++ b/samples/blazor-server/CodeBeam.UltimateAuth.Sample.BlazorServer/Program.cs @@ -82,9 +82,7 @@ app.MapOpenApi(); app.MapScalarApiReference(); - using var scope = app.Services.CreateScope(); - var seedRunner = scope.ServiceProvider.GetRequiredService(); - await seedRunner.RunAsync(null); + await app.SeedUltimateAuthAsync(); } app.UseForwardedHeaders();