Skip to content

Commit

Permalink
Upgrade to .NET 9x
Browse files Browse the repository at this point in the history
  • Loading branch information
VahidN committed Nov 16, 2024
1 parent 2c1ea7d commit 628055c
Show file tree
Hide file tree
Showing 38 changed files with 331 additions and 282 deletions.
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "8.0.8",
"version": "9.0.0",
"commands": [
"dotnet-ef"
]
Expand Down
20 changes: 20 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@ roslynator_object_creation_type_style = implicit_when_type_is_obvious
# The logging message template should not vary between calls to 'LoggerExtensions.LogError(ILogger, Exception?, string?, params object?[])'
dotnet_diagnostic.CA2254.severity = suggestion
dotnet_diagnostic.CA1852.severity = suggestion
dotnet_diagnostic.CA1515.severity = suggestion

dotnet_diagnostic.IDE0005.severity = none
dotnet_diagnostic.IDE0055.severity = none
dotnet_diagnostic.IDE0160.severity = none
dotnet_diagnostic.IDE0022.severity = none
dotnet_diagnostic.IDE0021.severity = none
dotnet_diagnostic.IDE0008.severity = none
dotnet_diagnostic.IDE0061.severity = none
dotnet_diagnostic.IDE0023.severity = none
dotnet_diagnostic.IDE0051.severity = suggestion
dotnet_diagnostic.IDE0052.severity = suggestion
dotnet_diagnostic.IDE0058.severity = suggestion
dotnet_diagnostic.IDE0046.severity = suggestion
dotnet_diagnostic.IDE0048.severity = suggestion
dotnet_diagnostic.IDE0010.severity = suggestion
dotnet_diagnostic.IDE0045.severity = suggestion
dotnet_diagnostic.IDE0130.severity = suggestion
dotnet_diagnostic.IDE0072.severity = suggestion


# SCS0008: The cookie is missing 'Secure' flag.
dotnet_diagnostic.SCS0008.severity = suggestion
Expand Down
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: nuget
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 10
groups:
tests:
patterns: ["*"]
update-types: ["minor", "patch"]
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.x
dotnet-version: 9.0.x
- name: Build ASPNETCore2JwtAuthentication
run: dotnet build ./src/ASPNETCore2JwtAuthentication.WebApp/ASPNETCore2JwtAuthentication.WebApp.csproj --configuration Release
8 changes: 4 additions & 4 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
config-file: ./.github/workflows/codeql/codeql-config.yml
Expand All @@ -62,11 +62,11 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
# If this step fails, then you should remove it and run the build manually (see below)
# - name: Autobuild
# uses: github/codeql-action/autobuild@v2
# uses: github/codeql-action/autobuild@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.x
dotnet-version: 9.0.x
- name: Build
run: dotnet build --configuration Release

Expand All @@ -81,6 +81,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
4 changes: 2 additions & 2 deletions ASPNETCore2JwtAuthentication.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
# Visual Studio 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 15.0.26124.0
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EB31F3BE-2CB7-4C42-8E35-FF97075ECB4E}"
EndProject
Expand Down
8 changes: 8 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@
<Features>strict</Features>
<ReportAnalyzer>true</ReportAnalyzer>
</PropertyGroup>
<PropertyGroup>
<NuGetAudit>true</NuGetAudit>
<NuGetAuditMode>all</NuGetAuditMode>
<NuGetAuditLevel>low</NuGetAuditLevel>
<WarningsNotAsErrors Condition="'$(Configuration)' != 'Release'">
$(WarningsNotAsErrors);NU1900;NU1901;NU1902;NU1903;NU1904
</WarningsNotAsErrors>
</PropertyGroup>
<ItemGroup>
<Using Include="System.Globalization"/>
<Using Include="System.Text.Json"/>
Expand Down
36 changes: 18 additions & 18 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
<Project>
<ItemGroup>
<PackageVersion Include="Meziantou.Analyzer" Version="2.0.163" />
<PackageVersion Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.11.20" />
<PackageVersion Include="Meziantou.Analyzer" Version="2.0.179" />
<PackageVersion Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.12.19" />
<PackageVersion Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.4" />
<PackageVersion Include="AsyncFixer" Version="1.6.0" />
<PackageVersion Include="Asyncify" Version="0.9.7" />
<PackageVersion Include="SonarAnalyzer.CSharp" Version="9.32.0.97167" />
<PackageVersion Include="SecurityCodeScan.VS2019" Version="5.6.7" />
<PackageVersion Include="Roslynator.Analyzers" Version="4.12.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Analyzers" Version="8.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8" />
<PackageVersion Include="Roslynator.Analyzers" Version="4.12.9" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Analyzers" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0" />
<PackageVersion Include="Microsoft.AspNet.WebApi.Client" Version="6.0.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.2" />
<PackageVersion Include="fluentassertions" Version="6.12.1" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.0" />
<PackageVersion Include="fluentassertions" Version="6.12.2" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageVersion Include="MSTest.TestAdapter" Version="3.6.0" />
<PackageVersion Include="MSTest.TestFramework" Version="3.6.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.7.3" />
<PackageVersion Include="MSTest.TestAdapter" Version="3.6.3" />
<PackageVersion Include="MSTest.TestFramework" Version="3.6.3" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.0" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="7.0.0" />
<PackageVersion Include="Microsoft.Web.LibraryManager.Build" Version="2.1.175" />
<PackageVersion Include="UAParser" Version="3.1.47" />
</ItemGroup>
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Jwt Authentication without ASP.NET Core Identity 8x
Jwt Authentication without ASP.NET Core Identity 9x
===========

<p>
Expand All @@ -10,11 +10,11 @@ Jwt Authentication without ASP.NET Core Identity 8x

