Is it safe to have visible Google Drive API keys in Javascript? - javascript

I am using Google drive API to download file from Google drive. I am using Javascript for that. Is it safe to have visible API keys in JS or I should use Node.js or something else? As you can see on the top of code, there are many keys (developer key, client id and app id). Is there any vulnerable in my code?
Here is my code:
var developerKey = '[key]';
var clientId = "[key]"
var appId = "[key]";
var scope = ['https://www.googleapis.com/auth/drive.file', 'https://www.googleapis.com/auth/drive'];
var pickerApiLoaded = false;
var driveLoaded = false;
var oauthToken;
// Use the Google API Loader script to load the google.picker script.
function loadPicker() {
gapi.load('auth', {'callback': onAuthApiLoad});
gapi.load('picker', {'callback': onPickerApiLoad});
gapi.load('client', function () {
gapi.client.load('drive', 'v2', function () {
driveLoaded = true;
});
});
}
function onAuthApiLoad() {
window.gapi.auth.authorize(
{
'client_id': clientId,
'scope': scope,
'immediate': false
},
handleAuthResult);
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
createPicker();
}
}
// Create and render a Picker object for searching images.
function createPicker() {
if (pickerApiLoaded && oauthToken) {
var view = new google.picker.View(google.picker.ViewId.DOCS);
view.setMimeTypes("application/sla,application/vnd.ms-pki.stl,application/x-navistyle");
var picker = new google.picker.PickerBuilder()
.enableFeature(google.picker.Feature.NAV_HIDDEN)
.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setAppId(appId)
.setOAuthToken(oauthToken)
.addView(view)
.addView(new google.picker.DocsUploadView())
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
downloadFile(fileId, data.docs[0].name);
}
}
function downloadFile(fileId, fileName)
{
var request = gapi.client.drive.files.get({
fileId:fileId,
alt:"media"
}).then(function(resp){
$.post("PHP/save_file.php", {Type: "stl", Filename: fileName, Data: resp.body}, function(response) {
if (response == "OK")
{
}
});
});
}
function showPickerDialog(){
loadPicker()
}

When you created your app on Google Developer console you created a web application. When you created it you added a javascript origin. As long as you set this javascript origin to the location of your webserver that the application is running on then there is no way anyone can use your client id. If you have left it set to localhost then yes there is a risk that someone could hijack your token and use it.
As for the api key you should lock that down to a specific domain, however api keys only give you access to read public data. The amount of public data in Google Drive but someone could abuse your api key if you dont lock it down.

Related

Cannot read property 'init' of undefined gapi.client

I am trying to integrate Google Calendar API with Js inside an application. I tried to follow Google Quickstart. If I paste the example code in an HTML doc, change the clientID and the API key, I get the error attached when I open the file in Chrome.
Also, with console.log(gapi.client) I get back null.
The first block of code is where gapi functions are called (calendar_model.js).
The second block is where I link the api script to the document (I need to do that by js, in a file called dependency.js).
The third block is my index.js, from where I call the function in dependency.js.
console.log("first");
// Client ID and API key from the Developer Console
var CLIENT_ID = 'xxxxxxxxxxxxxxxxx.apps.googleusercontent.com';
var API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx';
// Array of API discovery doc URLs for APIs used by the quickstart
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest"];
// Authorization scopes required by the API; multiple scopes can be
// included, separated by spaces.
var SCOPES = "https://www.googleapis.com/auth/calendar.readonly";
var authorizeButton;
var signoutButton;
/**
* On load, called to load the auth2 library and API client library.
*/
function handleClientLoad() {
console.log("gapi type: " + typeof gapi + '\n');
console.log("gapi client type: " + typeof gapi.client + '\n');
gapi.load('client:auth2', initClient);
}
/**
* Initializes the API client library and sets up sign-in state
* listeners.
*/
function initClient()
{
console.log("initClient callback start");
gapi.client.init({
apiKey: API_KEY,
clientId: CLIENT_ID,
discoveryDocs: DISCOVERY_DOCS,
scope: SCOPES
}).then(function () {
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
console.log(gapi);
// Handle the initial sign-in state.
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
signoutButton.onclick = handleSignoutClick;
}, function(error) {
appendPre(JSON.stringify(error, null, 2));
});
}
window.testMicroAppDependency = {
calendarInit: function(){
var calendar_root = document.getElementById("gcalendar-root");
//create authorize button
var x = document.createElement("button");
x.setAttribute("id", "authorize_button");
//x.style = "display: none";
calendar_root.appendChild(x);
//create signout button
x = document.createElement("button");
x.setAttribute("id", "signout_button");
//x.style = "display: none";
calendar_root.appendChild(x);
authorizeButton = document.getElementById('authorize_button');
signoutButton = document.getElementById('signout_button');
x = document.createElement("script");
x.src = "https://apis.google.com/js/api.js";
x.async = true;
x.defer = true;
x.setAttribute("onload", "handleClientLoad()");
x.setAttribute("onreadystatechange", "if (this.readyState === 'complete') this.onload()");
calendar_root.appendChild(x);
}
}
registry.add("microapp", "googlecalendar", {
init: function (parentNode, options) {
this._waitForDependency(function (error, dependency) {
if (error) {
console.error("Unable to start Google Calendar MicroApp: " + error);
} else {
var content = document.createElement("div");
content.setAttribute("id", "gcalendar-root");
parentNode.appendChild(content);
dependency.calendarInit();
}
});
},
_waitForDependency: function(callback) {
var timeout = 5000;
var startTime = new Date().getTime();
var interval = setInterval(function() {
if (window.hasOwnProperty("testMicroAppDependency")) {
clearInterval(interval);
callback(null, window.testMicroAppDependency);
}
if (new Date().getTime() - startTime > timeout) {
clearInterval(interval);
callback("Loading of HelloWorld MicroApp scripts timed out.", null);
}
console.log("... (waiting for testMicroAppDependency)");
}, 100);
}
});
Here is the console where I log the type of gapi and of gapi.client. gapi is an object, so the library is loaded, but gapi.client is undefined.
I am pretty a newbie in web dev, maybe it's a silly issue or I didn't comprehend something about Google API, but I can't get resolve it.
Any help is appreciated :)
The main issue you are having is you are calling initClient function as an explicit function here:
gapi.load('client:auth2', initClient())
you have to pass it as an implicit function because gapi.load will use it as a callback (I recommend you to check more about them). Therefore, it must be passed like this:
gapi.load('client:auth2', initClient)
Notice the subtle, but really important difference between the parenthesis in initClient() and initClient.
Also, you have these variables in the air without assigning them values for what I could see:
var authorizeButton;
var signoutButton;
They should be assigned the button elements to eventually handle them in your code:
var authorizeButton = document.getElementById('authorize_button');
var signoutButton = document.getElementById('signout_button');

