Skip to content

Instantly share code, notes, and snippets.

@tunnela
Last active February 3, 2025 12:36
Show Gist options
  • Save tunnela/6e4ee5f1d72a50e89d8be99fca1158f5 to your computer and use it in GitHub Desktop.
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() {});
});
})
}
@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