slug |
---|
/ |
In order to quickly get everything up and running locally, we'll use docker compose[^1].
-
create a
docker-compose.yml
file in your project directory -
Copy and paste the configuration below. Our compose file contains three services:
- Postgres[^2] - Our main data store.
- MailHog[^3] - Used for local development, mailhog.
- Vulpo Auth - The authentication server.
version: '2'
services:
postgres:
image: postgres
container_name: vulpo_pg
restart: always
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
ports:
- 5432:5432
volumes:
- postgres-data:/var/lib/postgres
mailhog:
image: mailhog/mailhog
container_name: vulpo_mailhog
restart: always
ports:
- 1025:1025
- 8025:8025
volumes:
- mailhog-data:/var/lib/mailhog
vulpo:
image: riezler/vulpo_auth
container_name: vulpo_auth_server
restart: always
environment:
- VULPO_SECRETS_PASSPHRASE=password
- VULPO_DATABASE_URL=postgres://postgres:postgres@vulpo_pg:5432/auth
- VULPO_DB_LOG_LEVEL=Off
# this should only be used for local development
# in production you should run migrations separatly
# before you run your container
- VULPO_RUN_MIGRATIONS=true
- VULPO_ADMIN_EMAIL=admin@vulpo.dev
- VULPO_ADMIN_PASSWORD=password
- VULPO_ADMIN_HOST=http://localhost:8000
# this will use an insecure smtp connection and should
# only be used for local development
- VULPO_MAIL_LOCALHOST=vulpo_mailhog
ports:
- 8000:8000
depends_on:
- postgres
- mailhog
volumes:
postgres-data:
mailhog-data:
- Go to localhost:8000 to sign in to your dashboard. Email:
admin@vulpo.dev
, Password:password
. - Create your first project.
-
Enable Email and Password Sign In/Up
- Go to the admin dashboard
- Got to your project → Sign In Methods
- Select Sign In, Sign Up and Email and Password
-
Create a new React[^4] project: Create React App
npx create-react-app my-app
cd my-app
npm start
- Install the vulpo auth packages
npm install @vulpo-dev/auth-ui react-router-dom
- Setup the Auth Client:
import React from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom'
// The Vulpo Auth packages
import { Auth as AuthCtx } from '@vulpo-dev/auth-react'
import { Auth } from '@vulpo-dev/auth-sdk'
import '@vulpo-dev/auth-ui/styles.css' // Default styles
let AuthClient = Auth.create({
// Got to localhost:8000 -> Your Project -> Settings
project: '<project-id>',
baseURL: 'http://localhost:8000'
})
let container = document.getElementById('root')
let root = createRoot(container) // createRoot(container!) if you use TypeScript
root.render(
<React.StrictMode>
<BrowserRouter>
{/* Wrap your application inside the Auth Context */}
<AuthCtx.Provider value={AuthClient}>
<App />
</AuthCtx.Provider>
</BrowserRouter>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
- Update your App.js component to make use of the AuthShell
import React from 'react'
import { Route, Link } from 'react-router-dom'
import {
AuthShell,
useUser,
PrivateRoute,
PublicRoute
} from '@vulpo-dev/auth-ui'
let App = () => {
return (
<AuthShell>
{/* Routes are by default private */}
<Route path='private' element={<WithUser />} />
{/* You can also be more explicit */}
<PrivateRoute path='user' element={<WithUser />} />
{/* A PublicRoute will be accessible by everyone */}
<PublicRoute path='/' element={
<div>
<h1>Public Page</h1>
<Link to="private">Private Route: Route</Link>
<Link to="user">Private Route: PrivateRoute</Link>
</div>
}/>
</AuthShell>
)
}
export default App
let WithUser = () => {
let user = useUser()
return (
<div>
<h1>With User </h1>
<Link to="page">Page</Link>
<pre>{JSON.stringify(user, null, 2)}</pre>
</div>
)
}
- Congrats, you have completed the set up!
The web SDK provides a withToken
method that manages your token life cycle.
Given the WithUser
component we have set up in the previous step, import the withAuth
hook to get access to the web SDK.
import { useUser, useAuth } from '@vulpo-dev/auth-react'
let WithUser = () => {
let user = useUser()
let auth = useAuth()
async function callApi() {
try {
let res = await auth.withToken((token) => {
return fetch('your.api-server.com', {
headers: {
'Authorization': `Bearer ${token}`,
}
})
})
console.log(await res.text())
} catch(err) {
console.log({ err })
}
}
return (
<div>
<h1>With User </h1>
<Link to="page">Page</Link>
<button onClick={callApi}>Call API</button>
<pre>{JSON.stringify(user, null, 2)}</pre>
</div>
)
}
All that's left to do is now to verify the JWT on the server. Here is an example of how you would do that using node[^5], express[^6] and passport[^7]. In order to verify the JWT, we need to grab the projects
public key, go to: Dashboard -> Your Project -> Settings -> Scroll to the bottom
.
let express = require('express')
let cors = require('cors')
let fs = require('fs')
let passport = require('passport')
let JwtStrategy = require('passport-jwt').Strategy
let ExtractJwt = require('passport-jwt').ExtractJwt
// This is the public key that you can find in the admin dashboard
let publicKey = fs.readFileSync('../key.pub', { encoding: 'utf8' })
let opts = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: publicKey,
}
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
done(null, jwt_payload)
}))
let app = express()
app.use(cors())
app.get('/',
passport.authenticate('jwt', { session: false }),
(req, res) => { res.json(req.user) }
)
app.listen(8001, () => {
console.log('Node Passport server is running')
})
[^1] https://docs.docker.com/compose/gettingstarted/
[^2] https://www.postgresql.org/
[^3] https://github.com/mailhog/MailHog
[^4] https://reactjs.org
[^5] https://nodejs.org
[^6] https://expressjs.com/
[^7] https://www.passportjs.org/