Securing ASP.Net Web API with API Key - asp.net-mvc-4

I'm developing an ASP.Net MVC 4 Web API application where this application will be the source data for different Mobile/Web client apps. I need to authenticate a user so I can return the correct set of content for the user. I'm thinking about using an API Key that is sent to every request of my Web API application. The API Key identifies the user. I found this post that outlines a potential solution: From API Key to User with ASP.NET Web API
I need to support forms authentication as well as oAuth 2.0 for Facebook, Twitter, etc. All of these approaches yield a token I can use to send back and forth from the different clients to my Web API so I can identify the user. I understand Facebook access tokens expire. I'm a little confused on what's the best way to deal with Facebook interactions. Which of the following paths is the best way to go:
Rely on the different client apps to authenticate against Facebook (and other oAuth providers) to establish a Facebook access token that's then forwarded to my Web API application? This means all of the clients are responsible for making sure the Facebook access token is not expired. The Web API app assumes the access token is always valid. This seems dangerous to me. The different apps would authenticate the user then send user information to WebAPI app to register the user in order for the user to consume the data from my Web API app. This seems like a lot of duplication.
Make my Web API application solely responsible for interacting with Facebook (and other oAuth providers) on behalf of all the different client apps using my Web API. So this approach seems to suggest I need to build some sort of authenticating UI for my Web API app. I know ASP.Net MVC Web API can have views and front end stuff, but it always seems to me that you are mixing things together. It seems Web API apps should be singularly focused on returning data. Users from all of the different client apps will register with my Web Api app by either filling out a registration form, or using Facebook, Twitter, etc. Is it OK to mix UI views in with a pure REST Web API application? Then you have to start worrying about everything that goes with UIs on different devices, etc.
Is there another way I'm not seeing?
I really appreciate any guidance and links to examples you might have. Thanks for your time.

I would suggest you below approach:
1. Create an authentication API which will authenticate the user. If user is authenticated successfully, create a session (self implemented, may be a record in your db) for that user.
2. Next time user call your other APIs which returns content for that user. In this case it would be must for that user to provider the session id (which you have created in first step) to get the content. If sessionId provided by user does not exist at your end, it means the user is not authenticated. In this case you can return authentication error message to the user telling that he needs to get authenticated first. It is very flexible, scaleable solution in a way that you can store many information regarding that user session. Also once authenticated, user does not need to get authenticated every time he calls your other APIs to get content. It would save you as well from authenticating the user every time.

Related

Do I not need to secure my API endpoints (resources) with OAuth 2 access tokens?

