Security for "Private" REST API - 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

Related

IdentityServer4 External Authentication without cookies

I'm having trouble understanding how ASP.NET Core authentication works.
I want to implement JWT access token authentication with refresh tokens. To my knowledge, this is the industry standard for authenticating a client (Mobile app, SPA Web application). For security purposes, I'd prefer to not implement my own authorization logic including JWT generation and refresh token handling. Since ASP.Net does not natively support this, Naturally my choice would be to use IdentityServer4, a large open source library for handling this kind of stuff.
However IdentityServer4 is heavily based on OAuth, and I'm not sure how that works with SPA applications and mobile apps (clients I trust). It requires the client to redirect to some arbitrary webpage to enter their credentials and then redirect back to the app. Gross. I've never seen a major app like Snapchat, Instagram, etc. have this kind of authentication flow where you are directed to some webpage/browser during the login flow. Luckily IdentityServer4 has a little feature to handle username/password authentication for my trusted clients (http://docs.identityserver.io/en/latest/quickstarts/2_resource_owner_passwords.html)
Great, that seems to suit my needs. But... Now I want to add Facebook Authentication. IdentityServer4 allows for External Authentication, however it is still cookie based (to my knowledge). Which requires the Android/iOS/SPA app to redirect to a webpage and then redirect back to the app. Again, this isn't ideal from a user perspective. Facebook provides native mobile SDKs to handle this type of authentication which returns an access token so there is no need to redirect to web pages using cookies.
Now lets say my iOS app uses the Facebook SDK to grab an access token for the user and sends it to the backend. The backend validates the token against the Facebook SDK, and subsequently registers a local user in it's own database.
Now when that same iOS user tries to login to the app, the app will generate a facebook access token for that user from the SDK and send it to the backend. However I'm not sure how to utilize IdentityServer4 to generate a JWT for the user since I need that users' username and password. This is where I'm stuck. I seem to be fighting against the library which makes me believe I am severely misunderstanding something.
TLDR; IdentityServer4 seems to be heavily based on cookies which doesn't really fit nicely into mobile apps/SPA webpages when you are redirected back and forth from authentication webpages. Am I using the wrong tool for the job? What are some alternative solutions?
As a note on big social apps: I think it comes down to who keeps the passwords. Facebook, Instagram, Snapchat, Google act as identity providers to third parties. They themselves require user to register and specify the password which they keep. Therefore they can use any customized approach for handling validation with those passwords. However, if any of them offerred a posibiltty to log-in with the other I.e Instagram were allowing to sign-in with Amazon credentials, then they would need to follow through a standard way like OAuth and redirect to the third party for log-in. Last time I checked Instagram, Facebook and Snapchat only offer to register and no option to sign in with 3rd parties which explains why the don't need redirects.
Now if we establish that a redirect is a necessary evil, then the means to carry over the data accross aren't that numerous. I.e. we either would need to pass data via a query string or use cookies. Am I missing any others?
Both have limitations but since cookies are persisted and browser carries them automatically with each request, they do seem like a better option for the job, especially if multiple redirects are required for an external IdP to track the state of authentication request. The same reason is mentioned here:
http://docs.identityserver.io/en/latest/topics/signin_external_providers.html
It's absolutely the right tool for the job if you want what OpenID Connect and OAuth2 give you. It sounds like you may need convincing though and it may be that your use case doesn't need the full breadth of functionality offered.
If you have multiple client applications and APIs in play then I think using OpenID Connect and IdentityServer4 the right choice at this point in time.
Regarding native apps, you used to word "gross" to describe using the user's default browser to perform the sign in process and it's understandable why you might think that at first but it's not as bad of a UX as you'd think and has plenty of advantages:
The client application is completely decoupled from how authentication is actually done be that federation, social sign in (Facebook in your case), multi-factor, retina scan etc. Your identity server deals with all that complexity and is a single point of management (and failure - so make it highly available!)
Single sign on is possible - if they're already signed into your IDP then they can go straight in (although you have full control of the flow - want them to consent or confirm the sign in request every time - you can do that)
If the user has a password manager set up in their browser then that'll work too
Both iOS and Android offer APIs for doing this stuff and the work well. If you skin your native and web UIs to look similar the flow from a user's PoV is not jarring at all.
You can still use refresh tokens (ultimately secured by the platform) so you don't actually have to do the interactive flow very often anyway.
Some additional reading below. Quite a lot of thinking has gone into this from the industry so it's definitely worth digesting the current best practice.
https://developers.googleblog.com/2016/08/modernizing-oauth-interactions-in-native-apps.html
IETF current best practice: https://www.rfc-editor.org/rfc/rfc8252
Don't make Scott hate you ;) : https://www.scottbrady91.com/OAuth/Why-the-Resource-Owner-Password-Credentials-Grant-Type-is-not-Authentication-nor-Suitable-for-Modern-Applications
For client side SPA browser apps OIDC provides the implicit grant type and uses a silent refresh and IDP session monitoring mechanism to maintain the session. Check out the oidc-client-js library which implements this approach.

Best practice for first-party auth in a native app

We have an auth infrastructure based on OAuth2 that is integrated into a variety of web apps within our organization. We also have a pure native application with no middle-ware of its own, and we want to integrate authentication into this native application. This application already has its own internal login mechanism with a native login screen, and we don't want to have it start launching external components like web browsers in order to display login windows. We are both the app provider and the auth provider, so the concern of the app having visibility into the user's credentials is less of an issue -- we trust ourselves to not intentionally do anything untoward with the user's credentials, and it's the same people writing a login form in the app as writing it on a web site. :-)
We are trying to figure out how best to support having the application continue to collect credentials the way it does now, but use them to obtain an auth token within our auth framework. With the APIs in place right now, the only way I can see for it to be done is to bake a Client Secret into the native app so that it can use a Resource Owner Password Credentials Grant request, since the code that would normally be making this call doesn't have a server side to live in. This feels really wrong, somehow. :-P
As far as I can see it, many of the structures of OAuth don't really apply to this app because it's not living in the context of a web browser, it doesn't have any concept of a "domain" nor any sort of "cross-domain" restrictions. It has been suggested that perhaps we create middleware for this app just for the purpose of exchanging authentication codes for tokens, but the rationale for that seems to be that this middleware theoretically ought to be able to somehow vet requests to determine whether they are legitimately from the application, and I don't see any way to do that that couldn't be faked by anyone with access to the client application code. Basically, the only purpose such middleware would serve would be to make the Client Secret irrelevant with respect to getting auth codes for credentials.
One thought that came to us was, how does something like Windows do it? Windows very obviously uses a native login form, but then some flow exists whereby the credentials that are entered are used for authentication and presumably, deep in the internals of the OS, for obtaining an auth token. Does anybody know if this architecture is documented anywhere? Does Microsoft's architectural choices here have any relation to OAuth2? What is the "best practice" for an application if you take it as a given that it doesn't have middleware and has its own native login form?
FWIW you don't need a client secret to use ROPC Grant to obtain or refresh tokens if the client is configured as a public client, i.e. a client that isn't capable of storing a secret.
RFC8252 OAuth 2.0 for Native Apps encourages using a native user agent for your scenario, using authorization code flows with PKCE. Authorization services like Okta and Auth0 have jumped onboard too, although they still recommend ROPC if the client is "absolutely trusted".
RFC6819 OAuth 2.0 Security discourages ROPC, but also says "Limit use of resource owner password credential grants to scenarios where the client application and the authorizing service are from the same organization", which are first-party apps.
So while the security verdict seems to be that authorization code+PKCE is the best practice, the UX hurdle of showing a user a browser window to log into a native app seem to be keeping ROPC alive. It's difficult to tell if that UX is jarring because people aren't used to it or because people can't get used to it.

