Skip to content

Instantly share code, notes, and snippets.

@tunnela
Last active February 3, 2025 12:36
Show Gist options
  • Select an option

  • Save tunnela/6e4ee5f1d72a50e89d8be99fca1158f5 to your computer and use it in GitHub Desktop.

Select an option

Save tunnela/6e4ee5f1d72a50e89d8be99fca1158f5 to your computer and use it in GitHub Desktop.
Webflow + Firebase user authentication

Webflow + Firebase user authentication

You can find a demo at https://webflow-authentication.webflow.io/sign-up.

1. Set up Firebase authentication

Log in to Firebase console. Create a new app and from the left side menu, under Develop, navigate to Authentication. Enable Email/Password sign-in provider. After this, create a Web application under the current Firebase project and copy the given firebaseConfig object.

2. Create Webflow pages

Go to the project settings and Custom Code tab. Add content from webflow-custom-code-before-body.html gist file to Footer Code input. Replace webflowAuth.firebaseConfig with the one you copied in the previous step. After this go to designer and create 3 new pages:

  1. /user page which is meant for logged in users.
  2. /log-in page which is used for logging in.
  3. /sign-up page which is used for signing up.

On /sign-up page, create a form and inside it add a submit button plus two input fields - email and password. Then do the following adjustments:

  1. Give form element (form element inside form, Form > Form) custom data attribute called data-signup-form.
  2. Give email field custom data attribute called data-signup-email.
  3. Give password field custom data attribute called data-signup-password.
  4. Give form error element custom data attribute called data-signup-error.
  5. Add custom data attribute called data-user-unauth to the body element.

On /log-in page, create a form and inside it add a submit button plus two input fields - email and password. Then do the following adjustments:

  1. Give form element (form element inside form, Form > Form) custom data attribute called data-login-form.
  2. Give email field custom data attribute called data-login-email.
  3. Give password field custom data attribute called data-login-password.
  4. Give form error element custom data attribute called data-login-error.
  5. Add custom data attribute called data-user-unauth to the body element.

On /user page add custom data attribute called data-user-auth to the body element. In addition to this, you can show any user properties returned from Firebase by giving an element custom data attribute called data-user. After this you can use user properties with curly bracets i.e. Your email is {{email}}.

If you have a navigation element from which you can navigate to /log-in, /sign-up etc. pages, you can adjust their visibility by using custom data attributes called data-user-auth and data-user-unauth. You can also add either one of those data attributes to body element which will adjust visibility of the given page. Log out button can be created by giving a link element a custom data attribute called data-logout.

3. Credits

Some of the ideas are taken from the YouTube video series by Jason Dark which you can find at https://www.youtube.com/watch?v=30AIpEnsEaQ&list=PL4TuDUnZkkhzSwfbFj6EJjxim6218ORc0.

