End-to-end example showing how Magic works with the Node.js Express framework.
Welcome to our end-to-end example to demonstrate how Magic works with your own Node.js server using the popular Express framework! If you haven't gone through the Hello World Example, we strongly recommend going through it before starting this tutorial.
In this example, we'll be implementing an additional feature in the Hello World example - letting only authorized users buy apples 🍎 and see how many they own.
0. Set Up Tutorial Template
Use our Node Tutorial Template to follow along with this tutorial.
The full stack Node.js server is set up using the vanilla Express template on CodeSandBox, using NeDB as an ultra lightweight database (you can switch it to other databases like MongoDB too) and the
express-session NPM package to manage sessions. We'll make use of the Magic Admin SDK for this example. You can learn how to install it via npm or yarn in the Node.js reference.
1. Setup Environment Variables
From the CodeSandBox's Node Tutorial Template, click "Fork" to create your own instance to play with.
Once you've forked the template, click on the "Server Rack" icon in the left menu, and then update your "Secret Keys".
To grab these two values, you need to sign up or log in to the Magic Dashboard to view your API keys. Once you are logged in you, you can add
MAGIC_SECRET_KEY as Name, and your actual secret API key, which looks something like
sk_test_********* as Value.
Once that's done, you can add
MAGIC_PUBLISHABLE_KEY as Name, and your publishable API key, which looks something like
pk_test_********* as Value.
Once the keys are copy and pasted in the Secret Keys section, click Restart Server to load these environment variables in the CodeSandBox container.
Note that the
MAGIC_SECRET_KEY environment variable is used to initialize the Magic Admin SDK.
Your very own full-stack Magic Apple Store application is now running! 🍎
The next steps explain each of major sections of the code base.
2️. Implement Auth Strategy
Magic leverages the popular and battle-tested Passport authentication middleware package for Express to provide our passwordless authentication service. This way it will be very seamless and easy to integrate for developers who are already familiar with Passport! (Don't worry if you are not, we'll go through comprehensive examples in this tutorial)
Magic's authentication is based on the Decentralized ID (DID) token standard, and the strategy implemented by
passport-magic already takes care of the heavy-lifting by verifying the token and returning the authenticated user object. In this strategy, we'd like to define what to do if this user is a new user versus a returning user.
Note that in the DID standard we use
issuer quite a lot, which looks something like
did:ethr:0xE0cef4417a772512E6C95cEf366403839b0D6D6D, it represents a unique blockchain public address which can often be used as an identifier field. The issuer can be used to fetch the authenticated user's metadata, which includes their associated email address.
3️. Implement Auth Behaviors
Implement User Signup
The user signup behavior is pretty straightforward in this case, where a new user would be inserted into the NeDB database.
Implement User Login
Since authentication is token-based, the user login behavior needs to implement a timestamp check to protect against replay attacks - here's a simple reference implementation, but you can make adjustments depending on your security preference.
Here's an example of how to call the Login Endpoint from the client-side:
4️. Implement Session Behavior
An awesome feature from the Passport middleware is the possibility to populate the
req.user object with an actual database record, so that the data can be conveniently used in your endpoints. See the next section for more examples.
5️. Implement User Endpoints
Implement Get Data Endpoint
This endpoint is responsible for grabbing the currently authenticated user's data, including the number of apples 🍎 to be displayed in the front-end! Note how this endpoint uses
req.isAuthenticated() to check if the current user is authenticated, and
req.user can be passed to the front-end without fetching from the database again!
Here's how you would call the Get Data Endpoint from the client-side:
Implement Buy Apple Endpoint
Follows similar pattern as the Get Data Endpoint, instead authenticated user can now update and increment their apple count!
Here's how you would call the Buy Apple Endpoint from the client-side:
Implement Logout Endpoint
To log out the user, you can use the Magic Admin SDK to logout the current user based on the user ID, remember to also call
req.logout() to clear the Express user session as well!
With this, you no longer have to call
magic.user.logout() on the client-side.
🎉 Congratulations! Now that you've completed the tutorial, you should have a working version of the 🍎 Apple Store app!
👉 What's Next
Use Magic with existing tools
Firebase – Magic provides much flexibility and composability to be combined with many other powerful platforms such as Firebase. Learn how to plug Magic into the entire Firebase suite of tools!
Customize your Magic flow 🎨
You can customize the login experience using your own UI instead of Magic's default one and/or customize the magic link email with your brand. Learn how to customize.