Why does "WebRTC Screen sharing" is not streaming when using different computers?

I am developing a web application, like an online classroom in which I want to share the screen of a browser from a computer and view it in another. I am getting an error "Uncaught (in promise) DOMException: Error" in chrome when I tried to share the screen from a computer and view it on another computer.
I am using WebRTC for this and WebSocket for signaling. At the backend, java jersey would be doing the searching & forwarding of the request to the appropriate clients. I can share the screen from one browser window and view it in another on the same machine. But when I'm using different computers I get this error. When I debug the RTCPeerConnection object, it shows that the property connectionState as failed and iceConnectionState as disconnected.
Javascript: Request to share the screen
var urlS = [];
var config = {iceServers: urlS};
var $source = $('#monitor-src');
$scope.context.peerConnection = new RTCPeerConnection();
$scope.context.peerConnection.onicecandidate = function(event)
{
console.log(event)
if (event.candidate)
{
var json =
{
type:event.type,
label:event.candidate.sdpMLineIndex,
id:event.candidate.sdpMid,
candidate:event.candidate
}
WebSocket.send({desc:json,usrId:$scope.context.me.id},$scope)
}
else
{
console.error("Failed to create ice candidate")
}
};
try
{
$scope.context.peerConnection.createOffer({offerToReceiveAudio: true,offerToReceiveVideo: true}).then(function(offer)
{
return $scope.context.peerConnection.setLocalDescription(offer);
}).then(function()
{
WebSocket.send({desc:$scope.context.peerConnection.localDescription,callee:mentee.id,caller:$scope.context.me.id,usrId:$scope.context.me.id},$scope)
});
}
catch(error)
{
console.error("onnegotiationneeded-"+error)
}
$scope.context.peerConnection.onnegotiationneeded = function()
{
console.error("onnegotiationneeded")
};
try
{
console.log($scope.context.peerConnection);
$scope.context.peerConnection.ontrack = function(event)
{
console.log("ontrack:"+event.streams.length)
$source.parent()[0].srcObject= event.streams[0];
};
$scope.context.peerConnection.onaddstream = function(event)
{
console.log("onaddstream:"+event.stream)
$source.parent()[0].srcObject = event.stream;
};
}
catch(error)
{
console.error(error)
}
Javascript:WebSocket Handling of the request and sending response
$rootScope.socket.onMessage(function(message)
{
data = angular.fromJson(message.data);
if(data.type == 'offer')
{
var stream = null;
//var urlS = [{urls: 'stun:192.168.1.16:8443'}];
var urlS = [];
var config = {iceServers: urlS};
scope.context.peerConnection = new RTCPeerConnection();
scope.context.peerConnection.setRemoteDescription(data).then(function(){
return navigator.mediaDevices.getDisplayMedia({video:true,audio: true});
}).then(function(stream){
console.log(scope.context.peerConnection)
scope.context.peerConnection.addStream(stream);
stream.getTracks().forEach(function(track)
{
//var rtpSender =
});
scope.context.peerConnection.createAnswer().then(function(answer){
return scope.context.peerConnection.setLocalDescription(answer)
}).then(function()
{
send({desc:scope.context.peerConnection.localDescription,usrId:scope.context.me.id},scope)
}).catch(function(error){
console.error(error)});
})
}
else if(data.type == 'answer')
{
scope.context.peerConnection.setRemoteDescription(data);
}
else if(data.type == 'icecandidate')
{
console.log("icecandidate:"+angular.toJson(data))
var promise = scope.context.peerConnection.addIceCandidate(data.candidate).then(function success(){
console.log("ice success")
}).catch(function error(err)
{
console.log(err);
});
}
});
};
The ontrack and onaddstream events are triggered when a stream is added to the peer connection. But I get nothing on the requested peer.
I am not a JavaScript expert but your urlS array seems to be empty. Try to add both Turn and Stun servers in your urlS.
For more info take a look here

