Authorising users in an ASP.NET (MVC5) web api project - asp.net

Ok, so I'm struggling a little bit with trying to get a authentication process in my ASP.NET MVC5 (Web API 2) project. To start, here are some requirements:
I can't use Entity Framework (all access to the DB needs to be done through stored procedures)
Needs to target .NET Framework 4.5.2
I am not using ASP.NET Core
I would like to be able to use Bearer (or similar) tokens for authentication
I would like to invalidate tokens if a user logs out or automatically invalidate them after 24 hours
I would like to pass (and receive) XML when sending requests to the "login" (or "token") endpoint (note that ideally the solution should respect the "Content-Type" and "Accepts" headers, so if I send it JSON it should respond in JSON, and if I send it XML it should respond in XML)
I will not be using external providers (e.g. Google) anytime soon (maybe never)
I would like to use the <Authorize> attributes to help with protecting other endpoints
I am using VB.NET, although answers to this question can be in C# (I can convert them or rewrite them to suit)
I would like to store the tokens in the database so I can record which user is doing what within the API
(note that there are lots of reasons why I can't change the above)
I've tried to do this with Owin (OAuth) but I've found the following issues when comparing this to the requirements:
I can't seem to send the token endpoint any XML
Responses from the authentication endpoints (both successful and unsuccessful) are in JSON
I can't invalidate the tokens when logging out
I am happy to move away from OAuth if that is the best way to go for what I want. I would prefer to use Microsoft built nuget packages (ie no third party solutions) or I'm happy to partially roll my own solution (I would like to leverage as much of in-built or Microsoft built code, including Identity and Claims as possible so I can minimise testing efforts).
I have read numerous StackOverflow questions about this and search heaps on the internet, but most articles stick with OAuth despite the above issues or they rely on EntityFramework. My current solution uses the code from here (pretty much copy/pasted with some custom code in ApplicationOAuthProvider.GrantResourceOwnerCredentials()): https://www.codeproject.com/Articles/1187872/Token-Based-Authentication-for-Web-API-where-Legac
Thanks for the help!

I did some more extensive research and it looks like OAuth is not applicable for my specific situation. Although it seems like a nice authentication method, I really need to invalidate tokens via the DB, and I need the API to always send/receive XML (these are apparently not applicable when using OAuth).
To solve these problems, I have rolled my own token-based solution that creates a hashed token on the client side, so I never send passwords over the wire (which is a little bit nicer) because the token is generated on the client side (note that I am controlling what happens on the client side - these are all in house clients and I am writing the libraries these clients will use). This involved me creating my own filter which inherits System.Web.Http.AuthorizeAttribute.
If anyone stumbles across this question and provides a really good answer, I'm more than happy to mark theirs as accepted.

Related

How to persist frequently used data in Web API Asp.NET Core 5?

I am developing a WebAPI service using ASP.NET Core 5.
I am using JWT Token for authentication on each request if the users are logged in. For the client-side I am using Next.js.
I am looking for a way to save frequently used data like User (userId, email, username, role) without tripping to the DB.
I have done deep research but most of the answers look outdated.
Some of the alternatives I looked
Use the JWT payload to save the User object. ( it doesn't look very secure).
Use a Cache system Redis for example (This looks like one of the best options but it is time-consuming and needs a lot of resources)
Do you guys have any other suggestions?
This is a highly subjective topic, but here is my two cents:
Packing your JWT with data is insecure (as you point out) and also will bloat your traffic if you are passing a very large JWT with each request. You can overcome the first issue (security) by looking into JWE (JSON Web Encryption) -- which is just encrypting the JWT. But the bloat issue will remain depending on how much info you want in there and there is overhead associated with the encryption/decryption process.
Caching is the classic solution to your problem, and Redis is one of the most common implementations (and easier if you're hosting on Azure). Using a hosted Redis cache simplifies this process if you can handle the expense (which largely depends on how much data you are caching and client connection count). This is going to be more scalable if you need to add more data to be cached in the future or change out what data is cached.

In my meteor app, how do I make authenticated google API calls on behalf of my user?

Background: This is my first standalone web development project, and my only experience in Meteor is building the Discover Meteor app over the last summer. I come from about a year of CS experience as a side interest in school, and I am most comfortable with C and C++. I have experience in python and java.
Project so far: I'm creating a calendar management system (for fun). Using accounts-google, I have created user accounts that are authenticated through google. I have requested the necessary permissions that I need for my app, including 'identity' and 'calendar read/write access'. I've spent the last week or so trying to get over this next hurdle, which is actually getting data from google.
Goal: I'd like to be able to make an API call to Calendar.list using a GET request. I've already called meteor add http to add the GET request functionality, my issue comes with the actual implementation.
Problem: I have registered my app on the developer console and set up Accounts using the client ID and secret, but I have not been able to find/generate my 'API key' for use in the request. Here is the google guide for creating the access token by using my (already) downloaded private key. I'm having a hard time wrapping my head around an implementation on the server side using JS because I don't have a lot of experience with what is mentioned in the HTTP/REST portion of the implementation examples. I would appreciate some help on how to implement a handshake and receive an access token for use in my app. If there is a call I can make or some package that will handle the token generation for me, that would be even better than implementation help. I believe an answer to this would also benefit this other question
The SO answer that I've been referring to so far: https://stackoverflow.com/a/14543159/4259653 Some of it is in spanish but it's pretty understandable code. He has an API key for his request, which I asked this question to help me with. The accounts-google documentation isn't really enough to explain this all to me.
Also an unrelated small question: What is the easiest way to deal with 'time' parameters in requests. I'm assuming JS has some sort of built-in functionality that I'm just not aware of yet.
Thanks for your research. I have also asked a very similar question, and right now I am looking into the package you recommend. I have considered this meteor-google-api package, but it looks abandoned.
Regarding your question about time manipulation, I recommend MomentJS. There are many packages out there; I am using meteor add mrt:moment
EDIT: MomentJS now has an official package for Meteor, so use meteor add momentjs:moment instead of the mrt command above
Below is a snippet of what moment can do. More documentation here.
var startTimeUTC = moment.utc(event.startTime, "YYYY-MM-DD HH:mm:ss").format();
//Changes above formatting to "2014-09-08T08:02:17-05:00" (ISO 8601)
//which is acceptable time format for Google API
So I started trying to implement all of this myself on the server side, but was wary of a lot of the hard-coding I was doing and assumptions I was making to fill gaps. My security prof. used to say "never implement encryption yourself", so I decided to take another gander for a helpful package. Revising search criteria to "JWT", I found jagi's meteor-google-oauth-jwt on Atmosphere. The readme is comprehensive and provides everything I need. Following the process used in The Google OAuth Guide, an authorization request can be made and a key generated for making an API call.
Link to Atmosphere: https://atmospherejs.com/jagi/google-oauth-jwt
Link to Repo: https://github.com/jagi/meteor-google-oauth-jwt/
I will update this answer with any additional roadblocks I hit in the Google API process and how I solved them:
Recently, I've been running into problems with the API request result. I get an empty calendarlist back from the API call. I suspect this is becuase I make an API call to my developer account rather than to the subject user. I will investigate the problem and either create a new question or update this solution with the fix I find.
Fix: Wasn't including the 'sub' qualifier to the JWT token. Fixed by modifying JWT package token generation code to include delegationEmail: user.services.google.email after scope. I don't know why he used such a long designation for the option instead of sub: as it is in the google API, but I appreciate his package nontheless.
I'm quickly becoming proficient in this, so if people have meteor-related google auth questions, let me know.
DO NOT USE SERVICE ACCOUNTS AS POSTED ABOVE!
The correct approach is to use standard web access + requesting offline access. The documentation on the api page specifically states this:
Typically, an application uses a service account when the application uses Google APIs to work with its own data rather than a user's data.
The only exception to this is when you are using google apps domain accounts and want to delegate access to your service account for the entire domain:
Authorizing a service account to access data on behalf of users in a domain is sometimes referred to as "delegating domain-wide authority"
This makes logical sense as a user must be allowed to "authorise" your application.
Back to the posters original question the flow is simple:
1) Meteor accounts google package already does most of the work for you to get tokens. You can include the scope for offline access required.
2) if you are building your own flow, you will go through the stock standard process and calls as explained on auth
This will require you to:
1) HTTP call to make the original request or you can piggyback off some of the internal meteor calls : Package.oauth.OAuth.showPopup() -- go look at the source there are more nifty functions around there.
2) Then you need to create an Iron router server side route to accept the oauth response which will contain a code parameter that you will use to exchange for tokens.
3) Next use this code to make a final call to exchange the "code" for the token + refresh_token
4) Store these where ever you want - my requirement was to store them not at the user level but multiple per user
5) Use a package like GoogleAPI this wraps up Google API calls and refreshes when required - it only works when tokens are stored in user accounts so you will need to rip it apart a bit if your tokens are stored somewhere else (like in my case)

