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.

2 changes: 1 addition & 1 deletion examples/with-firebase-authentication/README.md
Original file line number Diff line number Diff line change
@@ -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
16 changes: 16 additions & 0 deletions examples/with-firebase-authentication/components/FirebaseAuth.js
Original file line number Diff line number Diff line change
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
4 changes: 2 additions & 2 deletions examples/with-firebase-authentication/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
"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",
Expand Down
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,4 @@ const Example = (props) => {
)
}

Example.displayName = 'Example'

Example.propTypes = {}

Example.defaultProps = {}

export default Example
165 changes: 76 additions & 89 deletions examples/with-firebase-authentication/pages/index.js
Original file line number Diff line number Diff line change
@@ -1,113 +1,100 @@
import PropTypes from 'prop-types'
import { get } from 'lodash/object'
import cookies from 'next-cookies'
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

return (
<div>
<p>Hi there!</p>
{!AuthUser ? (
const { data } = props
if (!data)
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>
{data && (
<>
<div>
<p>You're signed in. Email: {data.user.email}</p>
<p
style={{
display: 'inlinelock',
color: 'blue',
textDecoration: 'underline',
cursor: 'pointer',
}}
onClick={async () => {
try {
logout()
Router.push('/auth')
} catch (e) {
console.error(e)
}
}}
>
Log out
</p>
</div>
<div>
<Link href={'/example'}>
<a>Another example page</a>
</Link>
</div>
<div>
<div>Your favorite food is {data.food}.</div>
</div>
</>
)}
<div>
<Link href={'/example'}>
<a>Another example page</a>
</Link>
</div>
<div>
<div>Your favorite food is {favoriteFood}.</div>
</div>
</div>
)
}

// Just an example.
const mockFetchData = async (userId) => ({
user: {
...(userId && {
id: userId,
}),
},
favoriteFood: 'pizza',
})
export const getServerSideProps = async (context) => {
const { auth } = cookies(context)
if (!auth) {
return {
props: {
data: null,
},
}
}
const { id, email, token } = auth

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)
try {
const response = await fetch('http://localhost:3000/api/getFood', {
method: 'GET',
// eslint-disable-next-line no-undef
headers: new Headers({ 'Content-Type': 'application/json', token }),
credentials: 'same-origin',
})

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

// You can fetch data here.
const data = await mockFetchData(get(AuthUser, 'id'))
const data = {
user: {
id,
email,
},
food,
}

return {
data,
return { props: { data } }
} catch (error) {
console.log(error)
}
}
todortotev marked this conversation as resolved.
Show resolved Hide resolved

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,
return {
props: {
data: '1',
},
}
}

// 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
Loading