This is a design question for AngularJS websites that access a REST API. Since all the AngularJS code can be viewed from the client side (assuming obfuscation is not completely secure) how do you hide the API access credentials (the API key and password or even a JWT)?
This can be extended to a broader question about how other application logic can be hidden in an AngularJS website?
My research led me to some insights, one of which was
http://billpatrianakos.me/blog/2016/02/15/securing-api-keys-in-a-javascript-single-page-app/
But this has me more confused now, since the post suggests an SPA connecting to a REST API is not a good architecture. I thought it was and now can't figure what the right approach is.
The closest I can come to an answer is this resource:
https://developers.facebook.com/docs/facebook-login/security#appsecret
Facebook, is pretty good with their security and say:
Never include your App Secret in client-side or decompilable code.
Use unique short-term tokens on clients.
In short, do not keep API secrets on the client side
Answering the discussion in comments for sake of not being brief:
And then my question would be "what then is the correct architecture for SPAs and server side code (or database access)?".
There's no one correct architecture, it depends on the size and scope of your project. It will also depend on what frontend and backend frameworks you choose. Those choices also will depend on how many other APIs you are calling, or what other developers or you are most familiar with.
Speaking more specifically about security though, ideally you'd like to set up a session for the user which consists of a token that the user uses to identify himself. This is usually generated for each user by the server when they login. Generally this is provided by the framework you are working in, but even if it isn't, it's fairly simple to build. You will want to prevent cross origin requests (making sure the user is actually on YOUR frontend) and have secure connections (setting up SSL and https, though this can get complicated). You will generally want to run your JS code through something like Uglify to prevent it from being too easy to look through, but this does NOT guarantee that people cannot take that code and un-uglify it.
As the other answers have suggested, you should never keep API keys or any secrets in the client source code. There is no way to hide anything on the client, and obfuscation != security.
If you are looking to architect secure authentication/authorization into your app, you will want to return a JWT to the AngularJS application. You can then pass this JWT as a Bearer token to your API which will verify the validity of the token and allow the API to authorize access to the AngularJS application.
As for where to store the JWT token, you can store it in either Local Storage or in a cookie. There are serious considerations between choosing whether to store the token in either of these locations.
If security is your concern, I would look into the OAuth 2.0 Implicit Flow.
Don't put API keys in your client side source code. Keep them on your server, and have your client make a request to YOUR server, which then calls out to external APIs for data.
Related
I have a problem trying to figure it out for few days, still didn't get any rigid solution.
I have an angular app which will be publicly available so no login or credential is needed to open the website, and user can have an Id as query param. lets' say www.mysite.com/123
to retrieve data for 123, I have a backend, that needs authentication with clientId and clientSecret, to get access_token and then call the api with access_token to get information.
If I put clientId and clientSecret in the code a hacker can steal it and will be using it.
There were some suggestion to enable CORS on backend to make sure only requests from my site will be handled. which I already did, but with knowing the clientId and clientSecret even if CORS is enable a hacker can send requests from postaman by adding origin and referrer as header.
I tried Angular Universal for server side rendering hoping the api call will be run on serve side and will be hidden from user, but api call still happing in front end.
Really stuck in this problem any kind of help is appreciated.
Since the application is small and it's only hosting a web component developed by stencilJs, if other languages such as react or vue can support my scenario I can switch
You can go extensive ways of obfuscating statically inserted token in the frontend client build, yet it is still going to be there and the only thing it will add — extra steps for an attacker to reverse it, at least to my knowledge.
So to explore the solution to your problem, i guess you want to define it in the more narrow way, i.e what are you trying to protect:
resource requiring privilege (admin panel)
then your answer will be dynamic auth.
protect your api from external usage/ddos
CORS, ratelimiting, dynamic token issuing(take notice that strategy still will be available inside frontend client code)
also i think owasp guidelines will be a good read on the topic:
https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html
I think i should clarify that in my opinion the solution that you are going to implement in the end in the case of the "protection of the api" is going to be building fences to jump over, rather than sealing api completely from the 3rd party usage.
I'm a regular reader here at stack overflow but this is my first question.
I'm developing an authorization-server using the OAuth2 specs. And I just got stuck with how do I ensure the first-party client authenticity while using the password flow. I read many forums and this is what I got:
Javascript single-page clients
This blog post by Alex Bilbie, he states that to avoid the client_secret problem we should just:
It’s simple; proxy all of your API calls via a thin server side component. This component (let’s just call it a proxy from here on)
will authenticate ajax requests from the user’s session. The access
and refresh tokens can be stored in an encrypted form in a cookie
which only the proxy can decrypt. The application client credentials
will also be hardcoded into the proxy so they’re not publicly
accessible either.
But now this proxy can be accessed by someone impersonating my
angular app. And then I came across this blog post from Andy
Fielder: How Secure is the OAuth2 Resourc Owner Password Flow
for Single Page Apps. He basically says to rely on CORS to
avoid impersonating JS clients.
It is a good idea to use both approaches to secure my JS app?
Native Apps (Desktop and Mobile)
In the case of mobile apps, I only found cases for Authorization
Code and Implicit flows. This is not what I want, as the redirects
will compromise the user experience. So my thoughts on this is:
I will use the ROP flow and then register the client with a
client_id generated for this particular installation and attach it
to the user account, receiving the access_token and a
client_secret as response. Any other token request made by this
client MUST carry this credentials (as the client_id is specific
for the installation, I will be able to check if this client is
already authenticated). This way if someone uses any credential for
impersonating a client, or even registers a bogus client, I can take
mesures to revoke the user and client access.
I know that this can be overthinking, and I also know that some of this matters doesn't avoid anything. I just feel that is my job to protect my API as much as I can.
I would really appreciate your thoughts about this matters! Am I really overthinking? Should I just use the concept of a 'public client' and carry on?
Thank you all and happy coding!
First of all, this problem is not a common priority because most applications are developed first with website, and after with the API. This is probably the reason because no one knows how to deal first clients with oauth2, because everyone have developed other ways to do that and oauth2 is needed only to grant user access to third party applications.
Even if you have develop the oauth2 authorization server only for your first clients applications (thinking about a single authentication mechanism instead of developing many), you should try to develop the authorization code or implicit grant types. You will realize that you need a way to check what user is actually logged in.
The two common methods are:
user session (based on Cookies)
user access from localStorage (based javascript)
In either ways you need to check your application security, user session is vulnerable to CSRF, localStorage are vulnerable to XSS. There are a lot of articles about how to secure your website against either, so I will not suggest anything here, you just need to know that they exist.
Now that you choose your authentication method we can start to do some consideration about:
Javascript single pages applications
Proxy
Having a proxy that filter all requests in my opinion is like to have a door with the keys always inserted. It's useless even build the door.
However, for session based authentication it's the only way to do it. Allowing session authentication on your Rest API will open to CSRF security issues, so you need to have a proxy layer that get the user session, retrieve the access token from the session and do the request to the Rest API adding the Authorization header.
CORS
With this method you need to store the user access token in the localStorage, because the token is retrieved from the Js client directly.
Using CORS you are sure that other websites cannot do requests to your Rest API from a browser. But your first client need to be public (ie: it does not have a client_secret).
Native Apps (Desktop and Mobile)
In my first application I tried to use the same mechanism that you suggest to secure the auth flow. However that type of mechanism require that you identify every user client in an unique way. This is not possible in iOS for privacy reasons and with some probability it will denied in the future releases of Android. So you should rely on a public client and add only the client_id in your native application code.
This means that your native app client/your js client can be impersonalized? Yes, and there is no way to prevent this with oAuth2 resource owner password credentials grant type.
The main reason about this is because oAuth2 is not for authentication, only for third-party authorization, and that grant type was added only for specific third-party applications trusted enought to use directly the user password. You could read more about this argument here and here.
At the end
You still need a way to auhorize your user, and I think that the best you can achieve using oAuth2 is what Auth0 did.
Essentially this Saas manage your users with an oAuth2 server + OpenID connect, so you are always managing your users like its a third-party application and everything works fine.
Indeed, you can see on this page that for mobile applications they suggest to use a browser based login form, because the native one can be impersonalized by everyone that decompile your application, but if you wrap it into an authorization code flow it works fine.
I want to create an API at www.MyDomain.com that is accessible from public websites www.Customer1.com and www.Customer2.com. These public websites display each customers inventory and do not have any login features. They will use AJAX calls to read data from my API.
How can I secure the API so that it can be accessed via AJAX from different domains but no one can access the API to be able to scrape all of my customers data and all of their inventory?
I have tried thinking of different solutions on my own but they would all either require people to login to the public websites (which isn't an option) or it would require some secret "key" to be displayed publicly in the browser source code which could then be easily stolen.
Any ideas would be greatly appreciated.
Thanks!
P.S. Are their any obstacles that I am going to run into using Javascript & CORS that I need to look into now?
Anything that is accessible without authentication from a browser is by definition insecure, so you can't stop that. Your best bet is to have to have a relationship with the owner of customer1.com and customer2.com - the server apps for those two websites would make an HTTP call to you and authenticate with your service. Going this way also avoids the CORS issues you're talking about.
If you've already designed the client functionality, you can still probably do it without much change to the javascript - have it point to customer1.com for its AJAX call instead of your API, and customer1.com would accept this request and just act as a proxy to your API. Aside from the authentication, the rest of the request and response could just be pass-throughs to your API.
You can use Microsoft.AspNet.WebApi.Cors.
It's just need add ONE line at webapi config to use CORS in ASP.NET WEB API:
config.EnableCors("*","*","*");
View this for detail.
The simplest way to provide a minimum security here is to provide some kind of token system. Each app has its own token, or combination of tokens which it must pass to the server to be verified. How you generate this tokens is up to you and other than being linked to app's access, doesn't have to mean anything.
Provide a way for each API implementer to open an account with you. This way you will know who is accessing what and in some cases you can block/stop service.
For instance, a token can just be an MD5 hash:
7f138a09169b250e9dcb378140907378
In the database, this hash is linked to their account. On each request, they send this token with what they want. It is verified first to be valid, then the request is fore filled. If the token is invalid, then you can decide how to deal with it. Either don't return anything or return an "access denied" (or anything you want).
One thing to avoid is having a single token for everyone, though this can be a starting point. The reason for this is if some unauthorized app gets a hold of this token and exploits it, you have to change the token for everyone, not just the app that somehow leaked the token. You also can't control if someone has access to something or not.
Since you listed ASP.NET, I can also point you to WCF, which is fairly complex but has all the tools that you need to setup a comprehensive web service to service both you and your clients.
I hope this gives you a starting point!
EDIT:
There are security concerns here in the case that someone leaks their token key somehow. Make sure that you setup a way in which the app/your service do not expose the the token in anyway. Also have a flexible way of blocking a token, both by your clients in you, if it so happens that a token is exploited.
Looking at Twitter OAuth Libraries, I saw this note:
Be cautious when using JavaScript with OAuth. Don't expose your keys.
Then, looking at jsOAuth examples, I noticed that the keys are exposed in the code.
So my question is: How it is possible to not expose your keys when you use an OAuth library in Javascript?
Thanks.
UPDATE: Ok, maybe jsOAuth is not the right library to use, but how it is possible to do authentication with OAuth on a full Javascript web site?
As said in the documentation linked by you:
Written in JavaScript, jsOAuth aims to be a fully featured open source OAuth library for use in Adobe AIR, Appcelerator Titanium and PhoneGAP. In fact, anywhere that javascript can be used and has cross-domain XMLHttpRequests. For security reasons jsOAuth doesn't run in the browser. Browsers are only mentioned here for running the test suite. If you need jsOAuth in the browser, write an extension.
A good answer to your added question is available here:
Secure OAuth in Javascript
The only really reasonable way, right now, to do OAuth 1 in the browser, is to route API-calls via your server.
There simply is no way, as far as I have understood it, around this. If you do OAuth 1.0a calls through JavaScript from the browser -> You will HAVE to expose your consumer secret and access token secret, to at least the end user.
You cannot store these credentials in:
a cookie, the user can find them.
local storage, the user can find them (better than cookie though, since it does not entail sending a cookie back and forth all the time over HTTP)
in javascript, the user can find them (although this is probably your best bet since it is easier to obscure).
If it were only the access token secret that was exposed to the end user, that would be bearable - since it is in fact he/she who have authenticated your application. But losing your consumer secret is really not so hot, it means that your application is eligible for identity theft. I.e someone else could write an app that claims to be your app.
Even if you made it work securely in the browser, you are hampered by cross domain security blocks.
You could also make a script that sends all necessary values and parameters to the server to do the signing with.
The signed URL can then be sent back to the client (browser) that in turn does the actual request.
I have implemented OAuth 1.0a on the Twitter API that way using jsonp requests.
The benefit of this is that the response body is not relayed via your server, saving bandwidth.
That way you can have your cookie and eat it too.
Is there a norm for AJAX security?
When making an XMLHttpRequest, if querying an HTTPS url, will the browser handle all the certificate business and properly encrypt the request (or use an already existing authenticated tunnel)? Are there any security flaws in this model?
Then there's also user authentication issues with AJAX. This made me think that using the user's password to encrypt part or all of an AJAX request could solve some authentication issues. I've seen some impressive javascript based encryption tools. It seems like there'd be lots of potential there to build a single system that takes care of both encryption and authentication(host level and application user level). I have however not seen anything that seems 'tried an true'.
My question can be summed up as:
Is there a norm for secure AJAX either
using browser technologies or client
side javascript? What
is it? And if not, what's preventing
us from building one using javascript?
Thank you, as always.
SSL through HTTPS is sort of a cooperative venture with the destination server. The destination server will report its identity with its identity certificate (sent back to the client). This is part of the protocol that will encrypt the data stream between the client and the server.
However, this just encrypts the stream, it does nothing about several other security issues. Identification and authentication of the user entity making a request is handled through other means. If you're encrypting the stream with SSL, it should be safe to use HTTP basic auth. After that, the response to authentication should be a session id sent back to the client that will pass it back on all subsequent requests. Application servers typically manage the creation of those session ids.
Ajax does not inherently introduce new
security vulnerabilities in the realm
of web applications. Instead, the
applications face the same security
issues as classic web applications.
Unfortunately, common Ajax best
practices have not been developed,
which leaves plenty of room to get
things wrong.
from: http://www.securityfocus.com/infocus/1868
Basic authentication makes sense. I found this article explaining how to do it.
I somehow still have this desire to not use all the browser technologies and encrypt/authenticate things myself. Not sure if that would make any sense. Key caching would be hard to accomplish.
I'm still looking to find out if this (SSL + using basic auth in ajax calls) is the norm.