API Authentication for multiple apps

I have been doing a lot of research into how to authenticate mobile apps with an API - I still feel a bit unsure about which flow & architecture would be better to use in my particular use case.
I think what's confusing me is some of the terminology used.
My use case:
An API & database on one server. Which holds the users & and the users resources.
A web app, which I have built and consumes the API. Hosted on the same server as the API. So it's dogfooding.
A web app, which I have built and consumes the API. Hosted on a different server to the API.
A mobile app, which I have built and consumes the API.
I'd like to be able to authenticate with the API using username & password.
The API will never be opened up for consumption by other 3rd party services except the web app and the mobile app.
Initially I felt like using the Resource Owner Password Credentials Grant flow would be sufficient. However in the docs it states that this flow should be used if "The client is absolutely trusted with the user credentials".
Since both my mobile & web apps will be built by me, I'm assuming they are seen as 1st party clients. Therefore am I right in thinking they are considered to be trusted with the user credentials? As I typically thought that when implementing oAuth, the idea would be to have the authentication server separate from the resource server. Which would allow you to have one authentication server for multiple APIs.
After reading this post: Why the Password Grant is not suitable for modern applications
It threw me off track a bit. But then, is this post talking about using this flow in my use case?
I was also looking at the Implicit Grant Tokens flow. However using this flow I couldn't really see how the user would enter their credentials first?
I also question if any of the oAuth flows is really needed for my use case and I should instead look at other ways of authenticating?
I'm really quite lost with this I would like some direction to go in with how to authenticate users in my particular case.
Thanks in advance!
I'll most likely be using Laravel to house my API and so I do have Passport available to me to implement oAuth
EDIT
From following this oauth article I've found that in all use cases of my app, I end at Password Credentials Grant flow. Would I be correct here?

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.

Does github (twitter, stripe & co) uses oauth for its own login?

Does github (twitter, stripe & co) uses OAuth for its own signin/signup forms?
All those authentications are cookie based, so is this regular web client basic auth or does it use some form of OAuth or xAuth ?
On login, a call to https://github.com/session (or https://twitter.com/sessions or https://dashboard.stripe.com/ajax/sessions) is made (with credentials given as formdata) that result in a 302 (or 200 for stripe) with Set-Cookie and a location to https://github.com (or https://twitter.com).
It does not seems that they use a client_id to get a code and exchange it with a token. All the OAuth dance seems striped. And the Bearer header too. So, what's going on here?
Thanks.
OAuth is a three-legged system, two-legs is sort of useless. The whole point of using OAuth is to give other services the ability to perform actions as you without needing to specifically authenticate or pass the data yourself. In the end you must still authenticate against some Auth service.
Since you are using these services as the Authentication mechanism for other sites, it wouldn't make sense to attempt to use it in your own. As part of setting OAuth, the second site redirects to the first and asked to authenticate there, which means you literally need to enter your credentials. Which means that if you are okay entering your credentials into say github, having a different authentication mechanism is useless.
OAuth allows non-github to create user accounts by trusting github with the authentication, or it allows non-github sites to make changes to github as the user once the user agrees to the interaction by logging into github to accept that policy (logging in using their credentials).
Sign in forms on github (and others websites as well) are simply cookie based.
Usually every direct login via the website through a browser is made with cookie based system , simply because isn't necessary to do otherwise.
A bit of theory
Every time you use a login form in a website you are calling an API, not necessarily intended for public use (so a private API)
When you put your credentials in the login form and push that login button , your credentials are being managed by some code in the server that permits you to authenticate against that website.
There is no need for the entire OAuth overhead here because the website has full control on the authentication mechanism and isn't necessary to externalize.
Why OAuth is different in this contest?
OAuth is a system designed to distribute the authentication system across different services / applications even from different vendors.
In OAuth there are multiple actors involved:
the client
the authorization server
the resource provider
In your case all these 3 actors are the website itself and so there is no need for a decoupling system like OAuth.