OAuth (OAuth2) ASP.NET REST Web API (Self host - windows service) implementation

I have built a Restful Web API for my (android) mobile application, and now i am trying to secure the access to the API. I was reading for about a week on this topic and i got the whole spectrum - from those who say that is is impossible to secure a Restful API to those who say that Https (SSL) is enough.
Here I don't want to start a discussion about that.I have settled with OAuth or OAuth2 it doesn't matter(as far as I have read OAuth seems to be the better choice, but in the Microsoft tutorials they use OAuth 2, so here i am quite confused), and yes i know that they are completely different, but I am so frustrated of searching that I would accept either (I must admit that I expceted this to be much easier). As I said, I was searching for about a week, and all I got are concepts(a lot of them). You send some data -magic start - usually username/password to the server, your data is being processed and you get a token back - magic stop-. On SO there are a lot of questions on this topic but most of the answers are unprecise (and unfortunately unusuable). For example I got this one How to secure WEB API, nice answers, but not really use of them, or this one Implement Web API with OAuth and a Single Page Application. I also got the examples from the Microsoft tutorials but there is a lot of overhead in the code and the part about OAuth isn't quite clear(which is unfortunate because the whole example should be about OAuth). I could post tons of links which claim to talk about this topic, but actually they are of no help.
What I am looking for is an simple, very very simple, example of an ASP.NET OAuth(2) implementation. It would be great if I just could use it with fiddler, provide an username/password in the header and with use of grant_type: xxx I get the token back(the permitted username/password can be hard coded inside the project, so no need for Entity framework implementation or any database on the backend). And it would also be great if someone could explain me how to use this token to authorize the user (I got it that I have to provide the Controller functions with the [Authorize] attribute, but how and where is this token-check being done ?). But please, don't post any theory about OAuth, I don't need that, here I am looking for the actual implementation of OAuth inside of Asp.Net Web Api
thanks
Here is detailed post about adding the resource owner password credentials flow for your Web API project.
The most simple implementation of OAuth2 in Web API project you can find here:
WebApiOAuth2 on GitHub
There are just two important files:
Startup.cs (with settings)
AuthorizationServerProvider.cs (authorization of users using oauth2)