<script src="https://www.gstatic.com/firebasejs/8.1.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.1.1/firebase-analytics.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.1.1/firebase-auth.js"></script>
<script>
var webflowAuth = {
loginPath: '/log-in',
loginRedirectPath: '/user',
signupPath: '/sign-up',
signupRedirectPath: '/user',
logoutRedirectPath: '/',
firebaseConfig: {
apiKey: "",
authDomain: "",
databaseURL: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: ""
}
};
</script>
<!-- you can replace this with the content from webflow-firebase-user-authentication.js -->
<script src="webflow-firebase-user-authentication.js"></script>
/*
Example config
var webflowAuth = {
loginPath: '/log-in',
loginRedirectPath: '/user',
signupPath: '/sign-up',
signupRedirectPath: '/user',
logoutRedirectPath: '/',
firebaseConfig: {
apiKey: "",
authDomain: "",
databaseURL: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: ""
}
};
*/
firebase.initializeApp(webflowAuth.firebaseConfig);
firebase.analytics && firebase.analytics();
{
var user;
var bodyAuth = document.body.getAttribute('data-user-auth');
var bodyUnauth = document.body.getAttribute('data-user-unauth');
var userAuth = document.querySelectorAll('[data-user-auth]');
var userUnauth = document.querySelectorAll('[data-user-unauth]');
var userDisplayName = document.querySelectorAll('[data-user-displayName]');
var userEmail = document.querySelectorAll('[data-user-email]');
var userContent = document.querySelectorAll('[data-user]');
userAuth.forEach(function(el) { el.style.display = 'none'; });
userUnauth.forEach(function(el) { el.style.display = 'none'; });
function updateContent() {
if (!user) {
return;
}
userContent.forEach(function(el) {
el.innerText = el.innerText.replace(/\{\{([^\}]+)\}\}/g, function(match, variable) {
return typeof user[variable] === 'undefined' ? '' : user[variable];
});
});
}
firebase.auth().onAuthStateChanged(function(authUser) {
user = authUser;
updateContent();
if (user && bodyUnauth) {
window.location.href = webflowAuth.loginRedirectPath;
} else if (!user && bodyAuth) {
window.location.href = webflowAuth.loginPath;
}
if (user) {
userAuth.forEach(function(el) { el.style.display = null; });
userUnauth.forEach(function(el) { el.style.display = 'none'; });
userEmail.forEach(function(el) { el.innerText = user.email; });
userDisplayName.forEach(function(el) { el.innerText = user.displayName; });
} else {
userAuth.forEach(function(el) { el.style.display = 'none'; });
userUnauth.forEach(function(el) { el.style.display = null; });
userEmail.forEach(function(el) { el.innerText = ''; });
userDisplayName.forEach(function(el) { el.innerText = ''; });
}
});
var signupForms = document.querySelectorAll('[data-signup-form]');
var signupErrors = document.querySelectorAll('[data-signup-error]');
var signupLoading = document.querySelectorAll('[data-signup-loading]');
var signupIdle = document.querySelectorAll('[data-signup-idle]');
signupForms.forEach(function(el) {
var signupEmail = el.querySelector('[data-signup-email]');
var signupPassword = el.querySelector('[data-signup-password]');
el.addEventListener('submit', function(e) {
e.preventDefault();
e.stopPropagation();
signupErrors.forEach(function(el) { el.style.display = 'none'; });
signupLoading.forEach(function(el) { el.style.display = 'block'; });
signupIdle.forEach(function(el) { el.style.display = 'none'; });
firebase.auth().createUserWithEmailAndPassword(signupEmail.value, signupPassword.value)
.then(function(authUser) {
user = authUser;
window.location.href = webflowAuth.signupRedirectPath;
})
.catch(function(error) {
signupErrors.forEach(function(el) {
el.innerText = error.message;
el.style.display = 'block';
});
setTimeout(function() {
signupLoading.forEach(function(el) { el.style.display = 'none'; });
signupIdle.forEach(function(el) { el.style.display = null; });
}, 1000);
});
});
});
var loginForms = document.querySelectorAll('[data-login-form]');
var loginErrors = document.querySelectorAll('[data-login-error]');
var loginLoading = document.querySelectorAll('[data-login-loading]');
var loginIdle = document.querySelectorAll('[data-login-idle]');
loginForms.forEach(function(el) {
var loginEmail = el.querySelector('[data-login-email]');
var loginPassword = el.querySelector('[data-login-password]');
el.addEventListener('submit', function(e) {
e.preventDefault();
e.stopPropagation();
loginErrors.forEach(function(el) { el.style.display = 'none'; });
loginIdle.forEach(function(el) { el.style.display = 'none'; });
loginLoading.forEach(function(el) { el.style.display = 'block'; });
firebase.auth().signInWithEmailAndPassword(loginEmail.value, loginPassword.value)
.then(function(authUser) {
user = authUser;
window.location.href = webflowAuth.loginRedirectPath;
})
.catch(function(error) {
loginErrors.forEach(function(el) {
el.innerText = error.message;
el.style.display = 'block';
});
setTimeout(function() {
loginIdle.forEach(function(el) { el.style.display = null; });
loginLoading.forEach(function(el) { el.style.display = 'none'; });
}, 1000);
});
});
});
var authLogout = document.querySelectorAll('[data-logout]');
authLogout.forEach(function(el) {
el.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
firebase.auth().signOut().then(function() {
user = null;
window.location.href = webflowAuth.logoutRedirectPath;
})
.catch(function() {});
});
})
}
@bossdown123
Copy link

anyone know how to use firestore to display specific user data

@tuckeralford
Copy link

@tunnela I'm stuck on adding the custom attributes in Webflow. It looks lik I have everything configured correctly in the frontend, but nothing is functioning. Any help would be sweet!

Screen Shot 2022-02-10 at 4 28 11 PM

Thanks so much!

@tunnela
Copy link
Author

tunnela commented Feb 11, 2022

@bossdown123 you can checkout my WIP example at https://webflow-authentication-v2.webflow.io where I use Firestore to save user information!

@tunnela
Copy link
Author

tunnela commented Feb 11, 2022

@tuckeralford I can't help much without seeing the website and its HTML/JS source code.

@truereflectionmedia
Copy link

It works great thank you for this. One part I'm not clear on why use Forms and forEach instead of a single form. I'm using this with a popup form. just curious.

@arnotventures
Copy link

I noticed all of the API information is exposed.. is that an issue?

@truereflectionmedia
Copy link

Arno the API is designed that way, you lock it down in google console. Also within firebase if using the firestore you create security rules.

@biniam-ux
Copy link

Thanks @tunnela for the post. I've managed to create gated access using firebase auth!
also thanks to @osamaaliarshad for the 'forgot password" part, that waas great too!

my little contribution will be a "delete user" functionality, that allow user to delete their account from firebase when logged in (if anyone need it):

var deleteAccountButton = document.querySelector("#delete-account-button"); deleteAccountButton.addEventListener("click", function () { firebase .auth() .currentUser.delete() .then(function () { // User deleted. }) .catch(function (error) { // An error occurred. }); });

btw, does anyone know as way to send user data (such as name, surname) to firebase firestore database for each individual user? that will be dope!

@Opsje
Copy link

Opsje commented Jun 15, 2023

Has anyone been able to get it working with firebase version 9?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment