Skip to content

Commit

Permalink
[Examples] remove getInitialProps from with-firebase-authentication (v…
Browse files Browse the repository at this point in the history
…ercel#13895)

Related to [11014](vercel#11014)
  • Loading branch information
todortotev authored and rokinsky committed Jul 11, 2020
1 parent e5305df commit e7a5264
Show file tree
Hide file tree
Showing 21 changed files with 122 additions and 580 deletions.
13 changes: 0 additions & 13 deletions examples/with-firebase-authentication/.env.local.example

This file was deleted.

3 changes: 1 addition & 2 deletions examples/with-firebase-authentication/README.md
@@ -1,6 +1,6 @@
# Example: Firebase authentication with a serverless API

This example includes Firebase authentication and serverless [API routes](https://nextjs.org/docs/api-routes/introduction). On login, the app calls `/api/login`, which stores the user's info (their decoded Firebase token) in a cookie so that it's available server-side in `getInitialProps`. On logout, the app calls `/api/logout` to destroy the cookie.
This example includes Firebase authentication and serverless [API routes](https://nextjs.org/docs/api-routes/introduction).

## How to use

Expand Down Expand Up @@ -32,7 +32,6 @@ Set up Firebase:
- Get your account credentials from the Firebase console at _Project settings > Service accounts_, where you can click on _Generate new private key_ and download the credentials as a json file. It will contain keys such as `project_id`, `client_email` and `client_id`. Set them as environment variables in the `.env.local` file at the root of this project.
- Get your authentication credentials from the Firebase console under _Project settings > General> Your apps_ Add a new web app if you don't already have one. Under _Firebase SDK snippet_ choose _Config_ to get the configuration as JSON. It will include keys like `apiKey`, `authDomain` and `databaseUrl`. Set the appropriate environment variables in the `.env.local` file at the root of this project.
- Go to **Develop**, click on **Authentication** and in the **Sign-in method** tab enable authentication for the app.
- Set the environment variables `SESSION_SECRET_CURRENT` and `SESSION_SECRET_PREVIOUS` in the `.env.local` file. (These are used by [`cookie-session`](https://github.com/expressjs/cookie-session/#secret).]

Install it and run:

Expand Down
16 changes: 16 additions & 0 deletions examples/with-firebase-authentication/components/FirebaseAuth.js
Expand Up @@ -3,6 +3,7 @@ import { useEffect, useState } from 'react'
import StyledFirebaseAuth from 'react-firebaseui/StyledFirebaseAuth'
import firebase from 'firebase/app'
import 'firebase/auth'
import cookie from 'js-cookie'
import initFirebase from '../utils/auth/initFirebase'

// Init the Firebase app.
Expand All @@ -20,6 +21,21 @@ const firebaseAuthConfig = {
],
signInSuccessUrl: '/',
credentialHelper: 'none',
callbacks: {
signInSuccessWithAuthResult: async ({ user }, redirectUrl) => {
// xa is the access token, which can be retrieved through
// firebase.auth().currentUser.getIdToken()
const { uid, email, xa } = user
const userData = {
id: uid,
email,
token: xa,
}
cookie.set('auth', userData, {
expires: 1,
})
},
},
}

const FirebaseAuth = () => {
Expand Down
10 changes: 4 additions & 6 deletions examples/with-firebase-authentication/package.json
Expand Up @@ -7,17 +7,15 @@
"start": "next start"
},
"dependencies": {
"cookie-session": "1.4.0",
"firebase": "^7.6.1",
"firebase-admin": "^8.9.0",
"lodash": "4.17.15",
"js-cookie": "2.2.1",
"next": "latest",
"next-cookies": "2.0.3",
"prop-types": "15.7.2",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-firebaseui": "4.0.0"
},
"devDependencies": {
"dotenv": "8.2.0"
"react-firebaseui": "4.0.0",
"swr": "0.2.2"
}
}
55 changes: 0 additions & 55 deletions examples/with-firebase-authentication/pages/_document.js

This file was deleted.

17 changes: 17 additions & 0 deletions examples/with-firebase-authentication/pages/api/getFood.js
@@ -0,0 +1,17 @@
import { verifyIdToken } from '../../utils/auth/firebaseAdmin'
const favoriteFoods = ['pizza', 'burger', 'chips', 'tortilla']

const getFood = async (req, res) => {
const token = req.headers.token

try {
await verifyIdToken(token)
return res.status(200).json({
food: favoriteFoods[Math.floor(Math.random() * favoriteFoods.length)],
})
} catch (error) {
return res.status(401).send('You are unauthorised')
}
}

export default getFood
37 changes: 0 additions & 37 deletions examples/with-firebase-authentication/pages/api/login.js

This file was deleted.

10 changes: 0 additions & 10 deletions examples/with-firebase-authentication/pages/api/logout.js

This file was deleted.

2 changes: 0 additions & 2 deletions examples/with-firebase-authentication/pages/auth.js
Expand Up @@ -11,6 +11,4 @@ const Auth = () => {
)
}

Auth.propTypes = {}

export default Auth
6 changes: 0 additions & 6 deletions examples/with-firebase-authentication/pages/example.js
Expand Up @@ -14,10 +14,4 @@ const Example = (props) => {
)
}

Example.displayName = 'Example'

Example.propTypes = {}

Example.defaultProps = {}

export default Example
139 changes: 43 additions & 96 deletions examples/with-firebase-authentication/pages/index.js
@@ -1,113 +1,60 @@
import PropTypes from 'prop-types'
import { get } from 'lodash/object'
import useSWR from 'swr'
import Link from 'next/link'
import Router from 'next/router'
import withAuthUser from '../utils/pageWrappers/withAuthUser'
import withAuthUserInfo from '../utils/pageWrappers/withAuthUserInfo'
import logout from '../utils/auth/logout'

const Index = (props) => {
const { AuthUserInfo, data } = props
const AuthUser = get(AuthUserInfo, 'AuthUser', null)
const { favoriteFood } = data
import { useUser } from '../utils/auth/useUser'

const fetcher = (url, token) =>
fetch(url, {
method: 'GET',
headers: new Headers({ 'Content-Type': 'application/json', token }),
credentials: 'same-origin',
}).then((res) => res.json())

const Index = () => {
const { user, logout } = useUser()
const { data, error } = useSWR(
user ? ['/api/getFood', user.token] : null,
fetcher
)

return (
<div>
<p>Hi there!</p>
{!AuthUser ? (
if (!user) {
return (
<>
<p>Hi there!</p>
<p>
You are not signed in.{' '}
<Link href={'/auth'}>
<a>Sign in</a>
</Link>
</p>
) : (
<div>
<p>You're signed in. Email: {AuthUser.email}</p>
<p
style={{
display: 'inlinelock',
color: 'blue',
textDecoration: 'underline',
cursor: 'pointer',
}}
onClick={async () => {
try {
await logout()
Router.push('/auth')
} catch (e) {
console.error(e)
}
}}
>
Log out
</p>
</div>
)}
</>
)
}

return (
<div>
<div>
<p>You're signed in. Email: {user.email}</p>
<p
style={{
display: 'inlinelock',
color: 'blue',
textDecoration: 'underline',
cursor: 'pointer',
}}
onClick={() => logout()}
>
Log out
</p>
</div>
<div>
<Link href={'/example'}>
<a>Another example page</a>
</Link>
</div>
<div>
<div>Your favorite food is {favoriteFood}.</div>
</div>
{error && <div>Failed to fetch food!</div>}
{data && <div>Your favorite food is {data.food}.</div>}
</div>
)
}

// Just an example.
const mockFetchData = async (userId) => ({
user: {
...(userId && {
id: userId,
}),
},
favoriteFood: 'pizza',
})

Index.getInitialProps = async (ctx) => {
// Get the AuthUserInfo object. This is set in `withAuthUser.js`.
// The AuthUserInfo object is available on both the server and client.
const AuthUserInfo = get(ctx, 'myCustomData.AuthUserInfo', null)
const AuthUser = get(AuthUserInfo, 'AuthUser', null)

// You can also get the token (e.g., to authorize a request when fetching data)
// const AuthUserToken = get(AuthUserInfo, 'token', null)

// You can fetch data here.
const data = await mockFetchData(get(AuthUser, 'id'))

return {
data,
}
}

Index.displayName = 'Index'

Index.propTypes = {
AuthUserInfo: PropTypes.shape({
AuthUser: PropTypes.shape({
id: PropTypes.string.isRequired,
email: PropTypes.string.isRequired,
emailVerified: PropTypes.bool.isRequired,
}),
token: PropTypes.string,
}),
data: PropTypes.shape({
user: PropTypes.shape({
id: PropTypes.string,
}).isRequired,
favoriteFood: PropTypes.string.isRequired,
}).isRequired,
}

Index.defaultProps = {
AuthUserInfo: null,
}

// Use `withAuthUser` to get the authed user server-side, which
// disables static rendering.
// Use `withAuthUserInfo` to include the authed user as a prop
// to your component.
export default withAuthUser(withAuthUserInfo(Index))
export default Index

0 comments on commit e7a5264

Please sign in to comment.