Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Examples] remove getInitialProps from with-firebase-authentication #13895

Merged
merged 17 commits into from Jun 11, 2020
Merged
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
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