Hide API token from generated .cshtml page source code - javascript

I have a .cshtml page, where a click on a button calls an API
Currently, my JS code looks like :
var headers = {};
headers["Authorization-Token"] = '#Model.ApiToken';
$.ajax({
url: "my-url",
type: "GET",
headers: headers
});
However, if the end-user opens the browser console, goes to the Network tab, searches for the generated cshtml, he can see :
var headers = {}
headers[Authorization-Token] = 'my_token'
The token can be seen in clear text
I can't call my API without this header, as the call is immediately rejected if the header is not present.
Is there a way to hide it to the end-user, and if so, how ?
Thank you

It is better to keep the tokens outside the browser, one option is to store the token inside the cookie (encrypted of course). ASP.NET Core can handle that for you automatically. Or in the backend as part of the user session.
An perhaps better option is to look at using the Backend For Frontend (a.k.a BFF) pattern to secure SPA applications.
See
Backend For Frontend Authentication Pattern with Auth0 and ASP.NET Core
The BFF Pattern (Backend for Frontend): An Introduction
Securing SPAs using the BFF Pattern (once and for all)

Related

How to POST an issue stub on GitHub using the GitHub API using the logged in user, without authentification keys?

Users of my web application are expected to provide bug reports as a GitHub issue, with a pregenerated title and body.
This works perfectly fine using GET for small bodies:
const title = getLastErrorTitle();
const body = getAllTheLogMessages();
window.open(`https://github.com/theuser/therepo/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`);
If the user is logged in, GitHub presents the user with a new issue with the title and body already filled out, perfect. If not, GitHub prompts the user to log in and it works the next time.
However, if the body is too large, the GET request fails because the URL becomes too long.
After consulting the manual I tried doing the same with POST but I get a 404 from GitHub with the following test request (jQuery for brevity):
$.ajax({
type: "POST",
url: "https://api.github.com/repos/theuser/therepo/issues",
data: data = {title: "Test", body: "Test Body"},
});
My suspicion is, that the GitHub API was not designed with my use case in mind, but that POST always requires authentication and creates the full issue in one go, without letting the user change it beforehand like it is possible with GET.
How can I transfer the functionality of the GET method over to the POST method? I just want GitHub to present the user, that is currently logged in inside the browser, with a prefilled issue, without needing a token.
You can't. Otherwise, it would be a major CSRF exploit.
However, you can use OAuth authentication that will allow your application to use some features : https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/
Or simply, redirect the user to a new issue page (for exemple with a simple HTML link <a>) with some automatic content, using this pattern :
https://github.com/{theUser}/{theRepo}/issues/new?body={theContentYouWhant}&title={theTitleYouWhant}
Example : https://github.com/CristalTeam/php-api-wrapper/issues/new?body=Hi,%20this%20is%20the%20body%20you%20want&title=Hello,%20this%20is%20a%20prefill%20issue
What I would suggest here is to generate a personal_auth_token at gihub and pass this token in the headers under Authorization field.
To generate personal_auth_token, login to github.com, go to settings -> developers settings -> Personal access tokens and generate one.
Pass this token in headers under Auhtorization: token. So in your AJAX request, it could look something like this:
$.ajax({
url: *yourUrl*
...
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', *token*));
},
});
One thing to note here is each of the developers POSTing to the repo will be requiring to generate their access token and you can't push this token on to a public Github repository because of obvious security breach. If you accidentally do so, the token is revoked immediately and you'll be required to create a new one.

Restrict ajax calls from outside of node app

