I have a cordova application which downloads a zip file as blob from azure. Since I am very new to azure, I would like to know that is it okay security wise to access azure blob with SAS url from the cordova application ?
My point is that I would need to append the shared access signature (SAS) token to the blob url, something like below.
https://myazureportal.container.blobs/myblob?MY_SAS
This way my javascript code will have SAS hard-coded. What is the correct approach since I would prefer to access blob using javascript only and preferably without writing any server side code if possible ?
if I use SAS inside javascript files of my cordova application, is it a security flaw ? If so, any approach to implement the same using purely javascript only ?
Things I tried:
Created a back-end WEB-API service in ASP.NET Core and this way, I would be able to download the blob file but I am looking for is a pure javascript approach.
Apart from the point mentioned by Eric about code being decompiled, there are a few other things you would need to worry about.
If you are embedding the SAS URL in your application, you will have to make them long-lived i.e. with an expiry date far out in future. That's a security risk and is against best practices.
A shared access signature is created using an account key and becomes invalid the moment you regenerate your account key. If you're embedding SAS URL in your application and have to regenerate your account key for any reason, your SAS URL becomes essentially useless.
You can learn more about the best practices for SAS Token here: https://learn.microsoft.com/en-us/azure/storage/common/storage-sas-overview#best-practices-when-using-sas.
Yes it is a security flaw as your app can be decompiled and your code inspected. If you want to keep this approach, at least have a login connected to a back-end that sends the SAS back to your front-end.
Ideally you would do everything in the back-end and return the blob to your front-end.
Related
I am brand new to a lot of Azure technology. I have familiarity with Graph API and JavaScript but have limited knowledge of C#.
Problem:
I need to write an Azure Function that queries an Azure App Registration that has the application permission 'Reports.ReadAll' and I need to do this in a secure method. This is to get data from Microsoft Graph Api. I want to do it in a way without writing the App Registrations Client Credentials in the code as that might be risky.
End Goal:
I am planning on collect the response from the App registration call and getting a url to a CSV file which I will Store somewhere (likely SharePoint). But this questions is about the first part, sending a request to the app registration securely and getting a response.
I have done quite a bit of research so far, and it seems I need to achieve my goal by writing a function in C# or JavaScript (preferably JavaScript, but any solution is welcome). To get the security I need some bits on the Internet say I need to Use Azure Key Vault so I am not store Client Credentials in plain text in the code?
I also need to get the bearer token first it seems according to my research, and I need to then include that in the call for the report's data I need, but I haven't been having much luck their either.
I know there are many similar questions on the internet but none of them could solve my doubt. So pardon me. About my project. I have a java file or program that takes a string , encrypts it and then returns the encrypted string to me.
I want to include or keep this java file (.jar file) on the webpage or the client-side. Now I know that we can upload this java program on server side and then easily communicate with it instead of calling keeping it on client-side which most people consider a bad practice.
But my purpose of keeping this jar file on the client side is that JavaScript code for encryption can be easily seen if we inspect element, so compared to it .jar file is more secure and one cannot see underlying encryption code and also if in case the there is network loss then instead of typing the entire string again and getting it encrypted again from the server, I want to save that string in such situation, get it encrypted from the jar file on the client-side so that once network problem is solved I don't need to retype whole message again and then I can directly send the message or the string to the other end or to other user on the network.
So for this I need help regarding how can I store my .jar file on webpage or client-side and then how to call methods from the .jar file using JavaScript. I know applets are deprecated, chrome does not support java. I have also seen some examples on internet like https://docs.oracle.com/javase/tutorial/deployment/applet/invokingAppletMethodsFromJavaScript.html but Its not working properly for me.
So I am in search of some ideal method by which I can first of all include or upload .jar file on client-side and then a method by which I can call java methods from .jar file using JavaScript. Please help... My earnest request...!
JavaScript code for encryption can be easily seen if we inspect element
I'm assuming you mean embedded Javascript here. Because you can refer to an external JS files which are located on the web server, not the client machine.
The browser may cache your script file somewhere locally but if one were bothered enough to dig it up, he might as well decompile your jar file which is much more easier.
Java can easily be decompiled. A jar file on the client will not be more secure than client-side JavaScript.
An encryption method that is compromised by looking at its code is not secure.
You seem to have many misconceptions... here are some facts for you to consider:
A JAR file (as either an application, WebStart or applet) running on client-side is NOT secure. If it runs on my computer, I can do anything I want. I can download the JAR file and decompile it. It's no better than JavaScript in this regard, it just takes slightly more effort and knowledge.
To protect data between client and server, you can simply use HTTPS and POST the data from web page to your server.
If client is encrypting data to you, there should be nothing to hide about the encryption process. The client generates a session key to encrypt the data, then wrap that session key by your server's public key. Then client send both encrypted data and wrapped session key to your server. Read more about Public Key Infrastructure (PKI): https://en.wikipedia.org/wiki/Public_key_infrastructure
By default a Java applet/WebStart is not granted access to disk. You must sign it to write data to disk, and user/security policies can still deny granting those access rights. (Applet - Unable to write file)
As you are aware of it, applet/WebStart is dying because of browsers rejecting plugins. There's Web Cryptography API (it's not mature, and there's no hardware support), you can try that instead. https://www.w3.org/TR/WebCryptoAPI/
I'm trying to make a program that can be hosted by many peoples, like an app.
The app use a REST API, so I must authenticate with Oauth,
and because anyone should be able to host the program, the redirect URI cannot be static.
Further, I don't want to use any server-side processing, which means only javascript for me.
Is it even possible to make a secure and working solution with non-static redirect URI,
and only using javascript, to work in a normal webbrowser?
So you use the information provided in the request to your app to indicate the URL for your app. For instance, if the request came to http://example.com/path/to/app and you knew in your app that /to/app was part of your routing infrastructure, then the path to your app is http://example.com/path/.
That is how I would determine it, using a serverside language.
Using a javascript library, which would be loaded from the server, I would either determine it like the above, or I would just hard code it on the generation of the javascript file (when you tell people where to download the javascript, it can use a form that requires their web address first).
I'm researching a possibility of using some cloud storage directly from client-side JavaScript. However, I ran into two problems:
Security - the architecture is usually build on per cloud client basis, so there is one API key (for example). This is problematic, since I need a security per my user. I can't give the same API key to all my users.
Cross-domain AJAX. There are HTTP headers that browsers can use to be able to do cross domain requests, but this means that I would have to be able to set them on the cloud-side. But, the only thing I need for this to work is to be able to add a custom HTTP response header: Access-Control-Allow-Origin: otherdomain.com.
My scenario involves a lots of simple queue messages from JS client and I thought I would use cloud to get rid of this traffic from my main hosting provider. Windows Azure has this Queue Service part, which seems quite near to what I need, except that I don't know if these problems can be solved.
Any thoughts? It seems to me that JavaScript clients for cloud services are unavoidable scenarios in the near future.
So, is there some cloud storage with REST API that offers management of clients' authentication and does not give the API key to them?
Windows Azure Blob Storage has the notion of a Shared Access Signature (SAS) which could be issued on the server-side and is essentially a special URL that a client could write to without having direct access to the storage account API key. This is the only mechanism in Windows Azure Storage that allows writing data without access to the storage account key.
A SAS can be expired (e.g., give user 10 minutes to use the SAS URL for an upload) and can be set up to allow for canceling access even after issue. Further, a SAS can be useful for time-limited read access (e.g., give user 1 day to watch this video).
If your JavaScript client is also running in a browser, you may indeed have cross-domain issues. I have two thoughts - neither tested! One thought is JSONP-style approach (though this will be limited to HTTP GET calls). The other (more promising) thought is to host the .js files in blob storage along with your data files so they are on same domain (hopefully making your web browser happy).
The "real" solution might be Cross-Origin Resource Sharing (CORS) support, but that is not available in Windows Azure Blob Storage, and still emerging (along with other HTML 5 goodness) in browsers.
Yes you can do this but you wouldn't want your azure key available on the client side for the javascript to be able to access the queue directly.
I would have the javascript talking to a web service which could check access rights for the user and allow/disallow the posting of a message to the queue.
So the javascript would only ever talk to the web services and leave the web services to handle talking to the queues.
Its a little too big a subject to post sample code but hopefully this is enough to get you started.
I think that the existing service providers do not allow you to query storage directly from the client. So in order to resolve the issues:
you can write a simple Server and expose REST apis which authenticate based on the APIKey passed on as a request param and get your specific data back to your client.
Have an embedded iframe and make the call to 2nd domain from the iframe. Get the returned JSON/XML on the parent frame and process the data.
Update:
Looks like Google already solves your problem. Check this out.
On https://developers.google.com/storage/docs/json_api/v1/libraries check the Google Cloud Storage JSON API client libraries section.
This can be done with Amazon S3, but not Azure at the moment I think. The reason for this is that S3 supports CORS.
http://aws.amazon.com/about-aws/whats-new/2012/08/31/amazon-s3-announces-cross-origin-resource-sharing-CORS-support/
but Azure does not (yet). Also, from your question it sounds like a queuing solution is what you want which suggests Amazon SQS, but SQS does not support CORS either.
If you need any complex queue semantics (like message expiry or long polling) then S3 is probably not the solution for you. However, if your queuing requirements are simple then S3 could be suitable.
You would have to have a web service called from the browser with the desired S3 object URL as a parameter. The role of the service is to authenticate and authorize the request, and if successful, generate and return a URL that gives temporary access to the S3 object using query string authentication.
http://docs.aws.amazon.com/AmazonS3/latest/dev/S3_QSAuth.html
A neat way might be have the service just redirect to the query string authentication URL.
For those wondering why this is a Good Thing, it means that you don't have to stream all the S3 object content through your compute tier. You just generate a query string authenticated URL (essentially just a signed string) which is a very cheap operation and then rely on the massive scalability provided by S3 for the actual upload/download.
Update: As of November this year, Azure now supports CORS on table, queue and blob storage
http://msdn.microsoft.com/en-us/library/windowsazure/dn535601.aspx
With Amazon S3 and Amazon IAM you can generate very fine grained API keys for users (not only clients!); however the full would be PITA to use from Javascript, even if possible.
However, with CORS headers and little server scripting, you can make uploads directly to the S3 from HTML5 forms; this works by generating an upload link on the server side; the link will have an embedded policy document on, that tells what the upload form is allowed to upload and with which kind of prefix ("directories"), content-type and so forth.
I want to collect data entered by the user in a browser and save to Amazon S3. Is this something I can do with Javascript/jQuery?
I know this is an old question, but I had the same issue and think I've found a solution. S3 has a REST interface to which you can POST data directly, without exposing your AWS Secret Key. So, you can construct an AJAX POST request to your S3 bucket endpoint using Javascript or jQuery. You can specify an access policy in the request as well, which restricts upload access to only certain buckets and certain directories.
Amazon verifies the authenticity of your requests using an HMAC signature which you provide in the request. The signature is constructed using details about the request and your AWS Secret Key, which only you and Amazon know, so fraudulent requests can't be made without someone having a valid signature.
Yes it is possible, and as I already pointed in the comments of the accepted answer there are legitimate and useful uses to do so without compromising security and credentials.
You can post objects to S3 directly from the browser:
http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectPOST.html
Bad idea:
1) Think of how much fun people could have with emptying your bank account when they find your S3 credentials embedded in your Javascript code.
2) The javascript would be loaded from your server and trying to talk to Amazon's servers - that's forbidden as it's cross-domain communication.
Something like this you'd want to handle on the server. You could easily whip up an AJAX interface to send the data client browser -> your server -> amazon. That way your S3 credentials are store on your server and not transmitted willy-nilly to everyone using your site.
Maybe have a look at node.js, and try the aws-sdk package by:
npm install aws-sdk
There are blog and doc I found about how to upload files to S3:
this blog. and
aws doc.
There are a variety of issues with attempting to access S3 via client-side code:
There is no way to secure your credentials.
Many responses are in XML instead of JSON, and the XML parsing engine in JavaScript is heavy and slow.
Authenticating the requests would require JavaScript implementations of HMAC-SHA1.
There are issues with making cross-domain requests from JavaScript without routing through a proxy.
All-in-all, there are no feasible solutions for client-side JavaScript at the moment. If you're interested in server-side JavaScript, there are some S3 classes floating around GitHub for Node.js.