Skip to content

Commit

Permalink
perf: remove oauth2 introspection authentication
Browse files Browse the repository at this point in the history
+ replace obsolete open telemetry methode
  • Loading branch information
Azaferany committed Jun 7, 2023
1 parent 2ee1c30 commit d7b3f6a
Show file tree
Hide file tree
Showing 7 changed files with 17 additions and 165 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,7 @@ msbuild.wrn
.vs/

*.nupkg


/test/*/*.received.txt
/test/*/*/*.feature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
<PackageReference Include="Serilog.Expressions" Version="3.4.1" />
<PackageReference Include="Serilog.HttpClient" Version="2.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="IdentityModel.AspNetCore.AccessTokenValidation" Version="1.0.0-preview.3" />
<PackageReference Include="IdentityModel.AspNetCore.OAuth2Introspection" Version="6.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.16" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="7.0.5" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="7.0.5" />
Expand Down
62 changes: 8 additions & 54 deletions src/QuickstartTemplate.WebApi/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using System.Reflection;
using IdentityModel.AspNetCore.AccessTokenValidation;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.Extensions.Http;
using Microsoft.Extensions.Internal;
using Microsoft.OpenApi.Models;
using Npgsql;
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using Prometheus;
Expand Down Expand Up @@ -77,33 +77,21 @@ public void ConfigureServices(IServiceCollection services)
options.Authority = _configuration["Authentication:Authority"];
options.Audience = _configuration["Authentication:ApiName"];
options.MapInboundClaims = false;
options.TokenValidationParameters.NameClaimType = "sub"; // user id accessible by HttpContext.User.Identity.Name
options.TokenValidationParameters.NameClaimType =
"sub"; // user id accessible by HttpContext.User.Identity.Name
options.SaveToken = true;
options.RequireHttpsMetadata = true;
// if token does not contain a dot, it is a reference token
options.ForwardDefaultSelector = Selector.ForwardReferenceToken("Introspection");
})

// reference tokens
.AddOAuth2Introspection("Introspection", options =>
{
options.Authority = _configuration["Authentication:Authority"];
options.ClientId = _configuration["Authentication:ApiName"];
options.ClientSecret = _configuration["Authentication:ApiSecret"];
options.NameClaimType = "sub"; // user id accessible by HttpContext.User.Identity.Name
options.EnableCaching = true;
});

services.AddScopeTransformation();

services.AddAuthorization(options =>
{
options.AddPolicy("admin",
policy => policy.RequireScope("QuickstartTemplate:admin"));
policy => policy.RequireRole("QuickstartTemplate:admin"));
options.AddPolicy("read",
policy => policy.RequireScope("QuickstartTemplate:read"));
policy => policy.RequireRole("QuickstartTemplate:read"));
options.AddPolicy("write",
policy => policy.RequireScope("QuickstartTemplate:write"));
policy => policy.RequireRole("QuickstartTemplate:write"));
});

services.AddHttpContextAccessor();
Expand Down Expand Up @@ -147,40 +135,6 @@ public void ConfigureServices(IServiceCollection services)
//... and tell Swagger to use those XML comments.
options.IncludeXmlComments(xmlPath);

options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
Password = new OpenApiOAuthFlow
{
TokenUrl = new Uri($"{_configuration["Authentication:Authority"]}/connect/token"),
},
ClientCredentials = new OpenApiOAuthFlow
{
TokenUrl = new Uri($"{_configuration["Authentication:Authority"]}/connect/token"),
}
}
});

options.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "oauth2"
},
Scheme = "oauth2",
Name = "oauth2",
In = ParameterLocation.Header
},
new List<string>()
}
});

options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme. Example: 'Bearer 12345abcdef'",
Expand Down Expand Up @@ -216,7 +170,7 @@ public void ConfigureServices(IServiceCollection services)
//https://github.com/dotnet/aspnetcore/issues/39317
services.AddHttpLogging(options => _configuration.Bind("HttpLogging", options));

services.AddOpenTelemetryTracing(builder =>
services.AddOpenTelemetry().WithTracing(builder =>
{
builder.AddSource(typeof(Startup).Assembly.FullName);
builder.AddSource(typeof(ApplicationCoreSetup).Assembly.FullName);
Expand Down Expand Up @@ -246,6 +200,7 @@ public void ConfigureServices(IServiceCollection services)
.WithExceptionStats()
.WithErrorHandler(ex => Console.WriteLine("ERROR on per: " + ex))
.StartCollecting();
#endif

//https://github.com/prometheus-net/prometheus-net#eventcounter-integration
// Collect below metrics and more
Expand All @@ -256,7 +211,6 @@ public void ConfigureServices(IServiceCollection services)

//https://github.com/prometheus-net/prometheus-net#net-6-meters-integration
var meter = MeterAdapter.StartListening();
#endif

services.AddHealthChecks()
.AddDbContextCheck<ProjectDbContext>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<PackageReference Include="FluentAssertions" Version="6.11.0" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.5" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageReference Include="NSubstitute" Version="5.0.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,19 +105,6 @@
}
},
"securitySchemes": {
"oauth2": {
"type": "oauth2",
"flows": {
"password": {
"tokenUrl": "https://demo.duendesoftware.com/connect/token",
"scopes": { }
},
"clientCredentials": {
"tokenUrl": "https://demo.duendesoftware.com/connect/token",
"scopes": { }
}
}
},
"Bearer": {
"type": "apiKey",
"description": "JWT Authorization header using the Bearer scheme. Example: 'Bearer 12345abcdef'",
Expand All @@ -127,11 +114,8 @@
}
},
"security": [
{
"oauth2": [ ]
},
{
"Bearer": [ ]
}
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,19 +105,6 @@
}
},
"securitySchemes": {
"oauth2": {
"type": "oauth2",
"flows": {
"password": {
"tokenUrl": "https://demo.duendesoftware.com/connect/token",
"scopes": { }
},
"clientCredentials": {
"tokenUrl": "https://demo.duendesoftware.com/connect/token",
"scopes": { }
}
}
},
"Bearer": {
"type": "apiKey",
"description": "JWT Authorization header using the Bearer scheme. Example: 'Bearer 12345abcdef'",
Expand All @@ -127,11 +114,8 @@
}
},
"security": [
{
"oauth2": [ ]
},
{
"Bearer": [ ]
}
]
}
}
76 changes: 2 additions & 74 deletions test/QuickstartTemplate.WebApi.IntegrationTests/UserDetailTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@
using System.Net.Http.Json;
using System.Security.Claims;
using FluentAssertions;
using IdentityModel.AspNetCore.OAuth2Introspection;
using IdentityModel.Client;
using IdentityModel.Jwk;
using Microsoft.Extensions.DependencyInjection;
using QuickstartTemplate.WebApi.IntegrationTests.Helpers;
using RichardSzalay.MockHttp;

namespace QuickstartTemplate.WebApi.IntegrationTests;

Expand All @@ -33,7 +29,8 @@ public async Task Test_HttpContext_User_Identity_Name_fill_correctly_with_SUB_fr
var request = new HttpRequestMessage(HttpMethod.Get, "v1/Test/UserDetail");

var userId = "64624";
request.SetBearerToken(MockJwtTokens.GenerateJwtToken(new[] { new Claim("sub", userId) }));
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer",MockJwtTokens.GenerateJwtToken(new[] { new Claim("sub", userId) }));

var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Expand All @@ -43,75 +40,6 @@ public async Task Test_HttpContext_User_Identity_Name_fill_correctly_with_SUB_fr
readFromString.Should().BeEquivalentTo(userId);
}

// some mocking like MockJwtTokens needed but i have no idea how do do that.
[Fact]
public async Task Test_HttpContext_User_Identity_Name_fill_correctly_with_SUB_from_OAuth2_Introspection_token()
{
var userId = "12345";

var factory = _customWebApplicationFactory.WithWebHostBuilder(builder =>
builder.ConfigureServices(services =>
{
services.AddControllers()
.AddApplicationPart(GetType().Assembly);

services.AddHttpClient(OAuth2IntrospectionDefaults.BackChannelHttpClientName)
.ConfigurePrimaryHttpMessageHandler(_ =>
{
var mockHttp = new MockHttpMessageHandler();

mockHttp.When($"*/introspect")
.Respond(JsonContent.Create(new
{
iss = "https://demo.duendesoftware.com",
client_id = "PayPingWebApp",
sub = userId,
name = "TestName",
active = true,
scope =
"QuickstartTemplate:admin QuickstartTemplate:read QuickstartTemplate:write"
}));

