Accessing Django server from AngularJs App: Easy authentication solution? - angularjs

I've been looking everywhere but can't seem to find an answer that has been helpful.
I have written an angular app that is trying to pull data from a django RESTful backend that was written by my company. I have a username and password, but I'm not sure how to write the get request to provide the authentication credentials to the backend. I'm also confused about what exactly I'm supposed to provide in the header.
Eventually, we will be communicating using nginx.
What I want
I'm looking for a fix to write in the angular app itself. I'm trying to write the angular app as separate as possible from the django backend. I have already enabled cross origin resource sharing.
This will be a band aid fix just to display data from the backend. It does not need to be permanent by any means.
So far I have tried:
app.factory('mySamples', ['$http', function($http) {
return $http.get('website/api/foo', {
headers: {'username':"foo", 'password': 'bar'}
}).success(function(data) {
return data;
}).error(function(err) {
return err;
});
};
app.factory('mySamples', ['$http', function($http) {
return $http({method: 'GET', url: 'website/api/samples/', headers: {
'user': 'foo', 'auth':'bar'}
});
};
The second factory I wrote returns METHOD: OPTIONS in the networks inspector under returned header. Does anybody have a quick fix just to get data from my api?
EDIT: My django backend doesn't support basic authentication, only session based. How would I edit my get request?

You first need to know what kind of Authentication and Authorization is implemented on the server side i.e. What headers the server looks for authentication/authorization credentials in and what format is expected by the server, then send the credentials under that header key. For example if the sever checks for Authentication credentials in the Authorization header in format username::password then you need to add the headers like
headers: {'Authorization': 'johndoe::password'}

(1) If you are using basic authentication, you can add a basic authentication like so:
app.factory('mySamples', ['$http', function($http) {
var credentials = btoa(username + ':' + authtoken);
var authorization = {
'Authorization': 'Basic ' + credentials
};
return $http({method: 'GET', url: 'website/api/samples/', headers: authorization });
};
If all of your $http calls use this same auth, you can use $http.defaults.headers.common.Authorization
(2) I’m pretty sure nginx does not provide session handling—you’ll have to do that in django.
(3) I don’t typically use sessions with REST since REST is usually done stateless.
OP asked how to enable CORS. Enabling CORS is usually done on the server-side. You can do it in nginx by adding:
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
To the appropriate location block. You can also do this on the django side with middleware pacakges like django-cors-middleware (https://pypi.python.org/pypi/django-cors-middleware) or django-cors-headers (https://pypi.python.org/pypi/django-cors-headers).

Related

Deny all but only allow access from Angularjs on the same server

I have a Lumen backend and an Angularjs project on the same server without a virtual host. The way I access APIs is simply by the URL like www.example.com/api/public/get_some_data. I want to hide these endpoints from the public but only allow access from the Angularjs.
I tried adding this to the .htaccess in the api/public folder,
Order deny, allow
Deny from all
Allow from 127.0.0.1
But Angular will be denied as well.
I access the endpoint from Angular like this,
function login(user) {
return $http({
method: 'POST',
url: 'api/public/login/user',
data: user,
headers: {'Content-Type': 'application/json'}
}).then(function(response){
console.log(response);
localStorage.setItem('token', response.data.token);
}).catch(dataServiceError);
}
Angular is client side framework. There is no difference for a server if a request comes from Angular application or anywhere else.
Access can be restricted based on some condition that can be satisfied by client side application, like request headers (example).
Security through obscurity is the weakest form of security and shouldn't be relied on. A proper solution in this case is basic authentication or token-based authentication.
Still, if an intruder has access to Angular application, he or she automatically gains access to API endpoints and can extract authentication information from the application.

Autodesk Forge OAuth using AngularJS: No 'Access-Control-Allow-Origin' header present

I'm running a test site built on AngularJS and am having issues trying to getting Forge OAuth going. Here's the request I'm trying to make...
$http({
method: 'POST',
url: 'https://developer.api.autodesk.com/authentication/v1/authenticate',
data: 'client_id=' + token.clientId + '&client_secret=' + token.secret + '&grant_type:client_credentials&scope=data:read',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
withCredentials: false
}).then(function (r) {
authToken = r.access_token;
toastr.success('success');
}, function (e) {
toastr.error('fail');
});
It's erroring out with:
XMLHttpRequest cannot load https://developer.api.autodesk.com/authentication/v1/authenticate. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 500.
I know this is a CORS related issue, which I'm not an expert about. Is this not possible using $http.post()? If not, how should I go about authenticating using Angular?
I assume you call your $http from the angular client side. Whether the call is successful or not, I need to mention here that it is a bad idea to share your client id and secret in your code. Anyone can read javascript code and stole your keys - once they do that, they can use them to request an access token and use your account to process files - and you'll pay the bill. This is valid for any WEB services - free or paid - such as Twitter, google maps, etc... Never, ever, compromise your keys on the client side. Use an endpoint on your server instead.
Now, I believe there is an error your data string formatting:
data: 'client_id=' + token.clientId + '&client_secret=' + token.secret + '&grant_type:client_credentials&scope=data:read',
should probably be
data: 'client_id=' + token.clientId + '&client_secret=' + token.secret + '&grant_type=client_credentials&scope=data:read',
grant_type: => grant_type=
For the CORS issue, this is because you are calling the http request for this endpoint from the browser. Watch for the Origin header sent by your browser, you'll see that it is something specific. Once you'll get the Authorization header, the CORS issue will go away.
Hope that helps,

How to secure my authentication headers on Angularjs when accessing REST API

I have this angularjs code below to access an API in json format with OAuth2's token. But I noticed writing in this way the access token can be seen and captured by everyone. I wonder how to hide or secure this so that no one can get the token easily by just checking the source.
<script>
var app = angular.module('myApp', []);
app.controller('articleCtrl', function($scope, $http) {
$http({
url: "http://example.com/api/article",
method: "GET",
headers: {
"Authorization": "Bearer bVM1HTeZ5R0HETGSTdjeg",
},
}).success(function(response) {
$scope.items = response;
});
});
</script>
You should use a HTTPS/SSL protocol to stablish communication with your REST API
You'll need to communicate with the API on the serverside and send the results to the client. There is no other way. People will be able to view your sourcecode, it's sent to the client so it can be executed. At that point it's in the hands of your client and they have your key. You could obfuscate your sourcecode but if somebody wants to, it's easy to undo. Just do API calls on your serverside through PHP/Node or whatever you are running and send the results to your client. The client isn't able to read your serverside code so your key will be safe. So instead of: API <> Client you'll need to do API <> server <> client

Salesforce and Angular with separate servers

I have two sets of servers:
apache serving up html/js/css pages in the angular flavor
SalesForce backend rest apis serving up Json
Salesforce has OAuth authentication, but it is not letting the javscript even perform an OPTIONS call in order to figure out if it can do the POST call it really wants to:
Is there any way to get around this without a proxy or jsonp?
is the Salesforce APEX Rest API configured wrong? the source domain is already whitelisted...
Update:
so some angular code to make the call:
var config = {
method: 'POST',
url: SalesforceRestApi,
headers: {
Authorization: "OAuth "+authToken,
"Content-Type": "application/pdf"
},
data : caseRequest,
};
var http = angular.element(document.body).injector().get('$http');
http(config).then(function(response){ console.log(response); });
this code here returns the good old Chrome error:
XMLHttpRequest cannot load https://xxx.salesforce.com/services/apexrest/xxx/v1/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://sample.com' is therefore not allowed access. The response had HTTP status code 401.

Not able to get response from API through angular?

My code is as below
$scope.LoadSearchResults = function () {
$scope.hotels = '';
$scope.allData = '';
var mydata = '';
$http({
url: 'myurl',
Authorization : 'code',
method: 'POST',
header: { 'Content-type': 'text/json' }
})
.success(function (mydata) {
$scope.hotels = JSON.parse(JSON.stringify(mydata.SearchResponse.Hotels.Hotel));
$scope.allData = JSON.parse(JSON.stringify(mydata.SearchResponse.Hotels.Hotel));
$scope.AllLocality($scope.allData);
})
.error(function (mydata) {
$scope.hotels = "Failed";
console.log(JSON.stringify(mydata));
});
}
and getting error is
"Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://example.com/some-page. (Reason: CORS header 'Access-Control-Allow-Origin' missing)."
How could I solve this problem?
this is not an Angular problem.
the reason is you are firing a cross origin request (e.g. your app sits on a domain and the request specified by url: 'myurl' is for a different domain) and HTTP does not allow it unless permissions are specifically added by the server receiving the request by adding a CORS header to the response.
to solve your problem you please check here one of the 4 options (I am sure you can find more depending on your specific setup):
make your app fire the request to the same domain, which is normally the preferred and most secure approach (e.g. the web app hosting the angular code is also responsible of responding to the xhr you are doing via $http)
if you have control on how the server creates the response, it should be fairly easy to add such headers (I cannot add an example here as it is entirely dependent on the web server or application gateway you are using)
if you don't have control over the server response (and most importantly its headers) you can add your own server in the middle that would act as a request proxy, thus making your JS app firing the request to your server (not incurring CORS problems) and the server itself making the proxy request to the 3rd party provider
if you just need GET requests (which doesn't seem the case from your snippet) you can use angular's $http JSONP if the server supports this type of requests.
Hi I have got it same issue but now i have resolved it by using below:
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Authorization");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
please pass header on controller after parent::__construct();

Resources