.Net Core 3 Windows Auth stops receiving credentials - c#

So I've been using the following code to get windows user-name within my .NET Core 2 web applications. However, I'm trying to use the same method in .NET Core 3 and it works, but periodically it will just stop working and I have to restart the application in order for it to start working. I'm not sure whether it's a timeout or something else.
Here's the code that I'm using within my Authentication controller
AuthController.cs
public AuthController()
{
}
[Authorize]
public override void OnActionExecuting(ActionExecutingContext context)
{
var userName = User.Identity.Name;
}
Like I said before, this usually works fine. But on occasion it stops working completely till I restart the application. The issue I get is a NullReferenceException on the User object itself. Is there something new in .NET Core 3 or is there something that I'm just completely missing here?
Thanks

Related

How to track dependencies, exceptions and requests for Live Metrics in ASP.NET MVC app?

I've configured Live Metrics for my ASP.NET MVC app with target framework 4.7.2 using the tutorial given in Microsoft Docs:
https://learn.microsoft.com/en-us/azure/azure-monitor/app/live-stream#enable-livemetrics-using-code-for-any-net-application
In this tutorial, they've given a sample client.TrackDependency() and client.TrackRequest() call in the end. They've also mentioned in comments that those are samples and we must replace it with actual application logic to work. I'm new to all these and I don't know what to replace. Since my application is huge and has a lot of methods, it is impractical to call the tracking methods in each method or controller. Since it is not ASP.NET Core, there are no middlewares and I have to enable Live Metrics by code too. I've added the code in the Application_Start() of Global.asax.cs of my application, so that it runs during startup.
This is what I've done so far,
// Create a TelemetryConfiguration instance.
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration telemetryConfig = Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.CreateDefault();
telemetryConfig.InstrumentationKey = System.Web.Configuration.WebConfigurationManager.AppSettings["AppInsightsInstrumentationKey"];
QuickPulseTelemetryProcessor quickPulseProcessor = null;
telemetryConfig.DefaultTelemetrySink.TelemetryProcessorChainBuilder
.Use((next) =>
{
quickPulseProcessor = new QuickPulseTelemetryProcessor(next);
return quickPulseProcessor;
})
.Build();
var quickPulseModule = new QuickPulseTelemetryModule();
// Secure the control channel.
// This is optional, but recommended.
//quickPulseModule.AuthenticationApiKey = "YOUR-API-KEY-HERE";
quickPulseModule.Initialize(telemetryConfig);
quickPulseModule.RegisterTelemetryProcessor(quickPulseProcessor);
// Create a TelemetryClient instance. It is important
// to use the same TelemetryConfiguration here as the one
// used to setup Live Metrics.
TelemetryClient client = new TelemetryClient(telemetryConfig);
// I need some method by which I can track all the requests, exceptions,
// dependencies etc. here.
I searched and searched a lot for a solution but couldn't get a concrete solution. As a last resort I'm requesting you guys to help me. What can I do to track all requests, dependencies, exceptions, etc. globally...?
If you're using the ASP .NET MVC with .Net Framework 4.7.2 Version, You need to configure the Application Insights code related to the .NET Specific SDK Type like Framework, Core, Console, etc.
From the given MS doc, you're following the console app related app insights code but as you're using the MVC Web App so you need to follow this code from this section of documentation.
Here is the workaround I tried to get the live metrics, logs in the Application Insights of Azure Portal.
In Visual Studio, Created the asp .net mvc web app (.NET Framework version 4.7.2)
Added the Application Insights Instrumentation Key in the ApplicationInsights.config
Follow the above documentation as it says to create a new folder in the root and add the ErrorHandler class and modify the FilterConfig class from the App_Start folder in order to match your ErrorHandler Class Functionality.
And then deploy the MVC Web App. While publishing configure the Application Insights in Visual Studio Publish Window like below:
After deploying the App, Open the Web App URL in the browser, then you can see the logs in overview tab and also in App Insights Resource Live Metrics Page as you can see the screenshots below:
I found a solution myself. I found out that I can use the Application_BeginRequest() event handler to catch all requests inside Global.asax itself. All I had to do is to store the TelemetryConfiguration into a global variable and access it from the Application_BeginRequest() handler. This is what I did:
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse;
protected void Application_Start()
{
RegisterLiveMetrics();
// Omitted the other code for brevity
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
var telemetryConfig = Application["TelemetryConfig"] as TelemetryConfiguration;
TelemetryClient client = new TelemetryClient(telemetryConfig);
var httpContextCurrent = HttpContext.Current;
client.TrackRequest(httpContextCurrent.Request.RawUrl, DateTimeOffset.Now,
TimeSpan.FromMilliseconds(230), httpContextCurrent.Response.StatusCode.ToString(),
true);
}
private void RegisterLiveMetrics()
{
// Create a TelemetryConfiguration instance.
Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration telemetryConfig = Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration.CreateDefault();
telemetryConfig.InstrumentationKey = System.Web.Configuration.WebConfigurationManager.AppSettings["AppInsightsInstrumentationKey"];
QuickPulseTelemetryProcessor quickPulseProcessor = null;
telemetryConfig.DefaultTelemetrySink.TelemetryProcessorChainBuilder
.Use((next) =>
{
quickPulseProcessor = new QuickPulseTelemetryProcessor(next);
return quickPulseProcessor;
})
.Build();
var quickPulseModule = new QuickPulseTelemetryModule();
quickPulseModule.Initialize(telemetryConfig);
quickPulseModule.RegisterTelemetryProcessor(quickPulseProcessor);
Application["TelemetryConfig"] = telemetryConfig;
}
Luckily this seems to work fine. Currently I'm only tracking requests.
Note: I'm not sure about the namespaces mentioned above.

