I'm trying to add firebase authentication to my google doc add on. My goal is to have a sidebar that displays data from my database after authentication. I get the most confused by other answers because I'm unsure about what goes in the html file verse what goes in the google app script file. I know I'm supposed to create a token but after I copy and paste that code from the tutorial I get lost.
Groups/Answers that were partly helpful:
https://groups.google.com/forum/#!topic/firebase-talk/-RKpHaMPTYQ
Google Authentication with Google Spread Sheet via App Script
https://sites.google.com/site/scriptsexamples/new-connectors-to-google-services/firebase/tutorials/using-secured-client-authentication-for-real-time-read-and-write-calls
app.html
<html lang="en">
<head>
<script src="https://www.gstatic.com/firebasejs/3.7.3/firebase.js"></script>
<script>
var config = {
apiKey: "",
authDomain: "",
databaseURL: "",
storageBucket: "",
messagingSenderId: ""
};
firebase.initializeApp(config);
</script>
</head>
<body>
<div id="databaseDiv"></div>
</body>
</html>
Code.gs
/**
* Creates a menu entry in the Google Docs UI when the document is opened.
* This method is only used by the regular add-on, and is never called by
* the mobile add-on version.
*
* #param {object} e The event parameter for a simple onOpen trigger. To
* determine which authorization mode (ScriptApp.AuthMode) the trigger is
* running in, inspect e.authMode.
*/
function onOpen(e) {
DocumentApp.getUi().createAddonMenu()
.addItem('Start', 'showSidebar')
.addToUi();
}
function onInstall(e) {
onOpen(e);
}
function showSidebar() {
var ui = HtmlService.createHtmlOutputFromFile('app')
.setTitle('Sow Google Docs');
DocumentApp.getUi().showSidebar(ui);
}
function makeToken(){
var firebaseUrl = "https://example.firebaseio.com/";
var secret = "EXAMPLEKEYYEKELPMAXE";
var base = FirebaseApp.getDatabaseByUrl(firebaseUrl, secret);
var token = base.createAuthToken(Session.getActiveUser().getEmail());
return token;
}
What am I missing?
Do not use any custom firebase library for apps script, use the Official Firebase Inline Javascript Libraries to achieve your objectives. If you run into problems ask your questions here (but do not be clueless), people will help.
Related
I am making a chrome extension with a custom popup that comes up after the page is loaded.
I would like to safe the submitted answers from the input-field to my firebase database, so that i cant include them in another website. It all works, but the problem is, that the answers from the extension get blocked:
Cross-Origin Read Blocking (CORB) blocked cross-origin response with MIME type text/plain. See for more details.
How can i solve this Problem?
Note: I am not a pro at this, so i'd really appreciate an easy to follow solution:)
these are my steps:
I downloaded the firebase.js and added it to my manifest.json:
"matches": ["<all_urls>"],
"js": [ "Libraries/firebase-app.js",
"Libraries/firebase-firestore.js",
"sketch.js"],
I injected the html to the webpage using the content-script:
<div id="bg-modal">
<div class="modal-content">
<button class="close">+</button>
<div class="text"></div>
<form class="antwortfeld antwortfeld1" action="">
<textarea type="text" name="antwort" placeholder="Antworten"></textarea>
<button class="Senden">Senden</button>
</form>
I added the firebase app configuration and initialized firebase in the content-script
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "...TRZeHhLQ9gMa4V4gy9WSlQ",
authDomain: "....firebaseapp.com",
databaseURL: "https://....firebaseio.com",
projectId: "....",
storageBucket: "....appspot.com",
messagingSenderId: "...0021",
appId: "1:385077100021:.....ba5a776b4bc"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const db = firebase.firestore();
then i added this to the content-script as well to save the inputdata to firebase:
const form1 = document.querySelector('.antwortfeld1');
// saving data
form1.addEventListener('submit', (e) => {
e.preventDefault();
db.collection('Antworten').add({
Antwort1: form1.antwort.value,
})
form1.antwort.value = ' ';
})
As I said, it's all working, but I get blocked. I guess I'll have to use a background-script to get around this? What would that look like?
Any other options?
I'm having some difficulty setting up push notifications with my Firebase app. I followed this tutorial to the letter on setting up cloud messaging
I'd like mobile devices to be able to receive notifications, so I add the requestPermssions() function directly to my index.html
<!-- Firebase -->
<script src="https://www.gstatic.com/firebasejs/3.4.0/firebase.js"></script>
<script src="https://www.gstatic.com/firebasejs/3.4.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/3.4.0/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/3.4.0/firebase-database.js"></script>
<script src="https://www.gstatic.com/firebasejs/3.4.0/firebase-storage.js"></script>
...
...
<script>
var config = {
apiKey: "56sds55hhjh906rwsbghghsd",
authDomain: "app-33aef.firebaseapp.com",
databaseURL: "https://app-33aef.firebaseio.com",
storageBucket: "app-33aef.appspot.com",
messagingSenderId: "43532673275"
};
firebase.initializeApp(config)
const messaging = firebase.messaging();
messaging.requestPermission()
.then(function(){
console.log('Have Permissions!');
return messaging.getToken()
})
.then(function(token){
console.log(token);
})
.catch(function(error){
console.warn('ERROR: ' + error);
})
messaging.onMessage(function(payload){
console.log('onMessage', payload);
})
</script>
However I'm seeing the following TypeError
firebase.messaging is not a function
After scouring the web I've read that you have to use firebase-admin to use the messaging() function. I've tried that as well but then I get an `Unexpected token import' error, but that may just be my project setup...
Does anyone have a solution for this? I feel like I'm going in circles here for something very simple
Well, I feel that this was so obvious that I never would have thought about it.
Include the script tag for firebase messaging (oy vey).
<script src="https://www.gstatic.com/firebasejs/4.2.0/firebase-messaging.js"></script>
It would have been helpful to mention this in the video as many others were stumped as well
I'm using both Google Analytics and branch.io in this website.
The website is designed for mobile.
The problem is that when clicking the banner with text "OPEN", the app cannot be opened.
Here is the code for the click:
$scope.openApp = () => {
let appOpened = false;
const open = () => {
if (!appOpened) {
appOpened = true;
branch.deepviewCta();
}
};
$timeout(open, 1000);
ga('send', 'event', 'homepage', 'download', {
hitCallback() {
open();
}
});
};
If I get rid of the GA code, it works fine:
$scope.openApp = () => {
let appOpened = false;
const open = () => {
if (!appOpened) {
appOpened = true;
branch.deepviewCta();
}
};
$timeout(open, 1000);
open();
};
The reason I put open() in hitCallback is to make sure GA sends out the hit because open() will redirect to another page.
Can you help me?
Alex from Branch.io here:
The Branch deepviewCta() function works on iOS 9+ by triggering an automatic redirect to a Universal Link URL (which opens the app) and then going to a fallback URL if that fails. But Apple is very specific about the situations in which a Universal Link is allowed to launch the app (including things like how long of a pause is allowed before redirection). Of course these restrictions are not public, so all we can do is guess. My suspicion is that putting the deepviewCta() function inside a GA callback is falling outside of Apple’s rules, so the app never opens and you are instead being sent to the fallback URL.
I can think of two options here:
You can build some way to trigger the GA and Branch functions separately so that they don’t conflict with Apple’s requirements.
We actually have a brand new, one-click integration with Google Analytics, which you can read about here and here. If you set that up, you’ll get all Branch-related events automatically instead of needing to manually collect link click data.
Hopefully that helps!
I'm currently in the learning phase for how the Google JS Client SDK works, since my boss needs me to learn how to integrate a Sign In button to his site to enable people to Authenticate via Google. I am testing the code for the custom Sign In button, with a touch of added functionality (like a Sign Out button), and in the process I've practically copy/pasted the code from their website. Let me show you the code first and then explain the issue, so that you can understand where the code is failing:
<script src="https://apis.google.com/js/client.js?onload=init"></script>
<script type="text/javascript">
var clientId = '{my client id here}'; // for web
var apiKey = '{my api key here}';
var scopes = 'profile email';
function SignOut() {
// I know, sloppy, but the signOut method from Google doesn't work.
window.location = 'https://accounts.google.com/logout';
// Additional code if necessary.
};
function makeApiCall() {
gapi.client.load('plus', 'v1', function () {
var request = gapi.client.plus.people.get({ 'userId': 'me' });
request.execute(function (response) {
var heading = document.createElement('h4');
var image = document.createElement('img');
image.src = response.image.url;
heading.appendChild(image);
heading.appendChild(document.createTextNode(response.displayName));
document.getElementById('name').appendChild(heading);
alert('User logged in. makeApiCall() has executed.');
})
})
};
function init() {
gapi.client.setApiKey(this.apiKey);
window.setTimeout(checkAuth, 1);
console.log('Up and ready to go.');
};
function checkAuth() {
// Triggers when the page and the SDK loads.
gapi.auth.authorize({ client_id: clientId, scope: scopes, immediate: true }, handleAuthResult);
};
function handleAuthClick(event) {
// Triggers after a user click event to ensure no popup blockers interfere.
gapi.auth.authorize({ client_id: clientId, scope: scopes, immediate: false }, handleAuthResult);
return false;
};
function handleAuthResult(authResult) {
var authorizeButton = document.getElementById('SignInBtn');
var signoutButton = document.getElementById('SignOutBtn');
if (authResult && !authResult.error) {
var V = JSON.stringify(authResult);
localStorage.setItem('GoogleAuthResult', V);
console.log(V); // Just for testing...
var authTimeout = (authResult.expires_in - 5 * 60) * 1000; setTimeout(checkAuth, authTimeout); // As recommended by a Google employee in a video, so that the token refreshes.
authorizeButton.style.display = 'none'; // Switching between Sign In and Out buttons.
signoutButton.style.display = 'inline-block';
makeApiCall();
} else {
// Immediate:true failed so user is NOT signed in.
// Make the Sign In button the one visible and prep it
// so that it executes the Immediate:false after user click:
authorizeButton.style.visibility = 'inline-block';
authorizeButton.onclick = handleAuthClick;
signoutButton.style.visibility = 'none';
}
};
</script>
The handleAuthClick function does run on the button click, but after taking the user to the Google Sign In page, when that page brings me back, the browser kinda flickers and the handleAuthResult function does not execute. Therefore, nothing changes in the page after the successful sign in; the button displayed is the Sign In button (Sign Out button not visible) and no information is displayed on the 'name' textNode. This happens on Internet Explorer (11), Firefox (39) and Chrome (44). Also, it happens at home on my laptop (straight connection to the web via Cable broadband) and at work (on Windows 8.1 behind an Active Directory).
I began wondering so I started refreshing the browser page and after a couple of refreshes, since the script runs from the beginning, the immediate:true fires again and voilá: user is connected and API call triggers.
So, on my laptop, I changed the function being called back, in the immediate:false line's callback parameter, to the init() function and that fixed the problem: everything runs smoothly from beginning to end. Yet, this is not the way it is supposed to work. I still don't know what is going on with that line.
This morning, on my computer at work (behind Active Directory), that fix didn't work. I have to refresh the page a couple of times so that the script runs from the beginning and the immediate:true triggers recognizing the user's Signed In state and displaying the proper button on screen.
Any ideas on why does this callback fail?
You need to define your apiKey in the first section of your code
var clientId = '{my client id here}'; // for web
var apiKey = '{my api key here}'
Maybe thats the problem.
Google ApiKeys
This is something I have been trying to figure out, but I am not sure exactly how to do it. I have a flex application that logs into facebook, but after that I can't access any of the facebook api. Right now I am using this HTML to log in:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
<!-- Include support librarys first -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
<script type="text/javascript" src="http://connect.facebook.net/en_US/all.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
//This example uses the javascript sdk to login before embedding the swf
var APP_ID = "[My App ID Here]";
var REDIRECT_URI = "http://apps.facebook.com/isotesthoskins/";
var PERMS = "publish_stream,offline_access"; //comma separated list of extended permissions
function init() {
FB.init({appId:APP_ID, status: true, cookie: true});
FB.getLoginStatus(handleLoginStatus);
}
function handleLoginStatus(response) {
if (response.session) { //Show the SWF
//A 'name' attribute with the same value as the 'id' is REQUIRED for Chrome/Mozilla browsers
swfobject.embedSWF("isotest.swf", "flashContent", "760", "500", "9.0", null, null, null, {name:"flashContent"});
} else { //ask the user to login
var params = window.location.toString().slice(window.location.toString().indexOf('?'));
top.location = 'https://graph.facebook.com/oauth/authorize?client_id='+APP_ID+'&scope='+PERMS+'&redirect_uri='+REDIRECT_URI+params;
}
}
$(init);
</script>
And everything logs in fine, but when I try this in the application after I am logged in, nothing happens.
Facebook.api("/me", function(response){
changeText.text = response.name;
});
I don't need to init because it was done by the javascript login, right? I might be wrong about that though.
Looks like you are calling the API using the Flex SDK.
That is not going to work, as the token is not shared between JS and Flex.
You should login on the Flex side or thunk into the JS to make the call.