I want to restrict AJAX calls other than my application. I don't want my AJAX request to send response when called from outside my application, even when the url of AJAX call is copied and pasted in browser. I am using node, express and mongodb.
What I did was add some headers in my ajax calls:
// javascript
$.ajax({
type: 'POST',
dataType: 'json',
headers: {"Content-Type": "application/json", "app-ver": 1.5}
})
.
// php
$client_ver = floatval($_SERVER['HTTP_APP_VER']);
// I also check $_SERVER['CONTENT_TYPE'] to be: 'application/json'
// and post method. (ask me I'll add)
if ( $client_ver != 1.5 )
{
echo '{}';
exit();
}
Edit:
Another way would be creating a "session" with your app, meaning every request after a successful login has to carry a token (at least)
and have your app attach lots of unique header key-values that is only recognizable by your server, and not any two requests are a like (eg: include time in header, and hash it with REST command, and have server check it to make sure it's a unique command, and it's not just being manipulated.
* You have to know your session creation algorithm and it HAS to be unique, or if you don't know how to do it, I suggest research more about it.
If your application runs on a user's machine (like a JavaScript web app) then it is impossible to prevent someone from making the calls from outside of your app. You can make it harder by using a nonce with each request, but even then someone could build their own app that mimics your app and makes the calls in the correct order.
In short: you can't ever fully trust the client and you can't prevent someone from spoofing the client. You need to re-examine your requirements.

How to authenticate a POST request from a chrome extension to my app with JSON web tokens?

Context
My HapiJS web application is currently using OAuth 2.0 to access Google APIs. Once a user authenticates in the app, the server generates a JSON Web Token (JWT) which is stored on the client and sent back in the Authorization header of subsequent requests.
What I would like to accomplish
I now would like to use the same steps (authorization + creation of a JWT) with my Google Chrome extension which syncs data back to the app via a REST endpoint.
Current Thoughts
My idea is to use the same OAuth authorization as I have in my application to generate a JWT and then to save this JWT into the Chrome extension. This JWT will then be passed with each request from my chrome extension to my application to validate the request.
Unfortunately, it seems that the Chrome extension is using its own authorization through the Chrome Identity API and won’t let me use the authentication process I had in mind.
The diagram below describes the steps I’m envisioning to get the JWT created on my application then saved on my chrome extension (and also points to where the problem lies):
The Question
So my question is: Is there another or a better way to store a JWT created on my application to my Chrome extension?
Hope my explanation is clear enough
You can use your localStorage to save your jwt from the web app, then, if your extension runs on the same domain, you can access saved information from the localStorage through a content script, that gets injected in that page. You can communicate with your popup using the Message Passing API for Chrome extensions.
The problem with this approach comes with the fact that saving sensible information like user info (which is encoded in the jwt) is frowned upon due to security concerns.
Ideally, you should have a server which handles the authentication back and forth, saves the information and emits a session token for its clients, which then you can save in the localStorage if you wish.
If you want your popup.html to contain a link to allow users to open (leading to OAuth Google in your model), you need more work than a simple anchor link.
You will need to add event listeners to the link and use chrome.tabs.create.
Here is a demo code:
popup.html
<html>
<body>
<span class="link" data-href="https://www.google.com">link</span>
<span class="link" data-href="https://www.bing.com">link</span>
<span class="link" data-href="https://www.yahoo.com">link</span>
<script>
//get all links
var links = document.getElementsByClassName('link');
//loop through each link
for (var ii = 0, nn = links.length; ii < nn; ii++)
{
//add listener
links[ii].addEventListener('click', function(e)
{
//grab link
var url = this.getAttribute('data-href');
//open link in new tab using chrome.tabs.create method
chrome.tabs.create({url:url});
});
}
</script>
</body>
</html>
I think you could use localStorage (or a library that do the same but could work better for your code)
Without code, i can't do better for you bro, sorry
Did you try to use localStorage?
You can save the token like:
localStorage.setItem('token', 'abcde')
and can retrieve
localStorage.getItem('token')
but the information will be lost if reloads the page.

Synchronous $resource in AngularJS

I'm in a dead end, because I know that Javascript isn't made for synchronous work, and specially not AngularJS. However, I am in a situation where I am stuck needing it.
I have one main page on the domain "www" (with AngularJS), that calls "api" a lot. Some of the resources on "api" requires authentication, so it returns an 401, which in turn AngularJS picks up and displays a login-box when it sees.
The www-login supports a bunch of login methods and sends the password/oauth/whatever to the "api", which returns a token which the angular app stores in a cookie, and sets in $http.defaults.headers.common['Authorization'] so it can be used to authenticate furter requests to the api.
The same method is also used to get the username that belongs to the api-token.
This works perfectly and solves my design goals. But if the browser is going to an url that requires authentication, the 401 (and hence the login box pops-up). This is (I guess) because angular is not able to populate the Authorization field in the header before the 401 hits the browser..
Solutions?
Have an async=false request using jquery?
Close the login-box when we are done getting the data we want. The login box might flicker...
Store more meta-data about the login (ie, username) in cookies, so we dont haveto do get this information from the server when the app is loading.
??
Is there a better solution? This one time, for this one request, I want async=false in my Angular resource....
The solution I went for (which works perfectly) is to set $http.defaults.headers.common['Authorization'] = 'Token ' + old_api_token;, before the async request. And then overwrite it when the async request is done (if it have changed).

Instagram how to get access_token

I'm new to Instagram apps development and struggling with this issue for some time now. Basically, this is how it looks like:
I'm redirecting user to authorization url like this:
window.open("https://api.instagram.com/oauth/authorize/?client_id=" + igClientId + "&redirect_uri=" + igCallbackUrl + "&response_type=code", "_blank");
Then, when user will login, page reloads and Instagram CODE is added at the end of callback url ('?code=returned_by_instagram_code').
And this is the place where I've stuck.
How can I obtain returned code from url after page reloads (it is stored in cookies or session so I could access it in some way, or should I get it somehow through callback url and some function attached to it)?
How next, when I'll obtain the code, can I send (POST) request to Instagram for access_token?
Thank you in advance for any help.
PS. I'm using javascript without any frameworks (e.g. jquery) and this is the response that I'm looking for.
From the documentation on using Client-Side access token generation only (http://instagram.com/developer/authentication/) and the key thing you need to change is the responsecode in your URL to be: &response_type=token
Client-Side (Implicit) Authentication
If you’re building an app that does not have a server component (a purely javascript app, for instance), you’ll notice that it’s impossible to complete step three above to receive your access_token without also having to ship your client secret. You should never ship your client secret onto devices you don’t control. Then how do you get an access_token? Well the smart folks in charge of the OAuth 2.0 spec anticipated this problem and created the Implicit Authentication Flow.
Step One: Direct your user to our authorization URL
https://instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECTURI&response_type=token
At this point, we present the user with a login screen and then a confirmation screen where they approve your app’s access to their Instagram data. Note that unlike the explicit flow the response type here is “token”.
Step Two: Receive the access_token via the URL fragment
Once the user has authenticated and then authorized your application, we’ll redirect them to your redirect_uri with the access_token in the url fragment. It’ll look like so:
http://your-redirect-uri#access_token=270740070.f59def8.d58713f2c81741c5b3686109306f98b4
Simply grab the access_token off the URL fragment and you’re good to go. If the user chooses not to authorize your application, you’ll receive the same error response as in the explicit flow
A simple example, get your token in registration app on api.instagran (https://instagram.com/developer/clients/register/). Make your login before:
var accessToken = '5e6e329062f047dd95ggj6c9df202c828';
$.ajax({
url: 'https://api.instagram.com/v1/media/popular',
dataType: 'jsonp',
type: 'GET',
data: {client_id: accessToken},
success: function(data){
console.log(data);
for(x in data.data){
$('ul').append('<li><img src="'+data.data[x].images.low_resolution.url+'"></li>');
}
},
error: function(data){
console.log(data);
}
});
The igCallbackUrl will redirect to a page. The code can be accessed as a GET parameter to that request.
Something like GET['code'] in php. If you give more details about the Server side framework then it will be helpful to answer your qwery.
You can use github.com/Instagram/instagram-javascript-sdk if you are using on Javascript.

Categories