diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 48fdce3..7958e8b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @atko-cic/project-dx-sdks-engineer-codeowner \ No newline at end of file +* @auth0/project-dx-sdks-engineer-codeowner diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 26d328c..5d0c270 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,8 +8,8 @@ on: jobs: build: - runs-on: - labels: ubuntu-22.04-2cpu-8ram-75ssd + runs-on: ubuntu-latest + steps: - name: Checkout repository uses: actions/checkout@v5 diff --git a/.github/workflows/sca_scan.yml b/.github/workflows/sca_scan.yml deleted file mode 100644 index aa1c2bd..0000000 --- a/.github/workflows/sca_scan.yml +++ /dev/null @@ -1,11 +0,0 @@ - -name: SCA - -on: - push: - branches: ["master", "main"] - -jobs: - snyk-cli: - uses: atko-security/devsecops-tooling/.github/workflows/sca-scan.yml@main - secrets: inherit diff --git a/.github/workflows/snyk.yml b/.github/workflows/snyk.yml index 88f983c..bea2c1a 100644 --- a/.github/workflows/snyk.yml +++ b/.github/workflows/snyk.yml @@ -24,8 +24,7 @@ jobs: check: name: Check for Vulnerabilities - runs-on: - labels: ubuntu-22.04-2cpu-8ram-75ssd + runs-on: ubuntu-latest steps: - if: github.actor == 'dependabot[bot]' || github.event_name == 'merge_group' diff --git a/Directory.Build.props b/Directory.Build.props index 5b9cd00..080653c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -12,8 +12,8 @@ Auth0, Inc. Copyright (c) 2016-2025 Auth0, Inc. Apache-2.0 - https://github.com/auth0/auth0-aspnetcore-api - https://github.com/auth0/auth0-aspnetcore-api + https://github.com/auth0/aspnetcore-api + https://github.com/auth0/aspnetcore-api git false diff --git a/EXAMPLES.md b/EXAMPLES.md index a16163c..e7b3988 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -1135,4 +1135,4 @@ If you have questions or need help with these examples: - 📖 Check the [main README](README.md) for overview and setup instructions - 💬 Visit the [Auth0 Community](https://community.auth0.com/) -- 🐛 Report issues on [GitHub Issues](https://github.com/auth0/auth0-aspnetcore-api/issues) +- 🐛 Report issues on [GitHub Issues](https://github.com/auth0/aspnetcore-api/issues) diff --git a/MIGRATION.md b/MIGRATION.md index a9a36ad..c3c7e7c 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1734,8 +1734,8 @@ If you encounter issues not covered in this guide: ### 🐛 GitHub Issues We're here to help! If you run into any problems during migration: -1. **Check existing issues:** [Search for similar problems](https://github.com/atko-cic/auth0-aspnetcore-api/issues) -2. **Create a new issue:** [Report your issue](https://github.com/atko-cic/auth0-aspnetcore-api/issues/new) +1. **Check existing issues:** [Search for similar problems](https://github.com/auth0/aspnetcore-api/issues) +2. **Create a new issue:** [Report your issue](https://github.com/auth0/aspnetcore-api/issues/new) When reporting an issue, please include: - Your current JWT Bearer configuration (sanitized) diff --git a/README.md b/README.md index d2709f5..a366f2d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Auth0 API SDK for securing your .NET API Server using tokens from Auth0](https://cdn.auth0.com/website/sdks/banners/auth0-dotnet-api-banner.png) -[![Build and Test](https://github.com/atko-cic/auth0-aspnetcore-api/actions/workflows/build.yml/badge.svg)](https://github.com/atko-cic/auth0-aspnetcore-api/actions/workflows/build.yml) +[![Build and Test](https://github.com/auth0/aspnetcore-api/actions/workflows/build.yml/badge.svg)](https://github.com/auth0/aspnetcore-api/actions/workflows/build.yml) [![License](https://img.shields.io/:license-Apache%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0) A library that provides **everything the standard JWT Bearer authentication offers**, with the added power of **built-in DPoP (Demonstration of Proof-of-Possession)** support for enhanced token security. Simplify your Auth0 JWT authentication integration for ASP.NET Core APIs with Auth0-specific configuration and validation. @@ -313,8 +313,8 @@ For comprehensive, copy-pastable code examples covering various scenarios, see * Clone the repository and build the solution: ```bash -git clone https://github.com/auth0/auth0-aspnetcore-api.git -cd auth0-aspnetcore-api +git clone https://github.com/auth0/aspnetcore-api.git +cd aspnetcore-api dotnet restore Auth0.AspNetCore.Authentication.Api.sln dotnet build Auth0.AspNetCore.Authentication.Api.sln --configuration Release ``` @@ -385,7 +385,7 @@ If you have questions or need help: - 📖 Check the [Auth0 Documentation](https://auth0.com/docs) - � See [EXAMPLES.md](./EXAMPLES.md) for code examples - 💬 Visit the [Auth0 Community](https://community.auth0.com/) -- 🐛 Report issues on [GitHub Issues](https://github.com/auth0/auth0-aspnetcore-api/issues) +- 🐛 Report issues on [GitHub Issues](https://github.com/auth0/aspnetcore-api/issues) ## License Copyright 2025 Okta, Inc. diff --git a/docs-source/articles/dpop-getting-started.md b/docs-source/articles/dpop-getting-started.md index 4b7d3a6..9aa3931 100644 --- a/docs-source/articles/dpop-getting-started.md +++ b/docs-source/articles/dpop-getting-started.md @@ -302,4 +302,4 @@ WWW-Authenticate: DPoP error="invalid_token", - [RFC 9449: OAuth 2.0 DPoP](https://datatracker.ietf.org/doc/html/rfc9449) - [Auth0 DPoP Documentation](https://auth0.com/docs/secure/tokens/token-best-practices/proof-of-possession) -- [Sample Application](https://github.com/atko-cic/auth0-aspnetcore-api/tree/main/Auth0.AspNetCore.Authentication.Api.Playground) +- [Sample Application](https://github.com/auth0/aspnetcore-api/tree/main/Auth0.AspNetCore.Authentication.Api.Playground) diff --git a/docs-source/articles/getting-started.md b/docs-source/articles/getting-started.md index ec2a1db..7866c7f 100644 --- a/docs-source/articles/getting-started.md +++ b/docs-source/articles/getting-started.md @@ -156,4 +156,4 @@ curl --request GET \ ### Need Help? -If you're experiencing issues not covered here, please [open an issue on GitHub](https://github.com/auth0/auth0-aspnetcore-api/issues) and we'll be happy to help! +If you're experiencing issues not covered here, please [open an issue on GitHub](https://github.com/auth0/aspnetcore-api/issues) and we'll be happy to help! diff --git a/docs-source/articles/index.md b/docs-source/articles/index.md index af94f68..56cff5a 100644 --- a/docs-source/articles/index.md +++ b/docs-source/articles/index.md @@ -35,7 +35,7 @@ This library simplifies the integration of Auth0 JWT authentication into your AS ## Resources -- [GitHub Repository](https://github.com/atko-cic/auth0-aspnetcore-api) +- [GitHub Repository](https://github.com/auth0/aspnetcore-api) - [Auth0 Documentation](https://auth0.com/docs) - [ASP.NET Core Documentation](https://docs.microsoft.com/aspnet/core) diff --git a/docs-source/index.md b/docs-source/index.md index 8d9dbae..c572f5e 100644 --- a/docs-source/index.md +++ b/docs-source/index.md @@ -70,7 +70,7 @@ Add the following to your `appsettings.json`: ## Resources -- [GitHub Repository](https://github.com/atko-cic/auth0-aspnetcore-api) +- [GitHub Repository](https://github.com/auth0/aspnetcore-api) - [Auth0 Documentation](https://auth0.com/docs) - [ASP.NET Core Documentation](https://docs.microsoft.com/aspnet/core) diff --git a/src/Auth0.AspNetCore.Authentication.Api/Auth0.AspNetCore.Authentication.Api.csproj b/src/Auth0.AspNetCore.Authentication.Api/Auth0.AspNetCore.Authentication.Api.csproj index 38f58f8..06c9a9f 100644 --- a/src/Auth0.AspNetCore.Authentication.Api/Auth0.AspNetCore.Authentication.Api.csproj +++ b/src/Auth0.AspNetCore.Authentication.Api/Auth0.AspNetCore.Authentication.Api.csproj @@ -23,7 +23,7 @@ README.md logo.png - See https://github.com/auth0/auth0-aspnetcore-api/releases for release notes. + See https://github.com/auth0/aspnetcore-api/releases for release notes. $(OutputPath)$(AssemblyName).xml diff --git a/src/Auth0.AspNetCore.Authentication.Api/Auth0.AspNetCore.Authentication.Api.nuspec b/src/Auth0.AspNetCore.Authentication.Api/Auth0.AspNetCore.Authentication.Api.nuspec index 28c3bb7..6770b00 100644 --- a/src/Auth0.AspNetCore.Authentication.Api/Auth0.AspNetCore.Authentication.Api.nuspec +++ b/src/Auth0.AspNetCore.Authentication.Api/Auth0.AspNetCore.Authentication.Api.nuspec @@ -12,15 +12,15 @@ Apache-2.0 $copyright$ - https://github.com/auth0/auth0-aspnetcore-api - + https://github.com/auth0/aspnetcore-api + logo.png README.md $description$ Auth0 JWT authentication for ASP.NET Core APIs with built-in DPoP (Demonstration of Proof-of-Possession) support for enhanced token security. - See https://github.com/auth0/auth0-aspnetcore-api/blob/main/CHANGELOG.md for detailed release notes. + See https://github.com/auth0/aspnetcore-api/blob/main/CHANGELOG.md for detailed release notes. $tags$ diff --git a/src/Auth0.AspNetCore.Authentication.Api/Utils.cs b/src/Auth0.AspNetCore.Authentication.Api/Utils.cs index 341a08e..9b514e7 100644 --- a/src/Auth0.AspNetCore.Authentication.Api/Utils.cs +++ b/src/Auth0.AspNetCore.Authentication.Api/Utils.cs @@ -17,7 +17,7 @@ public static string CreateAgentString() { Version? sdkVersion = typeof(AuthenticationBuilderExtensions).GetTypeInfo().Assembly.GetName().Version; var agentJson = - $"{{\"name\":\"auth0-aspnetcore-api\",\"version\":\"{BuildVersionString(sdkVersion)}\"}}"; + $"{{\"name\":\"aspnetcore-api\",\"version\":\"{BuildVersionString(sdkVersion)}\"}}"; return Convert.ToBase64String(Encoding.UTF8.GetBytes(agentJson)); } diff --git a/tests/Auth0.AspNetCore.Authentication.Api.IntegrationTests/DPoPRequiredModeIntegrationTests.cs b/tests/Auth0.AspNetCore.Authentication.Api.IntegrationTests/DPoPRequiredModeIntegrationTests.cs deleted file mode 100644 index 5cbd659..0000000 --- a/tests/Auth0.AspNetCore.Authentication.Api.IntegrationTests/DPoPRequiredModeIntegrationTests.cs +++ /dev/null @@ -1,255 +0,0 @@ -using System.Net; -using System.Net.Http.Headers; -using FluentAssertions; - -namespace Auth0.AspNetCore.Authentication.Api.IntegrationTests; - -/// -/// Integration tests for Auth0 DPoP authentication in Required mode. -/// In Required mode, only DPoP-bound tokens are accepted. Regular Bearer tokens are rejected. -/// -public class DPoPRequiredModeIntegrationTests : IAsyncLifetime -{ - private TestWebApplicationFactory? _factory; - private Auth0TokenHelper? _tokenHelper; - private DPoPHelper? _dpopHelper; - private Auth0Scenario? _scenario; - - public async Task InitializeAsync() - { - _scenario = Auth0TestConfiguration.WithDPoPRequired; - _factory = new TestWebApplicationFactory(_scenario); - _tokenHelper = new Auth0TokenHelper(_scenario.Domain, _scenario.ClientId, _scenario.ClientSecret, _scenario.Audience); - _dpopHelper = new DPoPHelper(); - - await Task.CompletedTask; - } - - public async Task DisposeAsync() - { - _dpopHelper?.Dispose(); - await (_factory?.DisposeAsync() ?? ValueTask.CompletedTask); - } - - #region Happy Path Tests - - [Fact] - public async Task ProtectedEndpoint_WithDPoPToken_ReturnsOk() - { - // Arrange - using var client = _factory!.CreateClient(); - - // Get DPoP-bound access token from Auth0 - var dpopToken = await _dpopHelper!.GetDPoPAccessTokenAsync( - _scenario!.Domain, - _scenario.ClientId, - _scenario.ClientSecret, - _scenario.Audience - ); - - // Create DPoP proof for the API request - var requestUrl = $"{client.BaseAddress}api/protected"; - var dpopProof = _dpopHelper.CreateDPoPProof("GET", requestUrl, dpopToken); - - // Set up the request with DPoP headers - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("DPoP", dpopToken); - client.DefaultRequestHeaders.Add("DPoP", dpopProof); - - // Act - var response = await client.GetAsync("/api/protected"); - - // Assert - response.StatusCode.Should().Be(HttpStatusCode.OK); - var content = await response.Content.ReadAsStringAsync(); - content.Should().Contain("protected endpoint"); - } - - #endregion - - #region Sad Path Tests - - [Fact] - public async Task ProtectedEndpoint_WithBearerToken_ReturnsBadRequest() - { - // Arrange - using var client = _factory!.CreateClient(); - - // For this test, we'll use a mock Bearer token instead of getting one from Auth0 - // because the Auth0 client in Required mode won't issue Bearer tokens - var mockBearerToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2V4YW1wbGUuYXV0aDAuY29tLyIsInN1YiI6InRlc3QiLCJhdWQiOiJ0ZXN0IiwiZXhwIjoxfQ.mock"; - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", mockBearerToken); - - // Act - var response = await client.GetAsync("/api/protected"); - - // Assert - // In DPoP Required mode, invalid Bearer tokens return BadRequest (400) before scheme validation - response.StatusCode.Should().Be(HttpStatusCode.BadRequest); - } - - [Fact] - public async Task ProtectedEndpoint_WithoutToken_ReturnsBadRequest() - { - // Arrange - using var client = _factory!.CreateClient(); - // No token is set - - // Act - var response = await client.GetAsync("/api/protected"); - - // Assert - // In DPoP Required mode, missing token returns 400 BadRequest - response.StatusCode.Should().Be(HttpStatusCode.BadRequest); - } - - [Fact] - public async Task ProtectedEndpoint_WithInvalidDPoPToken_ReturnsUnauthorized() - { - // Arrange - using var client = _factory!.CreateClient(); - - var invalidToken = "invalid.dpop.token.here"; - var requestUrl = $"{client.BaseAddress}api/protected"; - var dpopProof = _dpopHelper!.CreateDPoPProof("GET", requestUrl, invalidToken); - - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("DPoP", invalidToken); - client.DefaultRequestHeaders.Add("DPoP", dpopProof); - - // Act - var response = await client.GetAsync("/api/protected"); - - // Assert - response.StatusCode.Should().Be(HttpStatusCode.Unauthorized); - } - - [Fact] - public async Task ProtectedEndpoint_WithDPoPTokenButMissingProof_ReturnsBadRequest() - { - // Arrange - using var client = _factory!.CreateClient(); - - // Get DPoP-bound access token - var dpopToken = await _dpopHelper!.GetDPoPAccessTokenAsync( - _scenario!.Domain, - _scenario.ClientId, - _scenario.ClientSecret, - _scenario.Audience - ); - - // Set authorization header but omit DPoP proof - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("DPoP", dpopToken); - - // Act - var response = await client.GetAsync("/api/protected"); - - // Assert - Should fail because DPoP proof is missing - response.StatusCode.Should().Be(HttpStatusCode.BadRequest); - } - - [Fact] - public async Task ProtectedEndpoint_WithDPoPTokenButInvalidProof_ReturnsBadRequest() - { - // Arrange - using var client = _factory!.CreateClient(); - - // Get DPoP-bound access token from Auth0 - var dpopToken = await _dpopHelper!.GetDPoPAccessTokenAsync( - _scenario!.Domain, - _scenario.ClientId, - _scenario.ClientSecret, - _scenario.Audience - ); - - // Set authorization header with an invalid DPoP proof - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("DPoP", dpopToken); - client.DefaultRequestHeaders.Add("DPoP", "invalid.dpop.proof"); - - // Act - var response = await client.GetAsync("/api/protected"); - - // Assert - // Invalid DPoP proof should return 400 BadRequest - response.StatusCode.Should().Be(HttpStatusCode.BadRequest); - } - - [Fact] - public async Task ProtectedEndpoint_WithDPoPProofForWrongMethod_ReturnsBadRequest() - { - // Arrange - using var client = _factory!.CreateClient(); - - // Get DPoP-bound access token from Auth0 - var dpopToken = await _dpopHelper!.GetDPoPAccessTokenAsync( - _scenario!.Domain, - _scenario.ClientId, - _scenario.ClientSecret, - _scenario.Audience - ); - - // Create DPoP proof for POST but use it with GET request - var requestUrl = $"{client.BaseAddress}api/protected"; - var dpopProof = _dpopHelper.CreateDPoPProof("POST", requestUrl, dpopToken); - - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("DPoP", dpopToken); - client.DefaultRequestHeaders.Add("DPoP", dpopProof); - - // Act - var response = await client.GetAsync("/api/protected"); - - // Assert - // Mismatched HTTP method in proof should return 400 BadRequest - response.StatusCode.Should().Be(HttpStatusCode.BadRequest); - } - - #endregion - - #region Public Endpoint Tests - - [Fact] - public async Task PublicEndpoint_WithoutToken_ReturnsOk() - { - // Arrange - using var client = _factory!.CreateClient(); - // No token is set - - // Act - var response = await client.GetAsync("/api/public"); - - // Assert - response.StatusCode.Should().Be(HttpStatusCode.OK); - var content = await response.Content.ReadAsStringAsync(); - content.Should().Contain("public endpoint"); - } - - [Fact] - public async Task PublicEndpoint_WithDPoPToken_ReturnsOk() - { - // Arrange - using var client = _factory!.CreateClient(); - - // Get DPoP-bound access token from Auth0 - var dpopToken = await _dpopHelper!.GetDPoPAccessTokenAsync( - _scenario!.Domain, - _scenario.ClientId, - _scenario.ClientSecret, - _scenario.Audience - ); - - // Create DPoP proof for the API request - var requestUrl = $"{client.BaseAddress}api/public"; - var dpopProof = _dpopHelper.CreateDPoPProof("GET", requestUrl, dpopToken); - - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("DPoP", dpopToken); - client.DefaultRequestHeaders.Add("DPoP", dpopProof); - - // Act - var response = await client.GetAsync("/api/public"); - - // Assert - response.StatusCode.Should().Be(HttpStatusCode.OK); - var content = await response.Content.ReadAsStringAsync(); - content.Should().Contain("public endpoint"); - } - - #endregion -} diff --git a/tests/Auth0.AspNetCore.Authentication.Api.UnitTests/UtilsTests.cs b/tests/Auth0.AspNetCore.Authentication.Api.UnitTests/UtilsTests.cs index 55d154d..ec0bc87 100644 --- a/tests/Auth0.AspNetCore.Authentication.Api.UnitTests/UtilsTests.cs +++ b/tests/Auth0.AspNetCore.Authentication.Api.UnitTests/UtilsTests.cs @@ -9,7 +9,7 @@ public void CreateAgentString_ReturnsBase64EncodedJson_With_Correct_Name_And_Ver { var agentString = Utils.CreateAgentString(); var decoded = Encoding.UTF8.GetString(Convert.FromBase64String(agentString)); - decoded.Should().Contain("\"name\":\"auth0-aspnetcore-api\""); + decoded.Should().Contain("\"name\":\"aspnetcore-api\""); decoded.Should().MatchRegex("\"version\":\"\\d+\\.\\d+\\.\\d+\""); }