In our application, Organization/Employee Information has PII (Personally identifiable information) like Bank Account Info, Social Security number etc. This data is transmitted from the REST API response to the browser.
We have already following controls implemented
Data is transmitted over https
Authentication
Only Authorized users will be able to see full information
Data in the database is stored in an encrypted and masked format
APIs also have security controls. Only valid users will be able to execute REST APIs.
we wanted to add another layer of security i.e. data transmitted over https should be encoded.
In the Chrome browser, if the user presses F12 and opens dev tools, the user would be able to see REST API response JSON and data in a readable format.
So we wanted to ensure that PII data transmitted should not be in readable format instead it should be encoded format.
If we encode REST API JSON in Base64 and decode in JavaScript using Base64, then still hackers can hack data and decode using Base64.
Are there any other suggestions/recommendations about encoding/Hashing PII data so that data is NOT in the readable format while transmission? Any sample implementation would be helpful.
Related
Background:
I have an Azure Media Service setup with a video uploaded and encoded. To access this video I've created a Streaming Locator in Azure Portal. With this Locator I can stream the video.
Problem:
How do I make it so that only my website can stream that video? I don't want other website to take my Locator and use it in their players because that would mean I'm paying for their streaming traffic.
Is DRM the solution to this problem or do I need to create Locators on-demand when a user firsts clicks on a video and then delete it afterwards?
I've looked into API authentication but that requires a Client Secret which might be problematic on an Angular website. Orr user authentication which is odd to require just for browsing videos.
Thye typical workflow for this would be to use just Clear Key AES content protection and not try to use DRM which has a lot of issues in setting up and getting players to work correctly. Clear Key still has its player support issues on iOS for example, but it is the easiest way to pull off what you are trying to do.
The workflow would be to set up content protection for the asset and use AES Clear Key on the Streaming Locators. Your audience would have to login and authenticate on your web site, which would provide them with a JWT token to play back and decrypt the media.
I dont have a complete example, but this sample in the Javscript SDK shows how to enable clear key encryption and use a JWT token.
https://github.com/Azure-Samples/media-services-v3-node-tutorials/blob/main/Streaming/StreamFileWithAESClearKey/index.ts
Note that it does not cover where you get the JWT token from exactly - it is using a sample token really. You would have to set up a service (Azure function) that does the authentication of the user and provides them with a valid JWT token for playback. That's left up to you, as there are lots of security layers that have to be considered which would be too complicated for sample code.
To use AES Clear Key you follow these steps:
Create a ContentKeyPolicy with the claims you want to use in the token. That can be issuer, audience, etc. You set the primary verification key on this policy and the restriction type is set to token type of JWT
When you want to publish a video, you create a new Streaming Locator for it and set the "DefaultContentKeyPolicy" on the streaming locator to point the the name of the ContentKeyPolicy you created in step 1.
Then on the client side, when a customer logs into your site or selects a video - you can create the JWT token for that user and pass it into the player. This is demonstrated in the sample above.
There is also a .NET C# version of that same sample flow up here if you prefer:
https://github.com/Azure-Samples/media-services-v3-dotnet/tree/main/ContentProtection/BasicAESClearKey
My scenario with expected outcome:
User logs into a web portal.
The web portal presents content which is allowed to be accessed by the user.
The user selects a piece of content, which directs their browser to the m3u8 file for that content.
Each piece of content has an encryption key. The m3u8 file includes a URL for the key for that video, which is a REST endpoint with a query string (e.g. https://www.mymediaserver.com/api/key/100
The REST API will deliver the key in raw form to the requester if and only if a bearer token is provided along with the request. The key used to process the token is the same as the key used for the frontend API (e.g. that lists video content available). In other words, the same Authorization header that the user agent provides with API requests to populate the frontend can also be used for key retrieval. (This is not ideal, but it's a start and this project is more proof-of-concept at this stage.)
The video player would include the Authorization header with the request, and thus receive the key and be able to play the content.
Here are my questions:
The intended use case is simply to play the video within the browser. I could use a <video> tag, or even just redirect the browser to the file to begin playing the content full-screen on its own, and the user would use the Back button after playback.
I haven't yet started building all of this out because I'm not sure how the video playback engine actually requests the key. Is there a way to modify the HTTP request used to get the key, such that I can add the Authorization header?
Or, perhaps, does the video player automatically add the appropriate existing Authorization header?
Theories I've had:
I could dynamically generate the m3u8 file, adding the bearer token as a query string parameter. But, I'd then have to figure out how to get my REST endpoint to read the bearer token from the query string instead of from the headers. This would be an extra step.
I could generate my own one-time-use key retrieval strings and combine it with the above idea, but I then have to add the extra infrastructure to store the keys, expire them upon use, etc.
The summary question:
How do I implement bearer tokens when setting up a REST-style endpoint which will provide decryption keys for HLS video packages?
Notes:
The backend API is a C# ASP.NET Web API project.
The frontend for video selection is Angular.
I only plan to support iOS for now for this project.
I am aware that particularly crafty users may be able to figure out how to retrieve the keys. I'm trying to prevent casual downloading of video content from the server. (I fully realize you can't prevent copying, but you can prevent casual, easy copying.)
This is currently just a proof-of-concept idea for an internal video hosting platform that would make it at least challenging to retrieve video content for playback outside of the web site and without authentication.
For the last few months i've been working on a Rest API for a web app for the company I work for. The endpoints supply data such as transaction history, user data, and data for support tickets. However, I keep running into one issue that always seems to set me back to some extent.
The issue I seem to keep running into is how do I handle user authentication for the Rest API securely? All data is going to be sent over a SSL connection, but there's a part of me that's paranoid about potential security problems that could arise. As it currently stands when a client attempts to login the client must provide a username or email address, and a password to a login endpoint (E.G "/api/login"). Along with with this information, a browser fingerprint must be supplied through header of the request that's sending the login credentials. The API then validates whether or not the specified user exists, checks whether or not the password supplied is correct, and stores the fingerprint in a database model. To access any other endpoints in the API a valid token from logging in, and a valid browser fingerprint are required.
I've been using browser fingerprints as a means to prevent token-hijacking, and as a way make sure that the same device used to login is being used to make the requests. However, I have noticed a scenario where this practice backfires on me. The client-side library i'm using to generate browser fingerprints isn't always accurate. Sometimes the library spits out a different fingerprint entirely. Which causes some client requests to fail as the different fingerprint isn't recognized by the API as being valid. I would like to keep track of what devices are used to make requests to the API. Is there a more consistent way of doing so, while still protecting tokens from being hijacked?
When thinking of the previous question, there is another one that also comes to mind. How do I store auth tokens on client-side securely, or in a way that makes it difficult for someone to obtain the tokens through malicious means such as a xss-attack? I understand setting a strict Content-Security Policy on browser based clients can be effective in defending against xss-attacks. However, I still get paranoid about storing tokens as cookies or in local storage.
I understand oauth2 is usually a good solution to user authentication, and I have considered using it before to deal with this problem. Although, i'm writing the API using Flask, and i'm also using JSON Web tokens. As it currently stands, Flask's implementation of oauth2 has no way to use JWTs as access tokens when using oauth for authentication.
This is my first large-scale project where I have had to deal with this issue and i am not sure what to do. Any help, advice, or critiques are appreciated. I'm in need of the help right now.
Put an API Gateway in front of your API , your API Gateway is publicly ( i.e in the DMZ ) exposed while the actual API are internal.
You can look into Kong..
I noticed that a GET on a notification feed responds with a next attribute containing the API key. Not the secret, just the API key.
I'm curious whether this is safe to expose to an end user?
Example:
"next": "/api/v1.0/feed/notification/user8/?id_lt=8a4ba960-76fc-11e7-8080-800139637857&api_key=blahblahblahblah&limit=1&location=unspecified&offset=0"
The data payload you send to any of our API endpoints is encoded using your API secret into a JSON Web Token payload in the header for most calls. And guessing your very long API secret to properly encode anything would take an awfully long time, so yes we feel it's safe.
Also, you cannot log into the dashboard using your API credentials in any way so your billing information is safe (we still recommend turning on two-factor authentication in the dashboard though)
in my project, I am calling webservice with http get request.
API key is also there in http get parameter.
in j2me devices before connecting to the internet it is showing the URL and asking for permission to user.Here user can easily see my api key.
and i don't want to store api key in my application also.because using decompiler
anybody can get api key from applciation.
So my question is where to store api key and how to use it for calling web services?
If the API key is required to use the webservice, then you MUST store it somewhere in your app...By the way, you can store it in some kind of an encrypted way, so a simple decompile does not reveal it.
If the user should enter the API key, the you can store it in the standard RMS store outside of your app, again maybe encrypted.
An for the URL issue, use HTTP POST request instead of HTTP GET, and send the key in the post data.
You could encrypt the api key and store it as you do just now and then POST it to the web service.