Get the Current User in WebAPI2 with OWIN - c#

Here's a bit of a back story, feel free to skip to the problem below.
We have a handful of web applications exposed to the outside world (as opposed to ONLY on our internal business network) and these applications are using HTML5 for the offline capabilities. We also had IIS configured for Windows Authentication ONLY (no outside parties use our applications), thus we were issuing the challenge directly against our AD. With a recent update to Chrome for iOS, it broke the NTLM authentication (instead of prompting for use credentials, it just displayed a 401 unauthorized exception page) so we started looking at alternative solutions.
We figured we could leverage our current external ADFS/O365 access thus the user experience would be the same across all external facing applications (not just web apps).
We ended up adding OWIN to our WebForms app to use ADFS authentication and it works from a perspective of you can see the redirect to our external login page and then back to the web app. However, there is an additional problem. To get this to work, we had to DISABLE Windows Authentication in IIS and ENABLE Anonymous Authentication. Also, in the Web.Config in <system.web> we added <authorization><deny users="?" /></authorization>
PROBLEM
Since our applications are using HTML5 and are available offline, we are also using Web API to handle the push of data from the client device to the central system. When we moved to our "SSO type" solution, the POST methods in Web API started crashing. Turns out the line HttpContext.Current.User.Identity.Name stopped working.
How can I get the current authenticated [signed in] user when the user returns to the network and sync's their data? I'm not even sure what the best approach is here, I've tried a few different suggestions from SO and Google, but none seem to work. How does one get the current user in Web API with Owin using Federated Services?

Related

ASP.NET Identity with React app is breaking on OAuth2 callback