forge autodesk viewer api , onDocumentLoadFailure() - errorCode:4

i want to use the autodesk's viewer in my application so i used the forge ph client sdk,i made the 5 steps that are herehttps://forge.autodesk.com/blog/basic-usage-forge-sdk-php everything worked good.
but now, i want to view files in the viewer but it doesn't work i have thies error in my browser's concole :onDocumentLoadFailure() - errorCode:4
function viewObject(access,urn,divId){
var viewer;
var viewerDivId;
var options = {
env: 'AutodeskProduction',
accessToken: access
};
function onDocumentLoadSuccess(doc) {
// A document contains references to 3D and 2D viewables.
var viewables = Autodesk.Viewing.Document.getSubItemsWithProperties(doc.getRootItem(), {'type':'geometry'}, true);
if (viewables.length === 0) {
console.error('Document contains no viewables.');
return;
}
// Choose any of the avialble viewables
var initialViewable = viewables[0];
var svfUrl = doc.getViewablePath(initialViewable);
var modelOptions = {
sharedPropertyDbPath: doc.getPropertyDbPath()
};
var viewerDiv = document.getElementById('viewerDivId');
viewer = new Autodesk.Viewing.Private.GuiViewer3D(viewerDiv);
viewer.start(svfUrl, modelOptions, onLoadModelSuccess, onLoadModelError);
}
function onDocumentLoadFailure(viewerErrorCode) {
console.error('onDocumentLoadFailure() - errorCode:' + viewerErrorCode);
}
function onLoadModelSuccess(model) {
console.log('onLoadModelSuccess()!');
console.log('Validate model loaded: ' + (viewer.model === model));
console.log(model);
}
function onLoadModelError(viewerErrorCode) {
console.error('onLoadModelError() - errorCode:' + viewerErrorCode);
}
var documentId = 'urn:'+urn;
viewerDivId = divId;
Autodesk.Viewing.Initializer(options, function onInitialized(){
Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
});
}
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1 /jquery.min.js"></script>
<script>
function buttonViewClicked() {
var access = $('#token').val();
var urn = $('#urn').val();
viewObject(access, urn, "MonViewer");
}
</script>
Error code 4 refers to situations where the viewer gets 403 Access Denied when trying to download files from Forge. Make sure that the access token you're providing to the viewer is valid and that it has access to the model you're trying to view.
If you're still having issues, feel free to shoot us an email to forge (dot) help (at) autodesk (dot) com, and include as many details about your project, for example, how does the access token look like, the URN of your model, your Forge app ID, etc.

How to get Computer Name and IP address by Jquery or JS

