Create Next.js Application with passwordless authentication by using Magic
Magic is a simply Authentication Service and SDK. We can easy to create applications with passwordless / WebAu […]
目次
Magic is a simply Authentication Service and SDK. We can easy to create applications with passwordless / WebAuthn and Social Login.
Today, I’ve tried to create a new Next.js application and integrated it with Magic.
Step1: Create a new Magic account
We can start the service as free. https://dashboard.magic.link/signup is a Sign up page URL.
After put our own email, we must not close or back from the page.
We’ll get a confirm email from Magic, so we need to confirm it.
Then, we can sign in to the dashboard.
Step2: Get a API keys
By default, we have an example application named First App
. So let’s click the Get Started
button.
We can check the application’s publishable key and secret key.
And if you want to clear these API Keys, we can regenerate it in the API Keys
tab.
Step3: Create a new Next.js application
Next, we’ll create a new React application.
I love to create Next.js applications using TypeScript. So I always use my own starter-template for Next.js.
$ npx create-next-app magic-example --example "https://github.com/wpkyoto/nextjs-starter-typescript/tree/main"
$ cd magic-example
And install the magic-sdk for frontend.
$ yarn add magic-sdk
Then, we can setup the SDK like the following code.
const client = new Magic('pk_test_xxxxx')
If you want to use the client in several places, I recommend using useContext
.
const MagicContext = createContext<{
magicClient?: Magic;
}>({})
const MagicProvider: FC<PropsWithChildren<{
publishableAPIKey: string;
}>> = ({publishableAPIKey, children}) => {
const magic = useMemo(() => {
if (typeof window === 'undefined') return;
return new Magic(publishableAPIKey)
}, [publishableAPIKey])
return (
<MagicContext.Provider value={{
magicClient: magic,
}}>
{children}
</MagicContext.Provider>
)
}
const useMagic = () => useContext(MagicContext)
tips: the Magic
class using window
property
If you using any SSR enabled framework(Next.js / Gatsby / etc…), we should handle the window
property before initialize the Magic
class. Because the class may using the property, so when we use it in Node.js, we’ll get a ReferenceError: window is not defined
error.
We must check is the window not undefined.
Step4: Check the login status
We can check the user’s login status by using Magic.user.isLoggedIn
.
const {magicClient} = useMagic()
const [isLogin, setLoginStatus] = useState(false)
useEffect(() => {
if (!magicClient) return;
(async() => {
const result = await magicClient.user.isLoggedIn()
setLoginStatus(result)
})()
}, [magicClient, setLoginStatus])
In this example, we can dispatch the following cases.
- If the
magicClient
is undefined, this page will be loading. - If the
magicClient
is not undefined, and theisLogin
isfalse
, the user does not logged-in. - If the magicClient is not undefined, and the isLogin is true, the user does logged-in.
So we can change the React component by these properties.
Step5: Login / Sign-up by Email
Finally, we can create a Login and Sign-up form. The Login and Sign up action can call from the same function.
const useLoginByMagic = () => {
const [errorMessage, setErrorMessage] = useState<string>(undefined)
const [email, setEmail] = useState('')
const [token, setToken] = useState<string>(undefined)
const {magicClient} = useMagic()
const handleLogin = useCallback(async() => {
if (!magicClient) throw new Error('We have to initilize the magic client before use the hook. Or the Client can not use in Server Side process.')
try {
if (!email) throw new Error('Email is required')
setErrorMessage(undefined)
const magicAuthToken = await magicClient.auth.loginWithMagicLink({
email
})
setToken(magicAuthToken)
} catch (e) {
console.error(e)
setErrorMessage(e.message)
}
}, [email, magicClient, setToken, setErrorMessage])
return {
email,
setEmail,
token,
errorMessage,
handleLogin,
}
}
This code is example React hook to handle the login / sign up process.
We can update the user’s email by setEmail
. And when calling the handleLogin function, Magic will be login or create a new user by the provided email address. We can watch the token
and the errorMessage
properties to check the login process result.
If token
is not undefined, the login process will be completed. And if the errorMessage
is not undefined, the process may be failed by any reason.
Conclusion: Simple and useful, but not cheap
Magic is super simply authentication SaaS. We can easy to add the authentication feature into our own application.
But, the free plan can create only 100 active users. If you have more users, we need to pay 35 USD per month or more. It’s a little bit expensive than Auth0 / AWS Cognito User Pools or Firebase.
So I think it’s good for the paid application or closed application.
If you feel expensive the prices, I recommend using Auth0 and create a passwordless / WebAuthn / Social Login feature by yourself.