I have used the ASP.NET Core React project template to create a web application into which I've installed Identity Server 4. The React app takes care of all the user interaction, with the dotnet application used as an API only. I've integrated a Google OAuth2 authentication option using the services.AddAuthentication().AddGoogle builder extension provided by Microsoft.AspNetCore.Authentication. Finally, the whole thing is containerised and deployed to a Linux App Service on Azure.
Most of my code was ported from a previous version which was a very similar setup but in that case I'd added a custom React app to an existing ASP.NET application rather than start with the official React project template for dotnet. Back then everything worked well. But I'm facing problems with my new version when deployed to Azure. Here's a Fiddler trace to highlight the issue:
vault2 is a client of the identity service. identity-azure is the Identity Server application. The flow this trace shows is as follows:
User clicks Sign In on the Vault application
Browser is redirected to the Identity application
User clicks the Google button to initiate the OAuth2 flow
User signs in with Google account
User is redirected to the default callback URL (https://identity-azure.<domain>.com/signin-google?state=...)
This last step is where the problem is. You'll notice that you don't see the callback URL in the Fiddler trace, but instead you see a couple of other requests (e.g. service-worker.js) which are clearly being made from the React app. So the signin-google path is being handled by the browser's cached React app and not the server. The React app uses react-router-redux to handle certain routes client-side, and of course signin-google is not one of these so it appears to be returning an empty component.
As far as I can tell, all my ASP.NET routes (implemented using the Route attribute to decorate controller action methods) are handled consistently by the server. However, the signin-google route is implemented in the authentication middleware so as far as I know I don't have much control over it other than to change its path. Is there something I can do to force this to be handled server-side?
I should add that this behaviour is quite erratic. It seems that if my Google account is signed out then the above is observed, but if my account is already signed in then signin-google returns the expected 302 status code and the OAuth2 flow continues successfully.
I finally worked out what was going on. At least, I think I have. I can't be certain because I've since broken the React UI out into an entirely separate application but I was observing a similar pattern there. There was even a clue in my original question! Turns out the breaking pages were actually being served from the React app's service worker. I discovered this because even after breaking the React app out under its own domain leaving my identity-azure domain a pure ASP.NET Web API, requests for certain URLs under identity-azure were still behaving the same and I eventually noticed they were reporting themselves as being served by ServiceWorker on my browsers's Network tab. Example below.
As soon as I cleared the browsers application cache (in Chrome on Windows this was F12 > Application > Clear storage > Clear site data with Unregister service workers checked.
I'm not 100% sure what the solution would be if I'd left my React app in the same solution as the ASP.NET backend, but I presume it'd involve excluding specific URLs from service worker. I hope this helps someone in the future.
By the way, if you're thinking of building a fully decoupled UI for Identity Server 4, there's a great starter example here.

403 Forbidden when using client managed authentication on Azure App Service

I've been working on a multi-app project for a few months now using Azure App Service for my database and ADD B2C for authentication. There are three applications in this project: an admin WPF app, a client web app, and an employee WPF app. All three applications use client managed authentication with my B2C tenant by getting a token from B2C and using that token to login to the App Service database. Everything has been working fine until seemingly overnight I am no longer able to authenticate with the app service. I have no problem displaying the B2C login screen and getting an access token as a result of the authentication, but when I package the token in a JObject and call the 'mobileServiceClient.LoginAsync()' function, all I get back is a 403 "forbidden" error.
First I tried seeing if all three projects were affected, which they are. I then tried rolling back to my last commit. Still the same thing. I then tried re-cloning to see if there was any little quirk with still the same results. Because I know my Azure resources have not hit their limits, I then tried making a completely separate WPF project and I made a table on the app service that allows anonymous access. After setting "Action to take when request is not authenticated" to "Allow anonymous access" on the app service, I was able to read and write to the anonymous table without issue. I then tried to have this new project authenticate the same way the others have been only to get the same 403 error. After checking all of this I can say I'm almost completely sure that there is no issue with the client applications and the issue has to be on the server side.The most confusing part for me is that aside from adding a new table to the database, I haven't changed a single thing server side. I've checked out both the B2C tenant and the authentication settings on the app service but nothing seems to be different than before I was experiencing this problem. Investigating a little bit more in the app service, I tried to find some JS code that handles authentication to see if I could find any useful information using the console output. I did not find any code, but I did find out the console outputs PID[31680] Information Sending response: 403.76 Forbidden whenever a client tries to authenticate.
Additional information that might help is that my request header timestamp is correct. I know from research that Azure only allows a 15 minute variance for incoming requests from its time.
Any help or suggestions for solving this issue would be greatly appreciated! Thanks!

How to implement IIS authentication in an asp.net web api project?

I've been tasked with enabling authentication and authorization for our project's api. The main goal is to protect the methods from misuse, however we also need to enable a developer from another company to call the methods in their code.
Being new to authentication and authorization I'm overwhelmed with the many different options available for .NET etc. Some techniques look promising until you read that they pass credentials in plain text (basic auth?) or have other issues etc... I'm just looking for a reliable and safe approach.
I'm using IIS to host the web api, and I have seen that one such option is to authenticate at the 'host level'. My supervisor has mentioned this is the preferred approach.
I have looked at many threads and videos regarding authenticating in IIS. From what I can work out, such a solution alerts the user that a certain action requires authentication and to enter their credentials.
My issues are as follows:
Given the other developer is not a member of our domain, how can they authenticate using their (windows?) credentials. Is there an alternative to windows authentication?
How will requiring authorization on certain api actions impact the function of the site normally? I.e. will I have to pass valid credentials to the api in my code, for each request?
Overall I'm just a bit uncertain on how this all works and I appreciate any advice given.

How to get windows credentials from browser via Angularjs app and using them in the service level?

I have been scratching my head how to solve the issue described below.
So, the company where I work uses Visual Studio Team Services (was Visual Studio Online), and it is integrated/connected to our AD, meaning that If I log in to my workstation I can log in to Team Services without authenticating myself, like SSO.
I'm going to create an application which communicates to Team Services via Team Services SOAP and WebApi clients and here is the problem. I need a user to be able to communicate with Team Services and doing stuff (reading data, creating work items, creating test suits, etc.). I see little chance to convince IT to create a user only for this. They going to reject my request due to security risks.
The application architecture looks this:
browser: angularjs application, spa, calling only the WebApi service
server: WebApi service, which is responsible to communicate with Team Services and transforming data back and forth between the client and Team Services.
database: persisting data for later analysis
There is an idea in my mind, where I can get somehow the windows credentials from the OS and push it down to the server which uses it to communicate with Team Services. In Team Services, we will see that the particular user did things.
The question, how is possible that? The articles I have found searching for something similar, always mention .Net MVC app where I need to modify the web.config in order to get the credentials. But, in my architecture there is no .Net MVC app running on local machines. There is only a SPA running in browsers.
Or my architecture is not fit for this purpose? Shall I rework it and using MVC app to be able to get the credentials and working with them? But, the question still stands, how can I pass the credentials through the calls calling Team Services?
Do you know blog entries dealing with cases like above?
Thanks for any help in advance!
I think you have a bit of confusion over your terms. The SPA (Single Page App) has javascript code delivered by the server to the browser that calls the .NET WebApi code. In order to get the browser to use Kerberos/Windows Authentication you need to add
<system.web>
<authentication mode="Windows" />
</system.web>
to your web.config on the server where the .NET app is running (under IIS).
From here...
http://www.asp.net/web-api/overview/security/integrated-windows-authentication
"On the client side, Integrated Windows authentication works with any browser that supports the Negotiate authentication scheme, which includes most major browsers. For .NET client applications, the HttpClient class supports Windows authentication:"
Then the browser will do the rest for you and the HttpContext.CurrentUser in the .NET code on the server will be set to the windows user of the clients browser.

.NET OWIN Authentication - Cookie + Windows (active directory)

I'm currently working on a project which has an authentication requirement which is causing me some problems and I'd like some guidance on the best way to achieve it.
I have an internet C# MVC 5 project which currently has OWIN cookie authentication in place for external users. We now need to allow internal users to be able to access the application through Active Directory. Basically, an internal user would log in to their Windows computer, navigate to the website and they'll be signed in.
I don't have any experience of doing AD authentication, so it's a bit of a black hole at the moment.
I'm assuming, using OWIN, I need to create a new authentication middleware that can run before my cookie authentication.
However, I'm not sure where to start with setting this AD middleware up, or whether there is an existing one I can use.
I've tried searching around but can't seem to find much information on doing AD authentication through OWIN, there's just a lot about Azure AD.
I did come across this one https://github.com/MohammadYounes/OWIN-MixedAuth, but running locally, it's using Windows basic authentication, perhaps this can be adjusted for my purposes?
Could someone offer some advice on how to achieve this?
Thank you!
I was facing the same problem not-so-long ago, and went the route to use NTLM authentication (which boils down to what you want, intranet users will be "signed-in" automatically) while keeping full application accounts (ASP:NET Identity 2.0), you may want to check my OWIN NTML authentication middleware:
https://github.com/pysco68/Pysco68.Owin.Authentication.Ntlm
You will need to add a route to you "accounts controller" to handle the sign-in with NTLM and the creation of a local application account (if required). As a comfort-feature you could add an automatic redirect to that sign-in route for users from your intranet.
I hope this helps.
The link you came across is using Integrated Windows authentication NOT basic authentication.
I think your situation is similar to this one. The same can be achieved using OWIN-MixedAuth as per this comment.

Categories