There are multiple partied involved in OAuth2 conversation. Consider the
following diagram from the article here
Consider that I have an application that has data for restaurants and has APIs related to it. Let's call is restaurants APIs. Let us assign some role to each party in context of this example
User - our chefs, who have some recipes in restaurant
Application - Web client written in HTML5, JS, CSS that our Users use to interact with APIs
OAuth Endpoint - Google (who acts as Authorization Server)
API - My application API keeping all data for chefs
The workflow for Implicit (as per above diagram in the link) states the Application gets the access token and then the Application(browser) calls API (my application with chefs recipes) and gets the data back.
Questions
Shouldn't I secure my application endpoints or rather just believe the accesssTokens? Yes, the trust is established between Application and OAuth Endpoint (Google), but there is no trust developed API and Application by confirming the validity of accessToken with OAuth Endpoint (Google)?
If I should secure my application API endpoints, shall I have a /login endpoint for my APIs where my application accepts accessTokens, validate and create a JWT based headers for clients to use for further communication with protected resources like /recipes.
Looking forward to your ideas here.
Thanks in advance
TL;DR - don't blindly trust the access tokens. Ask Google to reveal the user/email associated with them and the client ID that was used when generating them. You can still provide a /login endpoint for scalability purposes mostly.
Let's deal with the core security first
OAuth is a delegation protocol, not an authentication protocol. To quote from the OAuth website:
The OAuth 2.0 specification defines a delegation protocol [...] OAuth is used in a wide variety of applications, including providing mechanisms for user authentication. [...] Let's say that again, to be clear:
OAuth 2.0 is not an authentication protocol.
Because it's not an authentication protocol, your app/API never learns who the user is. It just gets a token. Delegation in this context means that OAuth lets App A request access to resources in App B that belong to a User, by having the User authenticate to App B and then passing the token back to App A. In your example, it can provide your web app with access to Google resources (email, photos, etc. - depending on the required scopes) that are owned by the Users (chefs).
Note that this isn't what you are doing here, since you're accessing resources managed by your app, not by Google. In particular, as you correctly identified, the access token means nothing to your API. I could just as well give it a random string.
You might be tempted to use the following scheme:
Implement the implicit scheme as described in your question.
Have the API server validate the access token with Google, and ask Google for the name or email associated with the token. This will be the identity of the user who actually logged in to Google, and you can then decide whether or not to grant permission to that user.
The problem with this approach is that many apps use OAuth with Google, and so many apps will have Google access tokens that don't belong you app. How can you tell the difference?
You can ask Google, when you present it with the access token, to also provide you with the client ID that was provided when this token was generated (see how your diagram indicates that the client ID is sent?). Since that client ID uniquely identifies your app, then your API can tell that it's been given tokens that only came from your app. Note that this critical part of the OAuth flow is very different in mobile apps which is why the implicit flow should not be used with mobile apps (but it's fine with web apps).
Note that your client ID should be considered common knowledge (e.g. it's found in the .js files on the machines performing this flow), but it cannot be spoofed because as part of the OAuth flow, the user's browser will be redirected to a URL that is pre-configured in Google and belongs to your app. So even if a malicious app uses your client ID, Google will still send the token to your app.
Other practicalities
The above requires you to issue a call to Google on every API call, or at least cache the valid access tokens (which means you keep state, which is a bummer for scalability). If you want to avoid this, you can create a /login endpoint which generates a JWT. Note that you'll still need to validate the access tokens upon login.

What is the correct way to use OAuth for mobile and website consuming my own API?

I have a question more related to the way OAuth 2 is working but since using IdentityServer to implement OAuth I think it's relevant. I could not find an answer anywhere.
I'm building a website and a mobile app that consumes my own API. Each user of my app will have a username and password, that will give him access to the app/website and though the API to his information.
I'm not sure about the right way to handle the flow for user login:
On the website I have my own designed login form. I don't want to move the user to my auth server to login, and then have him approve the information he gives - he is the user on my system - I have access to all information - kida like facebook has a login and access to the informatio - they don't ask what you're willing to give them. So is implicit really the way for this?
On the mobile app I also have a login form and now I read here (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-native-apps-10) that the OAuth approach is to have the login in a WebView?? Doesn't look like facebook login is in a WebView on their mobile app.
The approach I was first lookin at is the Resource Owner. Users will login, get the token and the refresh token and can start working against my APIs. But storing my client_id and secret on the mobile app? on the website javascript files? doesn't feel right. I can of course make a call to an API that will mask those and be a proxy to the login process... but... (read #4).
In the future I would like to allow access for third-party developers. For them to allow login for users of my system I will use the implicit flow. Also, I plan for those developer accounts to have restricted API access (for example, the number of calls to the API will be limited by plan). What prevents those developers from asking for the username and password of their account on my system on their website, getting the response from my servers with the access token and refresh token, and using my API however they want, without restrictions, and having access to the entire user profile?
Lets say I'm sticking to the resource owner flow, receiving back from the server a token and a refresh token. What should I store on the mobile device and how? What should be stored in the browser and how? the refresh token? and each time he opens the app get a new updated token with that refresh token?
Edit
Just to clarify, because I find a lot of lectures and articles that explain the process from an API consumer point of view (ie. the third-party developer): I am the API owner and the auth server owner, I'm the owner of the user accounts (they are my users of my services), I'm also my own consumer (though the website and the mobile app), and in the future I want to enable third-party developers to allow my users to login with their accounts of my service (kinda like Facebook or Google)
You're correct that you shouldn't store the client_secret in your app, but I doubt you will get around storing the client_id. You could disable the consent screen for your app as well, and build a native login view. You need to store the access_token and the refresh_token on the device (maybe encrypted in a database) if you don't want the user to login everytime they use your app.
As for problem 4, you could do the following:
Embed the client_secret in your (web) app
Set up which hosts have access to your api on the IdentityServer
The IdentityServer generates a salt and sends it to the client
The client calculates a session_secret using hash(ip_address + session_salt)
The client uses the session_secret and the client_secret for the API call
Server validates the hash and client_secret
It's nearly impossible to completely prevent someone from using your API. But you should add various rate limiting methods, such as limiting IP addresses, API calls etc. But nothing will stop someone decompiling your app and accessing your client_id.

Security for "Private" REST API

I am currently developing a web application that is right now comprised of a front end which displays and interacts with the data using a REST API we have written. The only thing that will ever use the API is our front end website, and at some point a mobile app that we will develop.
I have done a lot of reading about how OAuth is the ideal mechanism for securing an API and at this point I am starting to have a good understanding of how it works.
My question is -- since I am never granting access to my API to a third-party client, is OAuth really necessary? Is there any reason it is advantageous? Furthermore, because the back end is simply the API, there is no gateway for a user to authenticate from (like if you were writing an app using the Twitter API, when a user authenticates they would be directed to the Twitter page to grant to access then redirected back to the client).
I am not really sure which direction to go in. It seems like there must be some approach halfway between http authentication and OAuth that would be appropriate for this situation but I'm just not getting it.
From my point of view, one of the scenarios that favor OAuth over other options is to work with untrusted clients, no matter if these are developed by you or a third party.
What's an untrusted client? Think from the point of who handles the credentials that grant access to your API.
For example, your web application could interact with your API in two falvors:
Your web app server side talks to your API. Your web app server is a trusted client because the credentials to access your API can only be access by whom have access to the server...You and your team. You could authenticate your web app server with a client_id and a client_secret.
You may want to make calls directly to your API from your Web app client, which runs on the end user's browser using JavaScript. The end user's browser is an untrusted client. If you were to deliver the credentials to your API down to the browser, anyone could check the JavaScript code and steal your credentials.
A third party Native App is also untrusted. A malicious developer that uses your API could save the credentials of and end user of your platform.
Your Native App is a trusted client and could manage the authentication with a simple username , password and a client id identifying your App.
How can OAuth help? OAuth Authorization code and Implicit grants can help you with this issue. These flows only work with clients that support a redirect, like a browser. And let you authenticate an untrusted client and a user against your Authorization Server to gain access to your Resource Server, your API, without exposing the credentials. Take a look at the RFC to see how it is done.
The good thing of OAuth is that it not only supports these redirect based authentication flows, but it also supports client credentials grant and user credentials grant. So an OAuth Authorization Server would cover all cases.
OAuth 2.0 originally seems like a PITA if you think about having to build a lot of it yourself, but most languages have some really solid OAuth 2.0 setups which you can just bolt in with varying amounts of fiddling. If you're using a framework like Laravel or RoR then it's barely any work.
PHP: http://oauth2.thephpleague.com/
Ruby (Rails or Grape): https://github.com/doorkeeper-gem/doorkeeper
If you don't want to redirect users as suggested in your post then ignore other comments and answers that talk about two legged flows. You can use the client_credentials grant type to have apps just provide their client id and secret in return for an access token, which is nice and easy.
I would ask how private are we talking, because if the only systems talking to it are within the backend and have no interaction with the outside world you could probably leave it wide open and just rely on the network to keep it safe (VPN/Firewall).
But if it's private in the sense of "our iPhone app uses it" then you definitely want to go with OAuth 2.0, or something like it.
2 legged OAuth is probably what you want to use. It's basically hashing a shared key, but you have the advantage of not having to write the code yourself.
Here's a related question: Two-legged OAuth - looking for information
You should use Oauth for mobile device to API layer communication.
However, there is no benefit of Oauth in this web UI layer to middle-layer access (machine to machine).
On the other hand there are some potential issues
Managing the access token expiry becomes a pain. Consider that your UI has to cache the access token across multiple nodes in a cluster. Refresh it when expired, and the fact that UI layer is negotiating security with backend will just take extra time once in a while.
In two legged Oauth (OAuth Client Credential as in v2.0) does not support any encryption. So you still need to send key and secret both to the server for getting an access token.
Backend has to implement issuing access token, refresh token, validating access token etc, without any significant benefit

How to authorize mobile apps with a third party by oauth BUT connect to my service, not the 3rd party

My app is architected as follows: I have a web service (running on GAE, not very relevant to this question) and the data that this service contains is made available through a website and through mobile and desktop apps.
Currently, the user authenticates to the website via Google ClientLogin and the apps authenticate/get authorized via GAE's built-in oauth provider. (OAuth is being used here mostly for authentication, my app doesn't actually use any external data via OAuth other than the user's unique ID and email address.)
What I'd like to do is expand the number of services that users can use to login. Because of the complicating factor of the apps, it seems I need OAuth. But I can't really properly conceptualize how this flow should go.
Lets take Facebook as an example. When a mobile app goes through the Facebook oauth flow and acquires an access token, this isn't enough - because its my service, not the app, that actually needs to talk to facebook to retrieve contact info and a unique user ID. This leads me to think that the OAuth process needs to happen in the context of my service, and not the mobile app. My service then becomes the consumer and Facebook the oauth providor, and the service holds on to the oauth access token, this happens when a user sets up their account for the first time.
If this is the correct approach, where does that leave authentication for the apps? What happens when the user already has an account and installs a fresh instance of a mobile app? I imagine also going through the oauth process, matching up credentials with the data already stored by my service, and then issuing my own "access token" to the app from the service, to authorize that instance of the app. This seems convoluted and hackish.
I'm sure I can't be the only person who is in effect "borrowing" the account system of a third party for a mobile app with a backend, but I really don't see what the proper way to do this is.
What am I not seeing and/or getting conceptually wrong?
A few colleagues and I once did a project quite similar in nature, back in university. We authenticated our users through either Facebook or Foursquare, using their respective OAuth APIs.
The native Android version of the app opened up a WebView with the OAuth provider's start page, which redirected back to our service after authentication. Then our service did a request for the OAuth token from the OAuth provider (Foursquare has some pretty simple instructions). When we got that token, we set up a session using cookies, which we could access from the app.
To validate sessions, we just checked whether the access token was still valid with the provider. We also used the respective providers' unique user IDs to distinguish users.
So yes, what worked for us is: Make the app authenticate & authorise your service, not the app itself.

how can I authenticate a user from a web app to an API?

It seems to be a widely asked questions and after having read tons of documentations on the subject, I'm still not sure to have understood everything correctly (I assume that being dumb is a possible answer ;)).
I'm trying to build an API that will provide a service to users. The users will be connected through Facebook or any OpenId provider (I separate Facebook since their implement their own connecting system).
(I think it's a good way because I will not store the user's password and finally will have less problem in case of a similar Gawker issue.)
When a request is made from the client (web app, mobile app, whatever) to the API, an indicator must be sent with the request in order to identify which user is using the app. This is generally used via a token, defined during the Authentication.
But regarding the Authentication, I can't find any valuable example, tutorial, explanations about how to implement it correctly.
I'll (try to) explain :
In my (wonderful world of happy care bears), I structured my project in various parts :
A RESTful API
A web apps that will use the api. Ideally, I was thinking about making a complete html/css/js project, without any server side work (php/python/java or whatever)
A mobile application
An windows/mac/linux application
As far as I saw, every time someone ask how to implement a RESTful API authentication, three major answers pops out :
The HTTP basic( + preferably SSL)/digest way
OAuth
OpenId
Since I will not store the user's password, the first one is out for me, but the two other leave me perplex.
But OAuth and OpenId are not the sames, one (OpenId) stand for the Authentication (that the base of the questions) where the second (OAuth) stand for the Authorization!
When Twitter implements OAuth for their API, they are not implementing an Authentication system, there are setting up a way to indicate their users that the application X want to have access to the user account (in various level of access). If the user is not currently logged in Twitter, he will first have to authenticate himself, and then authorize the current application to access his data.
So, just to clear things up, OAuth is NOT an authentication mechanism, it's a :
An open protocol to allow secure API
authorization
(source: http://oauth.net/)
Then, the only way to authenticate a user would be using OpenId. And then, the hell comes true.
If I take as an example a web application that is exclusively made of html/css/js, with no server side components, communicate with an API.
The web app must indicate to the API that the user currently using the API is mister X.
To do so, the web app show a popup containing a list of OpenId providers, asking the user to authenticate himself. The user click on one of them, get redirected (or a new popup open up) to the OpenId provider, indicate his login/pass, get authenticated by the OpenId provider, that return the success with a token (I simplified the communication).
That's great, the web app know now that the user is really mister X. But the API still have any clue !
Finally, my question is quite simple : how can I authenticate mister x through the web app to the API via OpenId and after that, how can the web app and the api keep the information that this is mister X that is currently using the web app and of course, the API.
Thank you very much for your help !
-edited format
You don't really want to login to the API using OpenID. As you said, OpenID is for Authentication, i.e. Who, while OAuth is for Authorization, i.e. am I allowed? But your structure suggest you'll be using an API as a backend and a web app as a front-end.
The best way then is to use OpenID on the web-app to authenticate the user, and then the web-app connects to the API and stores the OpenID credentials. The web-app then knows who the user is, and can provide the service. The API has nothing to do with the user, except that it stores its data.
The fundamental difference between OpenID and OAuth is its use. In your situation, you could have something like that:
-------- --------- -------
| User | <------> | App | <--------> | API |
-------- OpenID --------- (OAuth) -------
The User never interacts directly with the API: who would want to manually send HTTP request? (lol) Instead, the service is provided through the app, which can optionally be authorized using OAuth. However, in the case of a single app accessing the API, you can make the app <=> API connection internal and never expose it.
(If you don't want to read, the list bellow sum up the whole idea)
A possible solution (tell me if I'm wrong) would be to display the login form in the consumer (web apps, mobile apps, etc), the user click on it's provider (myopenid, google, etc) that opens a popup to do the login.
The tricky part is that the return_to parameter would be set to the API, not the website
The API will then resend the check_authentication and get the is_valid:true (or not).
During this step, the app would query the api to a specific url that return the state of the authentication (processing, failed, success). While it's procesing, an indicator is displayed to the user (loading gif), and if it's success/fail the result is displayed to the user.
If the api receive a is_valid:true, then it will ask informations about the user to the openid server, like email, firstname, lastname, and compare them with it's user's database. If there is a match, the api create a session between itself and the app, if the user is new, it create a new entry and then the session.
The session would be a unique token with a specific duration (maybe equal to the openid server assoc_handle duration ?)
It seems to be something possible, but I'm not an expert in security.
In order to explain things simplier, here is a little "map" :
Note: Provider is the OpenId server (that provide the informations about the authentication)
The User go the webapp and click on the login icon of his provider (Google for ex)
The webapp opens a popup containing the provider login page and access page, and specify a return_to to the Api
The provider sends informations to the Api
The Api validate these informations via the check_authentication
If not valid, the API indicate to the webapp (that ask the api every x seconds) the failure
If valid, the Api asks informations about the user to the provider, like email, display name, etc
If the user exists, a session is created
If the user is new, he's added to the database and the session is created
The Api returns the state of the auth (in this case, success) with a token session that will be used by the web app for further requests.