Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Microsoft.AspNetCore.SystemWebAdapters.sln
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.System
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.SystemWebAdapters.Apis.Tests", "test\Microsoft.AspNetCore.SystemWebAdapters.Apis.Tests\Microsoft.AspNetCore.SystemWebAdapters.Apis.Tests.csproj", "{E4D9A131-DC4E-403F-A10F-65F5E5E42475}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsAuth", "samples\WindowsAuth\WindowsAuth.csproj", "{B5E840F8-2021-4175-BFBF-F9447506242E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -222,6 +224,10 @@ Global
{E4D9A131-DC4E-403F-A10F-65F5E5E42475}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E4D9A131-DC4E-403F-A10F-65F5E5E42475}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E4D9A131-DC4E-403F-A10F-65F5E5E42475}.Release|Any CPU.Build.0 = Release|Any CPU
{B5E840F8-2021-4175-BFBF-F9447506242E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B5E840F8-2021-4175-BFBF-F9447506242E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B5E840F8-2021-4175-BFBF-F9447506242E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B5E840F8-2021-4175-BFBF-F9447506242E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -264,6 +270,7 @@ Global
{FA39AC22-0725-4532-A682-B054ADA5BDA2} = {03E4CEAB-D845-402A-9311-F7390B24BA2A}
{17055F45-E79A-41EF-825E-0B2211433729} = {A1BDA50C-D70B-416C-97F1-74B0649797C5}
{E4D9A131-DC4E-403F-A10F-65F5E5E42475} = {A1BDA50C-D70B-416C-97F1-74B0649797C5}
{B5E840F8-2021-4175-BFBF-F9447506242E} = {95915611-30BF-4AFF-AE41-5CDC6F57DCF7}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DABA3C65-9D74-4EB6-9B1C-730328710EAD}
Expand Down
23 changes: 23 additions & 0 deletions samples/WindowsAuth/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Microsoft.AspNetCore.Authentication.Negotiate;
using Microsoft.AspNetCore.SystemWebAdapters;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();

var app = builder.Build();

app.UseAuthentication();

app.MapGet("/", (HttpContext context) =>
{
return new
{
User = context.User.Identity?.Name,
Principal = context.AsSystemWeb().User.Identity?.Name,
LogonUser = OperatingSystem.IsWindows() ? context.AsSystemWeb().Request.LogonUserIdentity?.Name : null,
};
});