![jwtauth](/src/ASPNETCore2JwtAuthentication.WebApp/wwwroot/images/jwtauth.png)

A Jwt based authentication sample for ASP.NET Core 8x without using the Identity system. It includes:
A Jwt based authentication sample for ASP.NET Core 9x without using the Identity system. It includes:

- Users and Roles tables with a many-to-may relationship.
- A separated EF Core data layer with enabled migrations.
- An EF Core 8x based service layer.
- An EF Core 9x based service layer.
- A Db initializer to seed the default database values.
- An account controller with Jwt and DB based login, custom logout and refresh tokens capabilities.
- 2 sample API controllers to show how user-roles can be applied and used.
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"sdk": {
"version": "8.0.400"
"version": "9.0.100"
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<NoWarn>RCS1090</NoWarn>
</PropertyGroup>
<ItemGroup>
Expand Down
61 changes: 38 additions & 23 deletions src/ASPNETCore2JwtAuthentication.ConsoleClient/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,23 @@ public static class Program
BaseAddress = new Uri(BaseAddress)
};

public static async Task Main(string[] args)
public static async Task Main()
{
var (token, appCookies) = await LoginAsync(
"/api/account/login",
"Vahid",
"1234");
await CallProtectedApiAsync("/api/MyProtectedApi", token);
_ = await RefreshTokenAsync("/api/account/RefreshToken", token, appCookies);
requestUri: "/api/account/login", username: "Vahid", password: "1234");

await CallProtectedApiAsync(requestUrl: "/api/MyProtectedApi", token);
_ = await RefreshTokenAsync(requestUri: "/api/account/RefreshToken", token, appCookies);
}

private static Dictionary<string, string> GetAntiforgeryCookies()
{
WriteLine("\nGet Antiforgery Cookies:");
WriteLine(value: "\nGet Antiforgery Cookies:");
var cookies = _httpClientHandler.CookieContainer.GetCookies(new Uri(BaseAddress));

var appCookies = new Dictionary<string, string>();
WriteLine("WebApp Cookies:");
WriteLine(value: "WebApp Cookies:");

foreach (Cookie cookie in cookies)
{
WriteLine($"Name : {cookie.Name}");
Expand All @@ -46,53 +46,68 @@ private static Dictionary<string, string> GetAntiforgeryCookies()
return appCookies;
}

private static async Task<(Token Token, Dictionary<string, string> AppCookies)> LoginAsync(
string requestUri,
private static async Task<(Token Token, Dictionary<string, string> AppCookies)> LoginAsync(string requestUri,
string username,
string password)
{
WriteLine("\nLogin:");
WriteLine(value: "\nLogin:");

var response = await _httpClient.PostAsJsonAsync(requestUri, new User
{
Username = username,
Password = password
});

var response =
await _httpClient.PostAsJsonAsync(requestUri, new User { Username = username, Password = password });
response.EnsureSuccessStatusCode();

var token = await response.Content.ReadAsAsync<Token>(new[] { new JsonMediaTypeFormatter() });
var token = await response.Content.ReadAsAsync<Token>([new JsonMediaTypeFormatter()]);
WriteLine($"Response : {response}");
WriteLine($"AccessToken : {token.AccessToken}");
WriteLine($"RefreshToken: {token.RefreshToken}");

var appCookies = GetAntiforgeryCookies();

return (token, appCookies);
}

private static async Task<Token> RefreshTokenAsync(string requestUri, Token token,
private static async Task<Token> RefreshTokenAsync(string requestUri,
Token token,
Dictionary<string, string> appCookies)
{
WriteLine("\nRefreshToken:");
WriteLine(value: "\nRefreshToken:");

if (!_httpClient.DefaultRequestHeaders.Contains("X-XSRF-TOKEN"))
if (!_httpClient.DefaultRequestHeaders.Contains(name: "X-XSRF-TOKEN"))
{
// this is necessary for [AutoValidateAntiforgeryTokenAttribute] and all of the 'POST' requests
_httpClient.DefaultRequestHeaders.Add("X-XSRF-TOKEN", appCookies["XSRF-TOKEN"]);
_httpClient.DefaultRequestHeaders.Add(name: "X-XSRF-TOKEN", appCookies[key: "XSRF-TOKEN"]);
}

// this is necessary to populate the this.HttpContext.User object automatically
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.AccessToken);
var response = await _httpClient.PostAsJsonAsync(requestUri, new { refreshToken = token.RefreshToken });
_httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(scheme: "Bearer", token.AccessToken);

var response = await _httpClient.PostAsJsonAsync(requestUri, new
{
refreshToken = token.RefreshToken
});

response.EnsureSuccessStatusCode();

var newToken = await response.Content.ReadAsAsync<Token>(new[] { new JsonMediaTypeFormatter() });
var newToken = await response.Content.ReadAsAsync<Token>([new JsonMediaTypeFormatter()]);
WriteLine($"Response : {response}");
WriteLine($"New AccessToken : {newToken.AccessToken}");
WriteLine($"New RefreshToken: {newToken.RefreshToken}");

return newToken;
}

private static async Task CallProtectedApiAsync(string requestUrl, Token token)
{
WriteLine("\nCall ProtectedApi:");
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.AccessToken);
WriteLine(value: "\nCall ProtectedApi:");

_httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(scheme: "Bearer", token.AccessToken);

var response = await _httpClient.GetAsync(requestUrl);
var message = await response.Content.ReadAsStringAsync();
WriteLine("URL response: " + message);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ASPNETCore2JwtAuthentication.DomainClasses\ASPNETCore2JwtAuthentication.DomainClasses.csproj" />
Expand Down
Loading

0 comments on commit 628055c

Please sign in to comment.