46
loading...
This website collects cookies to deliver better user experience
npx express-generator --no-view account-service
cd account-service
npm install
npm install --save jsonwebtoken passport passport-google-oauth cors
var port = normalizePort(process.env.PORT || '5000');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const cors = require('cors');
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth').OAuth2Strategy;
const indexRouter = require('./routes/index');
const app = express();
// This is here for our client side to be able to talk to our server side. you may want to be less permissive in production and define specific domains.
app.use(cors());
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(passport.initialize());
app.use(passport.session());
app.use('/', indexRouter);
passport.serializeUser(function(user, cb) {
cb(null, user);
});
passport.deserializeUser(function(obj, cb) {
cb(null, obj);
});
passport.use(new GoogleStrategy({
clientID: 'your-google-client-id',
clientSecret: 'your-google-client-secret',
callbackURL: "http://localhost:5000/auth/google/callback"
},
function(accessToken, refreshToken, profile, done) {
// here you can create a user in the database if you want to
return done(null, profile);
}
));
module.exports = app;
const express = require('express');
const router = express.Router();
const passport = require('passport');
const jwt = require('jsonwebtoken');
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
const TOKEN_SECRET = 'SECRET';
router.get('/auth/google',
passport.authenticate('google', { scope : ['profile', 'email'] }));
router.get('/auth/google/callback',
passport.authenticate('google', { failureRedirect: '/error' }),
function(req, res) {
const token = jwt.sign({ id: req.user.sub, name: req.user.name }, TOKEN_SECRET, {
expiresIn: 60 * 60,
});
res.cookie('auth', token, { httpOnly: true });
res.redirect('http://localhost:3000/');
});
module.exports = router;
httpOnly
cookie, so that it is not accessible to javascript code (which is good in terms of security). You’ll soon see how this works on the client end.npx create-react-app auth-strategies-client
cd auth-strategies-client/
yarn add axios
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<a href="http://localhost:5000/auth/google">Sign in with Google</a>
</header>
</div>
);
}
export default App;
npx express-generator --no-view greetings-service
cd greetings-service
npm install
npm install --save passport passport-jwt cors
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const indexRouter = require('./routes/index');
const app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
module.exports = app;
var port = normalizePort(process.env.PORT || '5001');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const cors = require('cors');
const indexRouter = require('./routes/index');
const app = express();
app.use(cors({ credentials: true, origin: 'http://localhost:3000' }));
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
const passport = require('passport');
const JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
app.use(passport.initialize());
app.use(passport.session());
app.use('/', indexRouter);
const cookieExtractor = function(req) {
let token = null;
if (req && req.cookies)
{
token = req.cookies['auth'];
}
return token;
};
const TOKEN_SECRET = 'SECRET';
const opts = {
jwtFromRequest: ExtractJwt.fromExtractors([cookieExtractor]),
secretOrKey: TOKEN_SECRET,
};
passport.use(
'jwt',
new JwtStrategy(opts, (jwt_payload, done) => {
try {
console.log('jwt_payload', jwt_payload);
done(null, jwt_payload);
} catch (err) {
done(err);
}
}),
);
module.exports = app;
cookieExtractor
is responsible for reading the token from the httpOnly
cookie we created earlier and will be passed along with the request (more on that later).JwtStrategy
, which is responsible for providing us with the jwt_payload
. We could be fetching more info about the user from the database if we were to add a database, but for the sake of simplicity, I decided not to.const express = require('express');
const router = express.Router();
const passport = require('passport');
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.get('/greetme', (req, res, next) => {
passport.authenticate('jwt', { session: false }, (err, user, info) => {
if (err) {
console.log('error is', err);
res.status(500).send('An error has occurred, we cannot greet you at the moment.');
}
else {
res.send({ success: true, fullName: `${user.name.givenName} ${user.name.familyName}` })
}
})(req, res, next);
});
module.exports = router;
npm start
import React, { useState } from 'react';
import axios from "axios";
import logo from './logo.svg';
import './App.css';
function App() {
const [name, setName] = useState('');
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<a href="http://localhost:5000/auth/google">Sign in with Google</a>
<br />
<button onClick={async () => {
const result = await axios.get('http://localhost:5001/greetme', {
withCredentials: true
});
setName(result.data.fullName);
}}>Greet me please</button>
{name && <span>{`Hi, ${name}`}</span>}
</header>
</div>
);
}
export default App;
withCredentials
: true – that is what makes the cookies pass alongside our request, for the server to extract.