app.Run();
38 changes: 38 additions & 0 deletions samples/WindowsAuth/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": false,
"iisExpress": {
"applicationUrl": "http://localhost:50790",
"sslPort": 44383
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5041",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7245;http://localhost:5041",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
18 changes: 18 additions & 0 deletions samples/WindowsAuth/WindowsAuth.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.Negotiate" Version="8.0.7" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SystemWebAdapters.CoreServices\Microsoft.AspNetCore.SystemWebAdapters.CoreServices.csproj" />
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.SystemWebAdapters\Microsoft.AspNetCore.SystemWebAdapters.csproj" />
</ItemGroup>

</Project>
8 changes: 8 additions & 0 deletions samples/WindowsAuth/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
9 changes: 9 additions & 0 deletions samples/WindowsAuth/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,29 @@

using Microsoft.AspNetCore.Http.Features.Authentication;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Claims;
using System.Security.Principal;
using System.Web;

namespace Microsoft.AspNetCore.SystemWebAdapters.Features;

/// <summary>
/// Represents the user as an <see cref="IPrincipal"/> as opposed to the in-built <see cref="IHttpAuthenticationFeature.User"/> which
/// expects a <see cref="ClaimsPrincipal"/>.
/// Represents the users that ASP.NET Framework used.
/// </summary>
[Experimental(Constants.ExperimentalFeatures.DiagnosticId)]
public interface IPrincipalUserFeature
public interface IRequestUserFeature
{
/// <summary>
/// Gets or sets the user that corresponds to <see cref="HttpContext.User" />
/// </summary>
IPrincipal? User { get; set; }

/// <summary>
/// Gets the logged on user that corresponds to <see cref="HttpRequest.LogonUserIdentity" />
/// </summary>
WindowsIdentity? LogonUserIdentity { get; }
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ internal HttpRequest() { }
public bool IsLocal { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public bool IsSecureConnection { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public string this[string key] { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public System.Security.Principal.WindowsIdentity LogonUserIdentity { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public System.Collections.Specialized.NameValueCollection Params { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public string Path { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public string PathInfo { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
Expand Down Expand Up @@ -483,6 +484,7 @@ public abstract partial class HttpRequestBase
public virtual bool IsLocal { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public virtual bool IsSecureConnection { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public virtual string this[string key] { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public virtual System.Security.Principal.WindowsIdentity LogonUserIdentity { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public virtual System.Collections.Specialized.NameValueCollection Params { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public virtual string Path { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public virtual string PathInfo { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
Expand Down Expand Up @@ -527,6 +529,7 @@ public partial class HttpRequestWrapper : System.Web.HttpRequestBase
public override bool IsLocal { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public override bool IsSecureConnection { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public override string this[string key] { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public override System.Security.Principal.WindowsIdentity LogonUserIdentity { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public override System.Collections.Specialized.NameValueCollection Params { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public override string Path { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
public override string PathInfo { get { throw new System.PlatformNotSupportedException("Only supported when running on ASP.NET Core or System.Web");} }
Expand Down
17 changes: 2 additions & 15 deletions src/Microsoft.AspNetCore.SystemWebAdapters/HttpContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,21 +99,8 @@ public IHttpHandler? Handler

public IPrincipal User
{
get => Context.Features.Get<IPrincipalUserFeature>()?.User ?? Context.User;
set
{
if (Context.Features.Get<IPrincipalUserFeature>() is { } feature)
{
feature.User = value;
}
else
{
var newFeature = new PrincipalUserFeature(Context) { User = value };

Context.Features.Set<IPrincipalUserFeature>(newFeature);
Context.Features.Set<IHttpAuthenticationFeature>(newFeature);
}
}
get => Context.Features.Get<IRequestUserFeature>()?.User ?? Context.User;
set => Context.GetRequestUser().User = value;
}

public HttpSessionState? Session => Context.Features.Get<ISessionStateFeature>()?.Session;
Expand Down
2 changes: 2 additions & 0 deletions src/Microsoft.AspNetCore.SystemWebAdapters/HttpRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ internal HttpRequest(HttpRequestCore request)

public string CurrentExecutionFilePath => Request.HttpContext.Features.GetRequired<IHttpRequestPathFeature>().CurrentExecutionFilePath;

public WindowsIdentity? LogonUserIdentity => Request.HttpContext.GetRequestUser().LogonUserIdentity;

public NameValueCollection Headers => _headers ??= Request.Headers.ToNameValueCollection();

public Uri Url => new(Request.GetEncodedUrl());
Expand Down
2 changes: 2 additions & 0 deletions src/Microsoft.AspNetCore.SystemWebAdapters/HttpRequestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public abstract class HttpRequestBase

public virtual string? FilePath => throw new NotImplementedException();

public virtual WindowsIdentity? LogonUserIdentity => throw new NotImplementedException();

public virtual ReadEntityBodyMode ReadEntityBodyMode => throw new NotImplementedException();

public virtual void SaveAs(string filename, bool includeHeaders) => throw new NotImplementedException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Collections.Specialized;
using System.IO;
using System.Security.Principal;
using System.Text;

namespace System.Web
Expand Down Expand Up @@ -42,6 +43,8 @@ public override string? ContentType

public override NameValueCollection Form => _request.Form;

public override WindowsIdentity? LogonUserIdentity => _request.LogonUserIdentity;

public override string HttpMethod => _request.HttpMethod;

public override Stream InputStream => _request.InputStream;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Security.Claims;
using System.Security.Principal;
using Microsoft.AspNetCore.Http.Features.Authentication;
using Microsoft.AspNetCore.SystemWebAdapters.Features;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

namespace Microsoft.AspNetCore.SystemWebAdapters;

internal static partial class RequestUserExtensions
{
public static IRequestUserFeature GetRequestUser(this HttpContextCore context)
{
if (context.Features.Get<IRequestUserFeature>() is { } existing)
{
return existing;
}

var newFeature = new RequestUserFeature(context) { User = context.User };

context.Features.Set<IRequestUserFeature>(newFeature);
context.Features.Set<IHttpAuthenticationFeature>(newFeature);

return newFeature;
}

private sealed partial class RequestUserFeature : IRequestUserFeature, IHttpAuthenticationFeature
{
private readonly ILogger _logger;

public RequestUserFeature(HttpContextCore context)
{
var logger = (ILogger?)context.RequestServices?.GetService<ILoggerFactory>()?.CreateLogger<RequestUserFeature>();

_logger = logger ?? NullLogger.Instance;

User = context.User;
}

[LoggerMessage(0, LogLevel.Debug, "A custom principal {PrincipalType} is being used and should be replaced with a ClaimsPrincipal derived type.")]
private partial void LogNonClaimsPrincipal(Type principalType);

public IPrincipal? User { get; set; }

WindowsIdentity? IRequestUserFeature.LogonUserIdentity => User?.Identity as WindowsIdentity;

ClaimsPrincipal? IHttpAuthenticationFeature.User
{
get => GetOrCreateClaims(User);
set => User = value;
}

private ClaimsPrincipal? GetOrCreateClaims(IPrincipal? principal)
{
if (principal is null)
{
return null;
}

if (principal is ClaimsPrincipal claimsPrincipal)
{
return claimsPrincipal;
}

LogNonClaimsPrincipal(principal.GetType());

return new ClaimsPrincipal(principal);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
<Compile Include="Adapters/SessionState/ISessionState.cs" />
<Compile Include="IHtmlString.cs" />
<Compile Include="HtmlString.cs" />

<PackageReference Include="System.Security.Principal.Windows" Version="4.3.0" />
</ItemGroup>

<ItemGroup Condition=" '$(TargetFramework)' == 'net6.0' ">
Expand Down
Loading