How to get Computer Name and IP address by jquery or JS ?
I found this code snippet that actually worked for me
var RTCPeerConnection = /*window.RTCPeerConnection ||*/
window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
if (RTCPeerConnection) (function () {
var rtc = new RTCPeerConnection({ iceServers: [] });
if (1 || window.mozRTCPeerConnection) {
rtc.createDataChannel('', { reliable: false });
};
rtc.onicecandidate = function (evt) {
if (evt.candidate)
grepSDP("a=" + evt.candidate.candidate);
};
rtc.createOffer(function (offerDesc) {
grepSDP(offerDesc.sdp);
rtc.setLocalDescription(offerDesc);
}, function (e) { console.warn("offer failed", e);
});
var addrs = Object.create(null);
addrs["0.0.0.0"] = false;
function updateDisplay(newAddr) {
if (newAddr in addrs) return;
else addrs[newAddr] = true;
var displayAddrs = Object.keys(addrs).filter(function(k) {
return addrs[k];
});
document.getElementById('list').textContent =
displayAddrs.join(" or perhaps ") || "n/a";
}
function grepSDP(sdp) {
var hosts = [];
sdp.split('\r\n').forEach(function (line) {
if (~line.indexOf("a=candidate")) {
var parts = line.split(' '),
addr = parts[4],
type = parts[7];
if (type === 'host') updateDisplay(addr);
} else if (~line.indexOf("c=")) {
var parts = line.split(' '),
addr = parts[2];
updateDisplay(addr);
}
});
}
})(); else
{
document.getElementById('list').innerHTML = "<code>ifconfig| grep inet | grep -v inet6 | cut -d\" \" -f2 | tail -n1</code>";
document.getElementById('list').nextSibling.textContent = "In Chrome and Firefox your IP should display automatically, by the power of WebRTCskull.";
}
<div id="list"></div>
And unlike other codes which mostly returns server IP address it return client ip address of machine.Refer this article
https://www.c-sharpcorner.com/blogs/getting-client-ip-address-or-local-ip-address-in-javascript
To get Computer Name and IP Address using JavaScript,
-- ComputerName
var network = new ActiveXObject('WScript.Network');
// Show a pop up if it works
alert(network.computerName);
-- IP Address
$.getJSON("http://jsonip.com/?callback=?", function (data) {
console.log(data);
alert(data.ip);
});
for computer name
<script type="text/javascript">
var network = new ActiveXObject('WScript.Network');
alert(network.computerName);
</script>
You can get IP address by using simple ajax request as:-
let xhttp = new XMLHttpRequest();
xhttp.open("GET", "https://api.ipify.org/?format=json", true);
xhttp.send();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
let ip = JSON.parse(this.responseText).ip;
}
};
You can get an IP address by using a simple fetch request as:-
async function getIP(){
let req = await fetch("https://peerip.glitch.me/");
let data = await req.json();
let IP = data.ip;
return IP;
}
If you need these details client side,
you could use third party service like https://www.ipify.org/ and make API call to get the details like IP.
For other details, use similar service/services.
But if you are looking this details server side, then it depends what programming language you have used, though on server side this information readily available in HTTP Headers.
Refer similar questions for server side details.
How to get the exact client browser name and version in Spring MVC?
Browser, Operating System, Screen Colors, Screen Resolution, Flash version, and Java Support should all be detectable from JavaScript (and maybe a few more). However, computer name is not possible

how do I auto authenticate google javascript api ? REST api

I am using php. and want to use some javascript api function in my application. so can any one know that how can I auto authenticate this process:
<!--Add a button for the user to click to initiate auth sequence -->
<button id="authorize-button" style="visibility: hidden">Authorize</button>
<script type="text/javascript">
var clientId = '837050751313';
var apiKey = 'AIzaSyAdjHPT5Pb7Nu56WJ_nlrMGOAgUAtKjiPM';
var scopes = 'https://www.googleapis.com/auth/plus.me';
function handleClientLoad() {
// Step 2: Reference the API key
gapi.client.setApiKey(apiKey);
window.setTimeout(checkAuth,1);
}
function checkAuth() {
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult);
}
function handleAuthResult(authResult) {
var authorizeButton = document.getElementById('authorize-button');
if (authResult && !authResult.error) {
authorizeButton.style.visibility = 'hidden';
makeApiCall();
} else {
authorizeButton.style.visibility = '';
authorizeButton.onclick = handleAuthClick;
}
}
function handleAuthClick(event) {
// Step 3: get authorization to use private data
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: false}, handleAuthResult);
return false;
}
// Load the API and make an API call. Display the results on the screen.
function makeApiCall() {
// Step 4: Load the Google+ API
gapi.client.load('plus', 'v1').then(function() {
// Step 5: Assemble the API request
var request = gapi.client.plus.people.get({
'userId': 'me'
});
// Step 6: Execute the API request
request.then(function(resp) {
var heading = document.createElement('h4');
var image = document.createElement('img');
image.src = resp.result.image.url;
heading.appendChild(image);
heading.appendChild(document.createTextNode(resp.result.displayName));
document.getElementById('content').appendChild(heading);
}, function(reason) {
console.log('Error: ' + reason.result.error.message);
});
});
}
</script>
// Step 1: Load JavaScript client library
<script src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>
I have .json and also .p12 file for authenticate but I only want to direct access to api function instead of redirecting to google for permission access.
When using the Google+ API or other API that accesses user-specific data (e.g. Gmail, Calendar), you need to either use an OAuth client and ask the user for permission to access their data (i.e. the "redirect to google for permission access"), or use a service account.
A service account is a robot account that is used in place of a real user. If you decide to use a service account, you'll need to use the JSON or P12 key as you mentioned. Using a service account from JavaScript code requires a lot of work and is generally insecure since you would be making your service account key accessible to everyone. If you're going to use a service account, you should call the API from the server using a Google API Client Library.

Categories

Resources