I have implemented google authentication on a web page using firebase sdk.
It works fine on chrome, firefox and edge, but on ie11 I get a google authentication page but the authenticated user information is always null.
I think it's supported in ie 11.
firebase.google.com/support/guides/environments_js-sdk
I added the polyfill by cdn and executed it but it doesn't work. User information is still null.
unpkg.com/core-js-bundle#3.0.1/minified.js
Why doesn't it only work with ie11?
*function signInGoogle() {
if (!firebase.auth().currentUser) {
var provider = new firebase.auth.GoogleAuthProvider();
provider.addScope('https://www.googleapis.com/auth/plus.login');
firebase.auth().signInWithRedirect(provider);
} else {
firebase.auth().signOut();
}
}
function initApp() {
firebase.auth().getRedirectResult().then(function (result) {
var user = result.user;
console.log(user); // always null
if (user) {
document.getElementById('createForm').submit();
}
}).catch(function (error) {
var errorCode = error.code;
var errorMessage = error.message;
var email = error.email;
var credential = error.credential;
// [START_EXCLUDE]
if (errorCode === 'auth/account-exists-with-different-credential') {
alert('You have already signed up with a different auth provider for that email.');
} else {
console.error(error);
}
});
}*
In order to reduce the SDK size, Firebase no longer ship the Polyfils that are required for some older browsers. This was one of the changes in the 6.x release.
Please take a look at https://firebase.google.com/support/guides/environments_js-sdk how to manually enable Polyfills as required.
Related
I want to use access token instead of authorization. I have get my token and stored it in local storage. Now I am saying, if user has token then do not need of authorization. just call the required method. But it says "API keys are not supported by this API. Expected OAuth2 access token or other authentication credentials that assert a principal. See https://cloud.google.com/docs/authentication". How can I use access token in every Gmail method calling. Like for adding label, getting email messages in my DOM and all this stuff.
In short, I wanna get rid of every time authentication.
Normally with authorization flow we use something called a refresh token to enable applications to request a new access token when the user is offline or the user returns after being away from the application. This is not possible with implicit flow.
Implicit flow is defined in The OAuth 2.0 Authorization Framework
The implicit grant type is used to obtain access tokens (it does not
support the issuance of refresh tokens) and is optimized for public
clients known to operate a particular redirection URI. These clients
are typically implemented in a browser using a scripting language
such as JavaScript.
Client side JavaScript uses implicit flow there is no other option, the user will need to authorize your application every time they want to use it.
Official example.
The official Gmail JavaScript quick start will walk you though how to access this api. The client library handles all the interaction between your application and the authorization server for you so you wont need to worry about where to apply the access token.
<!DOCTYPE html>
<html>
<head>
<title>Gmail API Quickstart</title>
<meta charset="utf-8" />
</head>
<body>
<p>Gmail API Quickstart</p>
<!--Add buttons to initiate auth sequence and sign out-->
<button id="authorize_button" onclick="handleAuthClick()">Authorize</button>
<button id="signout_button" onclick="handleSignoutClick()">Sign Out</button>
<pre id="content" style="white-space: pre-wrap;"></pre>
<script type="text/javascript">
/* exported gapiLoaded */
/* exported gisLoaded */
/* exported handleAuthClick */
/* exported handleSignoutClick */
// TODO(developer): Set to client ID and API key from the Developer Console
const CLIENT_ID = '<YOUR_CLIENT_ID>';
const API_KEY = '<YOUR_API_KEY>';
// Discovery doc URL for APIs used by the quickstart
const DISCOVERY_DOC = 'https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest';
// Authorization scopes required by the API; multiple scopes can be
// included, separated by spaces.
const SCOPES = 'https://www.googleapis.com/auth/gmail.readonly';
let tokenClient;
let gapiInited = false;
let gisInited = false;
document.getElementById('authorize_button').style.visibility = 'hidden';
document.getElementById('signout_button').style.visibility = 'hidden';
/**
* Callback after api.js is loaded.
*/
function gapiLoaded() {
gapi.load('client', initializeGapiClient);
}
/**
* Callback after the API client is loaded. Loads the
* discovery doc to initialize the API.
*/
async function initializeGapiClient() {
await gapi.client.init({
apiKey: API_KEY,
discoveryDocs: [DISCOVERY_DOC],
});
gapiInited = true;
maybeEnableButtons();
}
/**
* Callback after Google Identity Services are loaded.
*/
function gisLoaded() {
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: CLIENT_ID,
scope: SCOPES,
callback: '', // defined later
});
gisInited = true;
maybeEnableButtons();
}
/**
* Enables user interaction after all libraries are loaded.
*/
function maybeEnableButtons() {
if (gapiInited && gisInited) {
document.getElementById('authorize_button').style.visibility = 'visible';
}
}
/**
* Sign in the user upon button click.
*/
function handleAuthClick() {
tokenClient.callback = async (resp) => {
if (resp.error !== undefined) {
throw (resp);
}
document.getElementById('signout_button').style.visibility = 'visible';
document.getElementById('authorize_button').innerText = 'Refresh';
await listLabels();
};
if (gapi.client.getToken() === null) {
// Prompt the user to select a Google Account and ask for consent to share their data
// when establishing a new session.
tokenClient.requestAccessToken({prompt: 'consent'});
} else {
// Skip display of account chooser and consent dialog for an existing session.
tokenClient.requestAccessToken({prompt: ''});
}
}
/**
* Sign out the user upon button click.
*/
function handleSignoutClick() {
const token = gapi.client.getToken();
if (token !== null) {
google.accounts.oauth2.revoke(token.access_token);
gapi.client.setToken('');
document.getElementById('content').innerText = '';
document.getElementById('authorize_button').innerText = 'Authorize';
document.getElementById('signout_button').style.visibility = 'hidden';
}
}
/**
* Print all Labels in the authorized user's inbox. If no labels
* are found an appropriate message is printed.
*/
async function listLabels() {
let response;
try {
response = await gapi.client.gmail.users.labels.list({
'userId': 'me',
});
} catch (err) {
document.getElementById('content').innerText = err.message;
return;
}
const labels = response.result.labels;
if (!labels || labels.length == 0) {
document.getElementById('content').innerText = 'No labels found.';
return;
}
// Flatten to string to display
const output = labels.reduce(
(str, label) => `${str}${label.name}\n`,
'Labels:\n');
document.getElementById('content').innerText = output;
}
</script>
<script async defer src="https://apis.google.com/js/api.js" onload="gapiLoaded()"></script>
<script async defer src="https://accounts.google.com/gsi/client" onload="gisLoaded()"></script>
</body>
</html>
firebase.auth().createUserWithEmailAndPassword(email, password).then((user) => {
user.sendEmailVerification().then(()=>{console.log("Email Sent")}).catch((err)=>{console.log(err)});
}).catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
});
Getting error - user.sendEmailVerification() is not function.
Can someone help how to send Verification Email in Firebase Authentication?
I faced the same issue and resolved now.You followed something that is from older versions.The latest library doesn't have the same code u using,please see the latest documentation:
https://firebase.google.com/docs/auth/web/manage-users
I'm trying to upload my user's files to a bucket connected to their uid. So, in order to do it I try to grab their uid from the following code in my upload.js file:
const uploader = document.getElementById("uploader");
const fileButton = document.getElementById("fileButton");
fileButton.addEventListener('change', function(e)
{
// Get file
var file = e.target.files[0];
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
console.log("state = definitely signed in");
firebase.storage().ref('users').child(user.uid + "designs").put(file);
} else {
// No user is signed in.
console.log("state = definitely signed out");
}
});
});
Even after the user is logged in and the it directs them to the new page I always get informed that they aren't signed in. Should I use information from the session cookie instead? Any help would be appreciated!
After a few days I realised that I wasn't calling the id token correlated with the user that is logged in. This solved it:
firebase.auth().onAuthStateChanged(function(user)
{
if (user)
{
// User is signed in.
console.log(user);
user.getIdToken().then(function(idToken)
{ // <------ Check this line
console.log(idToken); // It shows the Firebase token now
});
console.log(user.uid);
firebase.storage().ref('users').child(user.uid + "/designs").put(file);
}
else
{
// No user is signed in.
console.log("state = definitely signed out");
}
});
I am creating a website that has login with firebase google authentication. It's working fine in all browsers. But when I add this website in my app as webview it does not work.
website showing this error:
This operation is not supported in the environment this application is running on. "location.protocol" must be http, https or chrome-extension and web storage must be enabled.
here some code bellow:
javascript code:
function login(){
console.log('login called');
function newLoginHappend(user){
if(user){
model_questions(user);
}else{
var provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider).then(function(result) {
// This gives you a Google Access Token. You can use it to access the Google API.
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
// ...
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});
}
}
firebase.auth().onAuthStateChanged(newLoginHappend);
}
window.onload = login();
webview code:
WebSettings webSettings =webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient());
webView.loadUrl("https://mahmud-cse16.github.io/CBAP_Handout/");
Is there any way or technique to solve this problem?? if you have any idea then share with us please.
thanks
Try enabling DOM Storage for the webview
WebSettings webSettings = myWebView.getSettings();
webSettings.setDomStorageEnabled(true); // localStorage
Sets whether the DOM storage API is enabled. The default value is false.
Android Developer Reference
To get around "disallowed_useragent" error, one way is to use the Android Google Auth SDK to log in natively in the app, and then pass the Google token to the Webview so Firebase can use it with auth.signInWithCredential().
It might work for other providers but here's how I did it with Google auth on Android:
Android:
val gso =
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(clientId)
.requestEmail()
.build()
val googleSignInClient = GoogleSignIn.getClient(activity, gso)
activity.startActivityForResult(
googleSignInClient.signInIntent,
object : ActivityWithResultListener.OnActivityResultListener {
override fun onActivityResult(resultCode: Int, data: Intent?) {
if (data != null) {
val credential = GoogleAuthProvider.getCredential(account.idToken!!, null)
idToken = account.idToken!!
// Then pass the token to your webview via a JS interface
}
}
}
)
Web:
const idTokenFromApp = AndroidBridge.getAuthToken(); // This is the idToken from the Android code above
if (idTokenFromApp) {
// from https://firebase.google.com/docs/auth/web/google-signin
// Build Firebase credential with the Google ID token.
// https://firebase.google.com/docs/reference/js/v8/firebase.auth.GoogleAuthProvider#static-credential
const credential = firebase.auth.GoogleAuthProvider.credential(idTokenFromApp);
// Sign in with credential from the Google user.
firebase.auth.signInWithCredential(credential).catch((error) => {
// Handle Errors here.
const errorCode = error.code;
const errorMessage = error.message;
logError(`Error logging in: ${errorCode} ${errorMessage} token: ${idTokenFromApp}`, error);
});
}
I'm currently using Firebase such that users sign in with their Google accounts to access the app. However, closing the page/opening the page in a new tab requires the user to sign in again. Is there a way to prevent users from having to re-login?
Here is the login code I am using (the example from the firebase docs)
function firebaseLogin() {
firebase.auth().signInWithPopup(provider).then(function(result) {
var token = result.credential.accessToken;
var user = result.user;
document.getElementById('user-name').innerHTML = user.displayName;
document.getElementById('propic').src = user.photoURL;
addClass(login, 'hidden');
removeClass(logout, 'hidden');
var snackbarData = {
message: 'Login Successful',
timeout: 2000
};
snackbarContainer.MaterialSnackbar.showSnackbar(snackbarData);
console.log(user);
reloadList();
}).catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
var email = error.email;
var credential = error.credential;
var snackbarData = {
message: 'Login Unsuccessful',
timeout: 2000
};
snackbarContainer.MaterialSnackbar.showSnackbar(snackbarData);
console.error(error);
});
}
I'm not sure if this is the official way to do it, but I ended up saving the user returned from firebase.auth().currentUser in localStorage, and then checking if a user could be found in localStorage on document load. If a user is found, I just set firebase.auth().currentUser to equal the user from localStorage, and everything seemed to work as intended. (For example, if there wasn't an authenticated user, the client wouldn't be able to make calls to the database, but setting currentUser in this fashion allowed accessing the database.)