Create the Login & Admin Page
Let's create a login and an admin page for your web application.
Creating a login page
In order for users to sign up for an account and eventually log in, we need a page. We are going to create that in a new
services/web/src/routes/auth/login.svelte
file given below. Click Run and navigate to services/web
:
cd services/web
Adding a Sign In Button
Let’s add a simple button to sign in and a click handler to the login.svelte
file given below:
<script>
const signIn = () => {
// Open FirebaseUI
}
</script>
<button on:click={signIn}>Sign In</button>
Adding a menu item for Sign In page
To reach this page, we are going to add a new menu item to the navbar in the
src/components/Nav.svelte
file given below:
<script>
...
import AuthNavItem from "./auth-nav-item.svelte";
...
</script>
<style>
...
li:last-child {
float: right;
}
...
</style>
...
<li><AuthNavItem/></li>
</ul>
</nav>
Authenticating navbar item
An auth-nav-item.svelte
component is created in the same directory as the Nav.svelte
component we updated just now. Add the following content to it:
<style>
a {
/* Matches the styles in Nav.svelte */
text-decoration: none;
padding: 1em 0.5em;
display: block;
}
</style>
<a href="/auth/login">Sign In</a>
At this point, you can
Failing tests
If you were to run your tests now in another terminal with
npm run cy:run
, they would fail. Can you guess why? Try it out,. Start the dev server and run the tests to see what went wrong.That makes sense, as we added an additional menu item to the navbar, but one of our test cases did not expect that. Have a look at the test suite in the file
services/web/cypress/components/nav.spec.js
given below and update the failing test to make sure it expects four menu items.
Creating a FirebaseUI configuration object
Back in the src/routes/auth/login.svelte
page, what we need is to create a
FirebaseUI configuration object. This is where we configure which authentication
providers to display and also what to do once a user successfully registers an
account and/or signs in.
Update the <script>
tag to match the following:
<script>
import { goto } from '@sapper/app'; // Function to go to a specific URL
import { onMount } from "svelte"; // Function to perform specific operations when a component mounts
export let firebaseAuthUiConfig = {};
onMount(() => {
firebaseAuthUiConfig = {
callbacks: {
signInSuccessWithAuthResult: () => {
goto("/admin");
return false;
}
},
credentialHelper: firebaseui.auth.CredentialHelper.NONE,
signInFlow: "popup",
signInOptions: [firebase.auth.EmailAuthProvider.PROVIDER_ID]
};
});
const signIn = () => {
firebaseAuthUi.start("#firebaseui-auth-container", firebaseAuthUiConfig);
};
</script>
A few things to note:
- We specify the
firebaseAuthUiConfig
in theonMount()
. This is because theSvelte lifecycle method lifecycle firebase
andfirebaseui
variables are only available to the client. - In the
signInSuccessWithAuthResult
callback, we navigate to the/admin
page. We will configure that shortly. This is whatever URL you choose that is only available to authenticated users. Thereturn false
tells FirebaseUI that we take care of the redirect when authentication succeeds. - The
signIn
click handler specifies a#firebaseui-auth-container
container. This is where FirebaseUI is going to render its user interface.
Below the sign in button in login.svelte
, add the following empty div:
<div id="firebaseui-auth-container"></div>
Go back to your web application and click the Sign In navigation link to bring up the FirebaseUI screen. Provide your email address and click “Next”. It will show an error message.
Create account vs. sign in
The first time you enter your email address and click “Next”, FirebaseUI checks its user database and notices you don’t yet have an account. The UI updates on-the-fly to prompt for your name and password.
Going forward, once you enter your email address, FirebaseUI recognizes the email address and will prompt for your password.
The given sign-in provider is disabled
Oops… Firebase does not allow us to create an email and password account because we have not yet enabled this authentication provider.
To enable the Email/Password sign-in method:
- Open the Firebase web console.
- Click on “Authentication” in the navigation.
- Select the “Sign-in method” tab.
- Click “Email/Password” at the top.
- Click the first “Enable” toggle. To learn about the second “Enable” toggle, please refer to this link.
- Click “Save”.
Back on the login page, click “Next” again and type your first & last name, choose a password, and click “Save”.
You’ll get the error message “404 Not found”. Perfect, that’s what we are looking for, at the moment. Note the
URL you’re on: it’s /admin
, exactly as we configured it in the FirebaseUI config object earlier.
Hiding the Sign In button
Before we create the admin page, we want to hide the “Sign In” button when the user is signing in. To do that, we update the
src/routes/auth/login.svelte
page:
- Add the following code above the
onMount()
function.
let isSignInUiShown = false;
- Add a
uiShown
callback to thefirebaseAuthUiConfig
object, so it looks like this:
firebaseAuthUiConfig = {
callbacks: {
signInSuccessWithAuthResult: () => {
goto("/admin");
return false;
},
uiShown: () => {
isSignInUiShown = true;
}
},
credentialHelper: firebaseui.auth.CredentialHelper.NONE,
signInFlow: "popup",
signInOptions:[firebase.auth.EmailAuthProvider.PROVIDER_ID]
};
- Wrap the Sign In button in an
{#if !isSignInUiShown}
statement, as:
{#if !isSignInUiShown}
<button on:click={signIn}>Sign In</button>
{/if}
Get hands-on with 1200+ tech skills courses.