Porting ClaimsAuthorizationManager to .NET Core

I am preparing to port an .NET 4.6.1 application to .NET Core and struggle to find how the code permissions should be handled.
Currently i use custom ClaimsAuthorizationManager
public class AuthorizationManager : ClaimsAuthorizationManager
{
public override bool CheckAccess(AuthorizationContext context)
{
var resource = context.Resource.First().Value;
var action = context.Action.First().Value;
return context.Principal.HasClaim(resource,action);
}
}
The ClaimsAuthorizationManager is configured to be used by application in app.config file.
Then each function that needs to have a code access permission has an ClaimsPrincipalPermission set with required permissions.
Now i would want to achieve same functionality in .NET Core and outside of MVC.
Anyone has any idea if and how is this achievable?
Thanks.

Check if a mobile device is requesting the desktop site

I'm using 51 degrees on my MVC site as an adaptive approach to serving my pages. All is working well.
I have recently added output caching and I use the VaryByCustom to check whether it is mobile or desktop:
public override string GetVaryByCustomString(HttpContext context, string custom)
{
// this is for the output cache
if (context != null)
{
switch (custom)
{
case "Mobile":
return GetMobileCustomString(context);
}
}
return base.GetVaryByCustomString(context, custom);
}
private static string GetMobileCustomString(HttpContext context)
{
if (context.Request.Browser.IsMobileDevice)
{
return "IsMobile";
}
else
{
return "IsDesktop";
}
}
However I have run into a problem that if the first mobile user to browse the site has requested the desktop version, this will be cached for all mobile users.
I need to change the GetMobileCustomString to include a check for if it is a mobile requesting a desktop site. Is there any way to do this?
Update
As a bounty has been opened on this, I thought I would offer an update:
Firstly, it was not the first load causing the desktop page to be cached as I had initially thought, so having done a lot of searching, research and testing on this, I feel the desktop page should never be cached for the mobile version (if you are on MVC 5). I have stepped through the code when doing a mobile request and when it gets to the vary by custom, it shows context.Request.Browser.IsMobileDevice as false.
Not sure what is causing the desktop site to be cached for the mobile site - perhaps it is a hangover from the bug in MVC 4. It just seems to be random (ie, one day it will be fine and then another day it will be serving the desktop site for some reason) and recycling the app pool will always fix it.
I also found that I could get the overriden browser by using:
using System.Web.Wepages;
context.Request.RequestContext.HttpContext.GetOverriddenBrowser();
But it didn't seem to be much use
It seems to me like what you are doing should work, provided you are storing the cache at the client side.
You should be using the OutputCache attribute on your controller actions in the following manner:
[OutputCache(Duration = 5, VaryByCustom = "Mobile", Location = OutputCacheLocation.Client)]
(The duration is up to you)
That being said, browser detection is based on HTTP headers so nothing is going to help you if the requesting browser is sending headers for a different agent.
The other option is to use feature detection instead.
I hope that helps.
Within the 51degrees.config there is a setting
<redirect devicesFile="" timeout="20" firstRequestOnly="true"
This firstrequestonly may be confusing your caching system so treating the first mobile device as the first request, and all other mobiles as the same session of the original mobile device. Try setting this to false and see if that helps solve your issue.

Hosting an MVC6 application under default website

I have hosted many ASP.NET and MVC applications before. I was playing with MVC6 lately and tried to host an MVC6 application.
Everything works fine if I host it as a new website. When I host it as an application under the default website of IIS, it only shows an empty page. Please find the log information below
warn:
Microsoft.Extensions.DependencyInjection.DataProtectionServices[0]
Neither user profile nor HKLM registry available. Using an ephemeral key repository. Protected data will be unavailable when
application exits. warn:
Microsoft.AspNet.DataProtection.Repositories.EphemeralXmlRepository[0]
Using an in-memory repository. Keys will not be persisted to storage. Hosting environment: Production Now listening on:
http://localhost:23000 Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNet.Hosting.Internal.HostingEngine[1]
Request starting HTTP/1.1 GET http://localhost/MVC6 info: Microsoft.AspNet.Hosting.Internal.HostingEngine[2]
Request finished in 0.0687ms 404
Note: Default website uses application pool asp.net4.5 and my MVC6 application uses it's own application pool as mentioned in http://docs.asp.net/en/latest/publishing/iis.html#iis-server-configuration
Anyone else faced similar problem like this? I want to know how to make it work under default website
Edit: This is a bug in vs2015 rc1 https://github.com/aspnet/Hosting/issues/416#issuecomment-149046552.
There is a workaround for this bug in above link but I followed a different method because I need to host my application in more than one website without republishing.
I resolved the above problem using the Route attribute. After adding the route attribute to an action result, application works fine
public class HomeController : Controller
{
[Route("MVC6")]
[Route("")]
public IActionResult Index()
{
return View();
}
}

ASP.NET MVC 4 Internet Application Template OAuth RegisterGoogleClient Unsuccessful

I created a Visual Studio ASP.NET MVC 4 Internet Application Template project. I immediately went into the AuthConfig class and uncommented this line:
//AuthWebSecurity.RegisterGoogleClient();
I then ran the application. I clicked 'Log in', then 'Google'. I am redirected to Google where I sign in and then get redirect to the 'ExternalLoginCallback' action in the Account controller. In the debugger these line get executed:
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
if (!result.IsSuccessful)
{
return RedirectToAction("ExternalLoginFailure");
}
No matter what I do the results variable's IsSuccessful property is set to false. I am just wondering what I am doing incorrectly considering I am using the provided template? I have no idea how I can retrieve an error messages from OAuthWebSecurity.VerifyAuthentication to determine what is going on.
Any help is appreciated!
Note: I have tried updating all NuGet packages. I've also tried Microsoft (didn't work because a redirect url + localhost issue) and LinkedIn (didn't work, unsure why but receiving bad request 400 error) OAuth Clients.
I found a Google OAuth2 implementation that I was able to easily get working:
https://github.com/mj1856/DotNetOpenAuth.GoogleOAuth2

Categories