How to oconsume JWT's from identityServer in ASP.NET REST API

I have spent days trying to get up to speed on this but everything has changed since I last touched a web project and I'm utterly overwhelmed right now, and getting nowhere. I'm trying to put together the pieces for an implicit grant flow - just a simple web API that respects the tokens issued by my local instance of I.S.
I have been able to download and configure I.S. v2 locally. I've got it issuing authentication tokens in JWT format after sending the browser to the login page. I can see the token info come back as part of the redirect URL from IS, like 'access_token=...&token_type=urn:ietf:params:oauth:token-type:jwt&expires_in=599'.
So now I need to configure my asp.net API site to accept these tokens, and I can't figure out how. As I said, I haven't done web work in a while so Owin, WIF, and many more things involved here are brand new to me all at once.
What are the key steps I need to do have my API site accept these tokens? I guess I'm not sure what packages to include, what goes into the web.config related to the WIF aspect, do I need to write any code to make it work, or should there be some combination of config settings that just activate it? Do I need to create a custom ClaimsAuhtorizationManager?
Please, I'm bad shape here, I've been looking at this stuff for days and I still don't know enough to even figure out what else to try. Every sample I've found has had a significant different from my situation, rendering it unhelpful to me (most point to Azure or ADFS, or use the old classes which are now deprecated). It's not for a lack of effort, I've been reading everything I can get my hands on and scouring the web for days.
Thanks in advance for any help.
IdSrv issues standard JWT tokens - so there is nothing specific to it.
You can e.g. use the JWT handler from Microsoft. For Web API v2 the typical way would be to use the JWT middleware - here is a sample:
https://github.com/thinktecture/Thinktecture.AuthorizationServer/blob/master/samples/Flows/ResourceServer%20(Web%20API%20v2)/App_Start/AuthConfig.cs

Using sso for asp.net projects without external registration

I have two asp.net projects at the different domains. These projects use one database.
Let say www.test1.com and www.test2.com. (Late will be more projects)
I already have registration form and registered users.
Now I need to implement SSO possibility without registration at the external sites (google, openId, facebook).
All implementation which I have found required external registration (CAS, Federation, Facebook, openId).
Also I have read this article http://www.codeproject.com/KB/aspnet/CrossDomainSSOExample.aspx, but as far as I understood from comments such solution very insecure.
Please suggest solution or existed library which can help me to use SSO without external registration.
I needed the exact same solution for a client I was working for, I did the research and the only good solutions that I found where either too complex and not well documented or too expensive (I forgot which companies I looked into). So I decided to build a custom solution.
This is a short summary of the solution implemented:
In order to make things more clear let's call "nodes" the domains where you wanted to authenticate a user, and "SSO" the provider of the authentication.
I used a solution that is similar to the one in the link you posted HOWEVER I used the Asp.Net security cookie whenever I wanted to authenticate a node, and also to authenticate the SSO website:
HttpCookie formsCookie = FormsAuthentication.GetAuthCookie(userName, false, HttpRuntime.AppDomainAppVirtualPath);
HttpContext.Current.Response.Cookies.Add(formsCookie);
This also allowed me to not have to query back the SSO provider for each web request as the example you posted seem to do.
I used a new AuthenticationKey for each time I wanted to communicate from the SSO provider back to the node that the authentication was successfull.
Also I added some security features like encrypted communication and that the key could only be valid a max of 2 seconds (the time for the SSO to pass it to the node) and as soon as it was used it would be deleted.
I believe this solution is safe enough, however using an external ready made solution is surely safer.
It took me only a few days to implement the whole solution, so it's not too long of a task. However I cannot share the project as I am not sure the client would agree.
I hope those suggestions might help you.
Let us know what you decide to do in the end.

Resources