mockHttp.When($"*/openid-configuration")
.Respond(JsonContent.Create(new
{
issuer = "https://demo.duendesoftware.com",
jwks_uri =
"https://demo.duendesoftware.com/.well-known/openid-configuration/jwks",
authorization_endpoint =
"https://demo.duendesoftware.com/connect/authorize",
token_endpoint = "https://demo.duendesoftware.com/connect/token",
userinfo_endpoint = "https://demo.duendesoftware.com/connect/userinfo",
introspection_endpoint =
"https://demo.duendesoftware.com/connect/introspect",
scopes_supported = new List<string>()
{
"QuickstartTemplate:admin",
"QuickstartTemplate:read",
"QuickstartTemplate:write"
},
claims_supported = new List<string>() { "sub", "name" }
}));
mockHttp.When("*/jwks").Respond(JsonContent.Create(new JsonWebKeySet
{
Keys = new List<JsonWebKey>() { new JsonWebKey() { Alg = "test" } }
}));
return mockHttp;
});
}
));

var client = factory.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Get, "v1/Test/UserDetail");

request.SetBearerToken("testtoken");

var response = await client.SendAsync(request);

var readFromString = await response.Content.ReadFromJsonAsync<string>();

readFromString.Should().BeEquivalentTo(userId);
}
[Fact]
public async Task Test_Default_Culture_On_RequestLocalization()
{
Expand Down

0 comments on commit d7b3f6a

Please sign in to comment.