├── .gitignore
├── README.md
├── components
└── Button.js
├── initAuth.js
├── jsconfig.json
├── next.config.js
├── package.json
├── pages
├── _app.js
├── api
│ ├── login.js
│ └── logout.js
├── auth.js
├── demo.js
└── index.js
├── public
├── favicon.ico
├── panda-bear-gordo.jpg
└── vercel.svg
└── styles
├── Home.module.css
└── globals.css
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
27 | # local env files
28 | .env.local
29 | .env.development.local
30 | .env.test.local
31 | .env.production.local
32 |
33 | # vercel
34 | .vercel
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Next.js Firebase Auth
2 |
3 | Needed ENVIRONMENT VARIABLES:
4 |
5 | `COOKIE_SECRET_CURRENT`
6 | `COOKIE_SECRET_PREVIOUS`
7 | `FIREBASE_PRIVATE_KEY`
--------------------------------------------------------------------------------
/components/Button.js:
--------------------------------------------------------------------------------
1 | export default function Button () {
2 | return
5 | }
--------------------------------------------------------------------------------
/initAuth.js:
--------------------------------------------------------------------------------
1 | import { init } from 'next-firebase-auth'
2 |
3 | const initAuth = () => {
4 | init({
5 | authPageURL: '/auth',
6 | appPageURL: '/',
7 | loginAPIEndpoint: '/api/login', // required
8 | logoutAPIEndpoint: '/api/logout', // required
9 | firebaseAdminInitConfig: {
10 | credential: {
11 | projectId: 'meneadev',
12 | clientEmail: 'firebase-adminsdk-qdn79@meneadev.iam.gserviceaccount.com',
13 | // The private key must not be accesssible on the client side.
14 | privateKey: process.env.FIREBASE_PRIVATE_KEY,
15 | }
16 | },
17 | firebaseClientInitConfig: {
18 | apiKey: "AIzaSyBY-RUdvehNuwOFF6NM_g0_SenOxsfAd8A",
19 | authDomain: "meneadev.firebaseapp.com",
20 | projectId: "meneadev",
21 | storageBucket: "meneadev.appspot.com",
22 | messagingSenderId: "315195767367",
23 | appId: "1:315195767367:web:07ccc6fa7e00ceb13a4f62",
24 | measurementId: "G-N318HL6NF0"
25 | },
26 | cookies: {
27 | name: 'midu-cookie-app', // required
28 | // Keys are required unless you set `signed` to `false`.
29 | // The keys cannot be accessible on the client side.
30 | keys: [
31 | process.env.COOKIE_SECRET_CURRENT,
32 | process.env.COOKIE_SECRET_PREVIOUS,
33 | ],
34 | httpOnly: true,
35 | maxAge: 12 * 60 * 60 * 24 * 1000, // twelve days
36 | overwrite: true,
37 | path: '/',
38 | sameSite: 'strict',
39 | secure: true, // set this to false in local (non-HTTPS) development
40 | signed: true,
41 | },
42 | })
43 | }
44 |
45 | export default initAuth
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "./"
4 | }
5 | }
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | images: {
3 | domains: ['avatars.githubusercontent.com'],
4 | },
5 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nextjs-firebase-auth",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start"
9 | },
10 | "dependencies": {
11 | "firebase": "^8.6.8",
12 | "firebase-admin": "^9.9.0",
13 | "next": "11.0.1",
14 | "next-firebase-auth": "0.13.1",
15 | "react": "17.0.2",
16 | "react-dom": "17.0.2",
17 | "react-firebaseui": "^5.0.2"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/pages/_app.js:
--------------------------------------------------------------------------------
1 | import '../styles/globals.css'
2 | import initAuth from '../initAuth'
3 |
4 | initAuth()
5 |
6 | function MyApp({ Component, pageProps }) {
7 | return
8 | }
9 |
10 | export default MyApp
11 |
--------------------------------------------------------------------------------
/pages/api/login.js:
--------------------------------------------------------------------------------
1 | import { setAuthCookies } from "next-firebase-auth"
2 | import initAuth from "initAuth.js"
3 |
4 | initAuth()
5 |
6 | export default async function handler (req, res) {
7 | try {
8 | await setAuthCookies(req, res)
9 | } catch (e) {
10 | console.error(e)
11 | return res.status(500).json({ error: 'Unexpected error.' })
12 | }
13 | return res.status(200).json({ success: true })
14 | }
15 |
--------------------------------------------------------------------------------
/pages/api/logout.js:
--------------------------------------------------------------------------------
1 | import { unsetAuthCookies } from 'next-firebase-auth'
2 | import initAuth from 'initAuth.js' // the module you created above
3 |
4 | initAuth()
5 |
6 | export default async function handler (req, res) {
7 | try {
8 | await unsetAuthCookies(req, res)
9 | } catch (e) {
10 | return res.status(500).json({ error: 'Unexpected error.' })
11 | }
12 | return res.status(200).json({ success: true })
13 | }
--------------------------------------------------------------------------------
/pages/auth.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react'
2 | import firebase from 'firebase/app'
3 | import 'firebase/auth'
4 | import StyledFirebaseAuth from 'react-firebaseui/StyledFirebaseAuth'
5 | import { AuthAction, withAuthUser } from 'next-firebase-auth'
6 |
7 | const firebaseAuthConfig = {
8 | signInFlow: 'popup',
9 | // Auth providers
10 | // https://github.com/firebase/firebaseui-web#configure-oauth-providers
11 | signInOptions: [
12 | {
13 | provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
14 | requireDisplayName: false,
15 | },
16 | {
17 | provider: firebase.auth.GithubAuthProvider.PROVIDER_ID,
18 | }
19 | ],
20 | signInSuccessUrl: '/',
21 | credentialHelper: 'none',
22 | callbacks: {
23 | // https://github.com/firebase/firebaseui-web#signinsuccesswithauthresultauthresult-redirecturl
24 | signInSuccessWithAuthResult: () =>
25 | // Don't automatically redirect. We handle redirecting based on
26 | // auth state in withAuthComponent.js.
27 | false,
28 | },
29 | }
30 |
31 | function Auth () {
32 | const [renderAuth, setRenderAuth] = useState(false)
33 | useEffect(() => {
34 | setRenderAuth(true)
35 | }, [])
36 |
37 | return (
38 |
39 | {renderAuth ? (
40 |
44 | ) : null}
45 |
46 | )
47 | }
48 |
49 | export default withAuthUser({
50 | whenAuthed: AuthAction.REDIRECT_TO_APP
51 | })(Auth)
--------------------------------------------------------------------------------
/pages/demo.js:
--------------------------------------------------------------------------------
1 | import {
2 | AuthAction,
3 | useAuthUser,
4 | withAuthUser, // High Order Component -> función que devuelve un componente
5 | withAuthUserTokenSSR, // High Order Function -> función que devuelve una función
6 | } from 'next-firebase-auth'
7 | import firebase from 'firebase'
8 | import Image from 'next/image'
9 | import Button from 'components/Button.js'
10 | import pandaImageSrc from 'public/panda-bear-gordo.jpg'
11 |
12 | const Demo = () => {
13 | const user = useAuthUser()
14 | console.log({user})
15 |
16 | return (
17 |
18 |
19 |
20 | Panda bear gordito y acolchadito
21 |
22 |
23 |
24 |
25 |
Your email is {user.email ? user.email : "unknown"}.
26 |
27 |
28 | )
29 | }
30 |
31 | // Note that this is a higher-order function.
32 | export const getServerSideProps = withAuthUserTokenSSR({
33 | whenUnauthed: AuthAction.REDIRECT_TO_LOGIN
34 | })(() => {
35 | return {
36 | props: {}
37 | }
38 | })
39 |
40 | export default withAuthUser({
41 | whenUnauthedAfterInit: AuthAction.REDIRECT_TO_LOGIN
42 | })(Demo)
--------------------------------------------------------------------------------
/pages/index.js:
--------------------------------------------------------------------------------
1 | import { withAuthUser, useAuthUser } from 'next-firebase-auth'
2 | import Head from 'next/head'
3 | import Image from 'next/image'
4 | import styles from '../styles/Home.module.css'
5 |
6 | function Home() {
7 | const user = useAuthUser()
8 | console.log(user.id)
9 |
10 | return (
11 |
12 |
Estoy haciendo Auth para Next.js con Firebase 👋
13 |
14 | )
15 | }
16 |
17 | export default withAuthUser()(Home)
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midudev/next-firebase-auth/9b6c99a2adb177aace439d14118536373cf14344/public/favicon.ico
--------------------------------------------------------------------------------
/public/panda-bear-gordo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/midudev/next-firebase-auth/9b6c99a2adb177aace439d14118536373cf14344/public/panda-bear-gordo.jpg
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles/Home.module.css:
--------------------------------------------------------------------------------
1 | .container {
2 | min-height: 100vh;
3 | padding: 0 0.5rem;
4 | display: flex;
5 | flex-direction: column;
6 | justify-content: center;
7 | align-items: center;
8 | height: 100vh;
9 | }
10 |
11 | .main {
12 | padding: 5rem 0;
13 | flex: 1;
14 | display: flex;
15 | flex-direction: column;
16 | justify-content: center;
17 | align-items: center;
18 | }
19 |
20 | .footer {
21 | width: 100%;
22 | height: 100px;
23 | border-top: 1px solid #eaeaea;
24 | display: flex;
25 | justify-content: center;
26 | align-items: center;
27 | }
28 |
29 | .footer a {
30 | display: flex;
31 | justify-content: center;
32 | align-items: center;
33 | flex-grow: 1;
34 | }
35 |
36 | .title a {
37 | color: #0070f3;
38 | text-decoration: none;
39 | }
40 |
41 | .title a:hover,
42 | .title a:focus,
43 | .title a:active {
44 | text-decoration: underline;
45 | }
46 |
47 | .title {
48 | margin: 0;
49 | line-height: 1.15;
50 | font-size: 4rem;
51 | }
52 |
53 | .title,
54 | .description {
55 | text-align: center;
56 | }
57 |
58 | .description {
59 | line-height: 1.5;
60 | font-size: 1.5rem;
61 | }
62 |
63 | .code {
64 | background: #fafafa;
65 | border-radius: 5px;
66 | padding: 0.75rem;
67 | font-size: 1.1rem;
68 | font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
69 | Bitstream Vera Sans Mono, Courier New, monospace;
70 | }
71 |
72 | .grid {
73 | display: flex;
74 | align-items: center;
75 | justify-content: center;
76 | flex-wrap: wrap;
77 | max-width: 800px;
78 | margin-top: 3rem;
79 | }
80 |
81 | .card {
82 | margin: 1rem;
83 | padding: 1.5rem;
84 | text-align: left;
85 | color: inherit;
86 | text-decoration: none;
87 | border: 1px solid #eaeaea;
88 | border-radius: 10px;
89 | transition: color 0.15s ease, border-color 0.15s ease;
90 | width: 45%;
91 | }
92 |
93 | .card:hover,
94 | .card:focus,
95 | .card:active {
96 | color: #0070f3;
97 | border-color: #0070f3;
98 | }
99 |
100 | .card h2 {
101 | margin: 0 0 1rem 0;
102 | font-size: 1.5rem;
103 | }
104 |
105 | .card p {
106 | margin: 0;
107 | font-size: 1.25rem;
108 | line-height: 1.5;
109 | }
110 |
111 | .logo {
112 | height: 1em;
113 | margin-left: 0.5rem;
114 | }
115 |
116 | @media (max-width: 600px) {
117 | .grid {
118 | width: 100%;
119 | flex-direction: column;
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/styles/globals.css:
--------------------------------------------------------------------------------
1 | html,
2 | body {
3 | padding: 0;
4 | margin: 0;
5 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
6 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
7 | }
8 |
9 | a {
10 | color: inherit;
11 | text-decoration: none;
12 | }
13 |
14 | * {
15 | box-sizing: border-box;
16 | }
17 |
--------------------------------------------------------------------------------