SlideShare a Scribd company logo
1 of 128
Download to read offline
LA SÉCURITÉ,
JE M’EN FICHE
(VOUS DEVRIEZ AUSSI)
LA SÉCURITÉ,
JE M’EN FICHE
(VOUS DEVRIEZ AUSSI)
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
QUI SUIS-JE?
@joel__lord
joellord
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
INTRODUCTION À OAUTH
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
INTRODUCTION À OAUTH
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
INTRODUCTION À OAUTH
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
INTRODUCTION À OAUTH
INTRODUCTION À OAUTH
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
INTRODUCTION À OAUTH
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
INTRODUCTION À OAUTH
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
INTRODUCTION À OAUTH
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
INTRODUCTION À OAUTH
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
INTRODUCTION À OAUTH
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
INTRODUCTION À OAUTH
MAIS POURQUOI?
DÉLÉGATION!
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
APPLICATIONS TRADITIONNELLES
▸ Le navigateur demande la page
d’accueil
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
APPLICATIONS TRADITIONNELLES
▸ Le navigateur demande la page
d’accueil
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
APPLICATIONS TRADITIONNELLES
▸ Le navigateur demande la page
d’accueil
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
APPLICATIONS TRADITIONNELLES
▸ Le navigateur demande la page
d’accueil
▸ Le serveur valide l’usager dans la
base de données
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
APPLICATIONS TRADITIONNELLES
▸ Le navigateur demande la page
d’accueil
▸ Le serveur valide l’usager dans la
base de données
👍
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
APPLICATIONS TRADITIONNELLES
▸ Le navigateur demande la page
d’accueil
▸ Le serveur valide l’usager dans la
base de données
▸ Une session est créée et un Cookie
est envoyé
👍
"
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
POURTANT, ÇA FONCTIONNE, NON?
▸ Plusieurs plateformes tentent de se
connecter
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
POURTANT, ÇA FONCTIONNE, NON?
▸ Plusieurs plateformes tentent de se
connecter
▸ Code étroitement couplé
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
POURTANT, ÇA FONCTIONNE, NON?
▸ Plusieurs plateformes tentent de se
connecter
▸ Code étroitement couplé
▸ Partager un mot de passe pour se
connecter à un tier-parti (ugh!)
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
POURTANT, ÇA FONCTIONNE, NON?
▸ Plusieurs plateformes tentent de se
connecter
▸ Code étroitement couplé
▸ Partager un mot de passe pour se
connecter à un tier-parti (ugh!)
▸ Les utilisateurs ont déjà des
centaines de comptes, ce qui
mène à la réutilisation des mots de
passe et un bas taux de conversion
OAUTH GRANTS
LA SÉCURITÉ, JE M’EN FICHE
(VOUS DEVRIEZ AUSSI)
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
AUTHORIZATION CODE
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
AUTHORIZATION CODE
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
AUTHORIZATION CODE
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
AUTHORIZATION CODE
👍
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
AUTHORIZATION CODE
👍
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
AUTHORIZATION CODE
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
AUTHORIZATION CODE
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
AUTHORIZATION CODE
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
AUTHORIZATION CODE
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
AUTHORIZATION CODE
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
AUTHORIZATION CODE
⛔
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
AUTHORIZATION CODE
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
AUTHORIZATION CODE
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
IMPLICIT GRANT
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
IMPLICIT GRANT
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
IMPLICIT GRANT
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
IMPLICIT GRANT
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
IMPLICIT GRANT
👍
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
IMPLICIT GRANT
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
IMPLICIT GRANT
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
IMPLICIT GRANT
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
IMPLICIT GRANT
👍
TOKENS 101
LA SÉCURITÉ, JE M’EN FICHE
(VOUS DEVRIEZ AUSSI)
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
TOKENS
▸ Access Token
▸ Autorise l’accès à une
resources
▸ Contrôle les accès à un API
▸ Courte vie
▸ Refresh Tokens
▸ Permet d’obtenir un
Access Token
▸ Longue durée de vie
▸ Peut être révoqué
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
TOKENS
▸ Refresh Tokens
▸ Permet d’obtenir un Access
Token
▸ Longue durée de vie
▸ Peut être révoqué
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
TOKENS
▸ Refresh Tokens
▸ Permet d’obtenir un Access
Token
▸ Longue durée de vie
▸ Peut être révoqué
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
TOKENS
▸ WS Federated
▸ SAML
▸ Sur mesure
▸ …
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
TOKENS
▸ WS Federated
▸ SAML
▸ Sur mesure
▸ JWT
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
JSON WEB TOKENS
eyJhbGciOiJIUzI1NiIsInR5cC
I6IkpXVCJ9.eyJzdWIiOiIxMj
M0NTY3ODkwIiwibmFtZSI6I
kpvZWwgTG9yZCIsImFkbWl
uIjp0cnVlLCJzY29wZSI6InBv
c3RzOnJlYWQgcG9zdHM6
d3JpdGUifQ.XesR-
pKdlscHfUwoKvHnACqfpe2
ywJ6t1BJKsq9rEcg
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
JSON WEB TOKENS
▸ Entête (Header)
▸ Charge (Payload)
▸ Signature
eyJhbGciOiJIUzI1NiIsInR5cC
I6IkpXVCJ9.eyJzdWIiOiIxMj
M0NTY3ODkwIiwibmFtZSI6I
kpvZWwgTG9yZCIsImFkbWl
uIjp0cnVlLCJzY29wZSI6InBv
c3RzOnJlYWQgcG9zdHM6
d3JpdGUifQ.XesR-
pKdlscHfUwoKvHnACqfpe2
ywJ6t1BJKsq9rEcg
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
JSON WEB TOKENS
▸ Entête (Header) eyJhbGciOiJIUzI1NiIsInR5cC
I6IkpXVCJ9.eyJzdWIiOiIxMj
M0NTY3ODkwIiwibmFtZSI6I
kpvZWwgTG9yZCIsImFkbWl
uIjp0cnVlLCJzY29wZSI6InBv
c3RzOnJlYWQgcG9zdHM6
d3JpdGUifQ.XesR-
pKdlscHfUwoKvHnACqfpe2
ywJ6t1BJKsq9rEcg
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
JSON WEB TOKENS
▸ Entête (Header) eyJhbGciOiJIUzI1NiIsInR5cC
I6IkpXVCJ9
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
JSON WEB TOKENS
▸ Entête (Header) atob(‘eyJhbGciOiJIUzI1NiIsI
nR5cCI6IkpXVCJ9’);
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
JSON WEB TOKENS
▸ Entête (Header) {
"alg": "HS256",
"typ": "JWT"
}
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
JSON WEB TOKENS
▸ Charge (Payload) eyJhbGciOiJIUzI1NiIsInR5cC
I6IkpXVCJ9.eyJzdWIiOiIxMj
M0NTY3ODkwIiwibmFtZSI6I
kpvZWwgTG9yZCIsImFkbWl
uIjp0cnVlLCJzY29wZSI6InBv
c3RzOnJlYWQgcG9zdHM6
d3JpdGUifQ.XesR-
pKdlscHfUwoKvHnACqfpe2
ywJ6t1BJKsq9rEcg
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
JSON WEB TOKENS
▸ Charge (Payload) eyJzdWIiOiIxMjM0NTY3OD
kwIiwibmFtZSI6IkpvZWwgT
G9yZCIsImFkbWluIjp0cnVlL
CJzY29wZSI6InBvc3RzOnJl
YWQgcG9zdHM6d3JpdGUi
fQ
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
JSON WEB TOKENS
▸ Charge (Payload) atob(‘eyJzdWIiOiIxMjM0NT
Y3ODkwIiwibmFtZSI6IkpvZ
WwgTG9yZCIsImFkbWluIjp
0cnVlLCJzY29wZSI6InBvc3R
zOnJlYWQgcG9zdHM6d3J
pdGUifQ’);
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
JSON WEB TOKENS
▸ Charge (Payload) {
"sub": "1234567890",
"name": "Joel Lord",
"admin": true,
"scope": "posts:read
posts:write"
}
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
JSON WEB TOKENS
▸ Signature XesR-
pKdlscHfUwoKvHnACqfpe2
ywJ6t1BJKsq9rEcg
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
JSON WEB TOKENS
▸ Signature hmacsha256(
`${header}.${payload}`,
SECRET_KEY
);
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
JSON WEB TOKENS
Image: https://jwt.io
UN PEU DE CODE
Serveur Auth API
var express = require('express');
var Webtask = require('webtask-tools');
var bodyParser = require('body-parser');
var randopeep = require("randopeep");
var jwt = require("jsonwebtoken");
var app = express();
var users = [
{id: 1, username: "joellord", password: "joellord"},
{id: 2, username: "guest", password: "guest"}
];
app.use(bodyParser.json());
app.post("/login", function(req, res) {
if (!req.body.username || !req.body.password) return
res.status(400).send("Need username and password");
var user = users.find(function(u) {
return u.username === req.body.username && u.password ===
req.body.password;
});
if (!user) return res.status(401).send("User not found");
var token = jwt.sign({
sub: user.id,
scope: "api:read",
username: user.username
}, "mysupersecret", {expiresIn: "10 minutes"});
var express = require('express');
var Webtask = require('webtask-tools');
var bodyParser = require('body-parser');
var jwt = require("jsonwebtoken");
var app = express();
var users = [
{id: 1, username: "joellord", password: "joellord"},
{id: 2, username: "guest", password: "guest"}
];
app.use(bodyParser.urlencoded());
app.get("/login", function(req, res) {
var loginForm = "<form method='post'><input type=hidden
name=callback value='" + req.query.callback + "'><input type=text
name=username /><input type=text name=password /><input
type=submit></form>";
res.status(200).send(loginForm);
});
app.post("/login", function(req, res) {
if (!req.body.username || !req.body.password) return
res.status(400).send("Need username and password");
var user = users.find(function(u) {
return u.username === req.body.username && u.password ===
req.body.password;
});
if (!user) return res.status(401).send("User not found");
@joel__lord
#WAQ19
Serveur Auth
var express = require('express');
var bodyParser = require('body-parser');
var jwt = require("jsonwebtoken");
var app = express();
// ...
@joel__lord
#WAQ19
Serveur Auth
var express = require('express');
var bodyParser = require('body-parser');
var jwt = require("jsonwebtoken");
var app = express();
// ...
@joel__lord
#WAQ19
Serveur Auth
var express = require('express');
var bodyParser = require('body-parser');
var jwt = require("jsonwebtoken");
var app = express();
// ...
@joel__lord
#WAQ19
Serveur Auth
var express = require('express');
var bodyParser = require('body-parser');
var jwt = require("jsonwebtoken");
var app = express();
// ...
@joel__lord
#WAQ19
Serveur Auth
// Requires ...
var users = [
{id: 1, username: "joellord", password:
"joellord"},
{id: 2, username: "guest", password: "guest"}
];
@joel__lord
#WAQ19
Serveur Auth
// Requires ...
var users = [...];
app.use(bodyParser.urlencoded());
app.post("/login", function(req, res) {
// POST for login
});
app.get('*', function (req, res) {
res.sendStatus(404);
});
@joel__lord
#WAQ19
Serveur Auth
// Requires ...
var users = [...];
app.use(bodyParser.urlencoded());
app.post("/login", function(req, res) {
// POST for login
});
app.get('*', function (req, res) {
res.sendStatus(404);
});
@joel__lord
#WAQ19
Serveur Auth
app.post("/login", function(req, res) {
// POST for login
if (!req.body.username || !req.body.password)
return res.status(400).send("Need username and password");
var user = users.find(function(u) {
return u.username === req.body.username && u.password === req.body.password;
});
if (!user) return res.status(401).send("User not found");
var token = jwt.sign({
sub: user.id,
scope: "api:read",
username: user.username
}, "mysupersecret", {expiresIn: "10 minutes"});
res.redirect(req.body.callback + "#access_token=" + token);
});
@joel__lord
#WAQ19
Serveur Auth
app.post("/login", function(req, res) {
// POST for login
if (!req.body.username || !req.body.password)
return res.status(400).send("Need username and password");
var user = users.find(function(u) {
return u.username === req.body.username && u.password === req.body.password;
});
if (!user) return res.status(401).send("User not found");
var token = jwt.sign({
sub: user.id,
scope: "api:read",
username: user.username
}, "mysupersecret", {expiresIn: "10 minutes"});
res.redirect(req.body.callback + "#access_token=" + token);
});
@joel__lord
#WAQ19
Serveur Auth
app.post("/login", function(req, res) {
// POST for login
if (!req.body.username || !req.body.password)
return res.status(400).send("Need username and password");
var user = users.find(function(u) {
return u.username === req.body.username && u.password === req.body.password;
});
if (!user) return res.status(401).send("User not found");
var token = jwt.sign({
sub: user.id,
scope: "api:read",
username: user.username
}, "mysupersecret", {expiresIn: "10 minutes"});
res.redirect(req.body.callback + "#access_token=" + token);
});
@joel__lord
#WAQ19
Serveur Auth
app.post("/login", function(req, res) {
// POST for login
if (!req.body.username || !req.body.password)
return res.status(400).send("Need username and password");
var user = users.find(function(u) {
return u.username === req.body.username && u.password === req.body.password;
});
if (!user) return res.status(401).send("User not found");
var token = jwt.sign({
sub: user.id,
scope: "api:read",
username: user.username
}, "mysupersecret", {expiresIn: "10 minutes"});
res.redirect(req.body.callback + "#access_token=" + token);
});
@joel__lord
#WAQ19
Serveur Auth
// Requires ...
var users = [...];
app.use(bodyParser.urlencoded());
app.post("/login", function(req, res) {
// POST for login
});
app.get('*', function (req, res) {
res.sendStatus(404);
});
app.listen(8080, () => console.log("Auth server running on
8080"));}
@joel__lord
#WAQ19
API
var express = require('express');
var bodyParser = require('body-parser');
var randopeep = require("randopeep");
var expressjwt = require("express-jwt");
var app = express();
@joel__lord
#WAQ19
API
var express = require('express');
var bodyParser = require('body-parser');
var randopeep = require("randopeep");
var expressjwt = require("express-jwt");
var app = express();
@joel__lord
#WAQ19
API
var express = require('express');
var bodyParser = require('body-parser');
var randopeep = require("randopeep");
var expressjwt = require("express-jwt");
var app = express();
@joel__lord
#WAQ19
API
var express = require('express');
var bodyParser = require('body-parser');
var randopeep = require("randopeep");
var expressjwt = require("express-jwt");
var app = express();
@joel__lord
#WAQ19
API
var express = require('express');
var bodyParser = require('body-parser');
var randopeep = require("randopeep");
var expressjwt = require("express-jwt");
var app = express();
@joel__lord
#WAQ19
API
// Requires ...
var jwtCheck = expressjwt({
secret: "mysupersecret"
});
@joel__lord
#WAQ19
API
// Requires and config ...
app.get("/headline", function(req, res) {
// Unprotected
res.status(200).send(randopeep.clickbait.headline());
});
app.get("/protected/headline", jwtCheck, function(req, res) {
// Protected
res.status(200).send(randopeep.clickbait.headline("Joel Lord"));
});
app.get('*', function (req, res) {
res.sendStatus(404);
});
@joel__lord
#WAQ19
API
// Requires and config ...
app.get("/headline", function(req, res) {
// Unprotected
res.status(200).send(randopeep.clickbait.headline());
});
app.get("/protected/headline", jwtCheck, function(req, res) {
// Protected
res.status(200).send(randopeep.clickbait.headline("Joel Lord"));
});
app.get('*', function (req, res) {
res.sendStatus(404);
});
@joel__lord
#WAQ19
API
// Requires and config ...
app.get("/headline", function(req, res) {
// Unprotected
res.status(200).send(randopeep.clickbait.headline());
});
app.get("/protected/headline", jwtCheck, function(req, res) {
// Protected
res.status(200).send(randopeep.clickbait.headline("Joel Lord"));
});
app.get('*', function (req, res) {
res.sendStatus(404);
});
@joel__lord
#WAQ19
API
// Requires and config ...
app.get("/headline", function(req, res) {
// Unprotected
res.status(200).send(randopeep.clickbait.headline());
});
app.get("/protected/headline", jwtCheck, function(req, res) {
// Protected
res.status(200).send(randopeep.clickbait.headline("Joel Lord"));
});
app.get('*', function (req, res) {
res.sendStatus(404);
});
@joel__lord
#WAQ19
API
// Requires and config ...
app.get("/headline", function(req, res) {
// Unprotected
});
app.get("/protected/headline", jwtCheck, function(req, res) {
// Protected
});
app.get('*', function (req, res) {
res.sendStatus(404);
});
app.listen(8888, () => console.log("API listening on 8888"));
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
DIEUX DES DÉMOS, FAITES QUE ÇA FONCTIONNE
▸ https://github.com/joellord/
secure-spa-auth0
DÉLÉGATION!
INTRODUCTION À OPEN ID
CONNECT
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
OPEN ID CONNECT
▸ S’assois sur OAuth 2.0
▸ OpenID Connect !== OpenId
▸ Fournit l’identité de l’utilisateur avec un JWT
▸ Utilise la route /userinfo pour fournir cette info
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
OPEN ID CONNECT
▸ Utilise un “scope” pour fournir l’information de l’utilisateur
▸ openid
▸ Profile
▸ email
▸ address
▸ phone
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
OPEN ID CONNECT
scope=openid%20profile
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
OPEN ID CONNECT
👍
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
OPEN ID CONNECT
👍
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
OPEN ID CONNECT
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
OPEN ID CONNECT
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
OPEN ID CONNECT
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
OPEN ID CONNECT
/userinfo
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
OPEN ID CONNECT
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
OPEN ID CONNECT
Image: https://openidconnect.net
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
DIEUX DES DÉMOS, FAITES QUE ÇA FONCTIONNE
▸ https://github.com/joellord/
secure-spa-auth0
DÉLÉGATION!
@joel__lord
#WAQ19
LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
RESSOURCES
▸ Plus sur les JWT
▸ https://jwt.io/
▸ Plus sur OIDC
▸ https://openidconnect.net/
▸ Exemples de code
▸ http://bit.ly/idontcareaboutsecurity
@joel__lord
joellord
LA SÉCURITÉ, JE M’EN FICHE
(VOUS DEVRIEZ AUSSI)
Web à Québec
10 avril 2019
MERCI!
TEXT
TEXT

More Related Content

More from Web à Québec

Guillaume Labbé-Morissette
Guillaume Labbé-MorissetteGuillaume Labbé-Morissette
Guillaume Labbé-MorissetteWeb à Québec
 
Frédérick Capovilla
Frédérick CapovillaFrédérick Capovilla
Frédérick CapovillaWeb à Québec
 
Cynthia Thibault-Larouche
Cynthia Thibault-LaroucheCynthia Thibault-Larouche
Cynthia Thibault-LaroucheWeb à Québec
 
Intelligence artificielle, Données massives et Internet des objets: Quels son...
Intelligence artificielle, Données massives et Internet des objets: Quels son...Intelligence artificielle, Données massives et Internet des objets: Quels son...
Intelligence artificielle, Données massives et Internet des objets: Quels son...Web à Québec
 
So you want to be a service designer - Jamin Hegeman
So you want to be a service designer - Jamin HegemanSo you want to be a service designer - Jamin Hegeman
So you want to be a service designer - Jamin HegemanWeb à Québec
 
AI & the future of the political party - Colin Megill
AI & the future of the political party - Colin MegillAI & the future of the political party - Colin Megill
AI & the future of the political party - Colin MegillWeb à Québec
 
comment le Canada peut Gagner dans le secteur du numérique - Alex Benay
comment le Canada peut Gagner dans le secteur du numérique - Alex Benay comment le Canada peut Gagner dans le secteur du numérique - Alex Benay
comment le Canada peut Gagner dans le secteur du numérique - Alex Benay Web à Québec
 
Rendre son équipe performante : plus simple qu'on le pense - Louis-Philippe C...
Rendre son équipe performante : plus simple qu'on le pense - Louis-Philippe C...Rendre son équipe performante : plus simple qu'on le pense - Louis-Philippe C...
Rendre son équipe performante : plus simple qu'on le pense - Louis-Philippe C...Web à Québec
 
Turning Research Ripples Into Waves: Growing UX Research Capacity Through Col...
Turning Research Ripples Into Waves: Growing UX Research Capacity Through Col...Turning Research Ripples Into Waves: Growing UX Research Capacity Through Col...
Turning Research Ripples Into Waves: Growing UX Research Capacity Through Col...Web à Québec
 
Complexité et systèmes opérables - Fred Hébert
Complexité et systèmes opérables - Fred HébertComplexité et systèmes opérables - Fred Hébert
Complexité et systèmes opérables - Fred HébertWeb à Québec
 
Designing brands that last - Ben Hulse
Designing brands that last - Ben Hulse Designing brands that last - Ben Hulse
Designing brands that last - Ben Hulse Web à Québec
 

More from Web à Québec (20)

Gabriel LeBreton
Gabriel LeBretonGabriel LeBreton
Gabriel LeBreton
 
Rémi Prévost
Rémi PrévostRémi Prévost
Rémi Prévost
 
Ludivine Durand
Ludivine DurandLudivine Durand
Ludivine Durand
 
Julie Simard
Julie SimardJulie Simard
Julie Simard
 
Guillaume Labbé-Morissette
Guillaume Labbé-MorissetteGuillaume Labbé-Morissette
Guillaume Labbé-Morissette
 
Katherine Mailloux
Katherine MaillouxKatherine Mailloux
Katherine Mailloux
 
Denis Martel
Denis MartelDenis Martel
Denis Martel
 
Charles Davignon
Charles DavignonCharles Davignon
Charles Davignon
 
Frédérick Capovilla
Frédérick CapovillaFrédérick Capovilla
Frédérick Capovilla
 
Cynthia Thibault-Larouche
Cynthia Thibault-LaroucheCynthia Thibault-Larouche
Cynthia Thibault-Larouche
 
Louis-André Labadie
Louis-André LabadieLouis-André Labadie
Louis-André Labadie
 
Christophe Clouzeau
Christophe ClouzeauChristophe Clouzeau
Christophe Clouzeau
 
Intelligence artificielle, Données massives et Internet des objets: Quels son...
Intelligence artificielle, Données massives et Internet des objets: Quels son...Intelligence artificielle, Données massives et Internet des objets: Quels son...
Intelligence artificielle, Données massives et Internet des objets: Quels son...
 
So you want to be a service designer - Jamin Hegeman
So you want to be a service designer - Jamin HegemanSo you want to be a service designer - Jamin Hegeman
So you want to be a service designer - Jamin Hegeman
 
AI & the future of the political party - Colin Megill
AI & the future of the political party - Colin MegillAI & the future of the political party - Colin Megill
AI & the future of the political party - Colin Megill
 
comment le Canada peut Gagner dans le secteur du numérique - Alex Benay
comment le Canada peut Gagner dans le secteur du numérique - Alex Benay comment le Canada peut Gagner dans le secteur du numérique - Alex Benay
comment le Canada peut Gagner dans le secteur du numérique - Alex Benay
 
Rendre son équipe performante : plus simple qu'on le pense - Louis-Philippe C...
Rendre son équipe performante : plus simple qu'on le pense - Louis-Philippe C...Rendre son équipe performante : plus simple qu'on le pense - Louis-Philippe C...
Rendre son équipe performante : plus simple qu'on le pense - Louis-Philippe C...
 
Turning Research Ripples Into Waves: Growing UX Research Capacity Through Col...
Turning Research Ripples Into Waves: Growing UX Research Capacity Through Col...Turning Research Ripples Into Waves: Growing UX Research Capacity Through Col...
Turning Research Ripples Into Waves: Growing UX Research Capacity Through Col...
 
Complexité et systèmes opérables - Fred Hébert
Complexité et systèmes opérables - Fred HébertComplexité et systèmes opérables - Fred Hébert
Complexité et systèmes opérables - Fred Hébert
 
Designing brands that last - Ben Hulse
Designing brands that last - Ben Hulse Designing brands that last - Ben Hulse
Designing brands that last - Ben Hulse
 

Recently uploaded

Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 

Recently uploaded (20)

Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 

Je me fiche de la sécurité (vous devriez aussi) - Joel Lord

  • 1. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
  • 2.
  • 3. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
  • 4. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) QUI SUIS-JE? @joel__lord joellord
  • 5.
  • 6.
  • 7.
  • 8.
  • 9. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) INTRODUCTION À OAUTH
  • 10. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) INTRODUCTION À OAUTH
  • 11. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) INTRODUCTION À OAUTH
  • 12. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) INTRODUCTION À OAUTH
  • 14. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) INTRODUCTION À OAUTH
  • 15. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) INTRODUCTION À OAUTH
  • 16. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) INTRODUCTION À OAUTH
  • 17. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) INTRODUCTION À OAUTH
  • 18. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) INTRODUCTION À OAUTH
  • 19. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) INTRODUCTION À OAUTH
  • 22. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) APPLICATIONS TRADITIONNELLES ▸ Le navigateur demande la page d’accueil
  • 23. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) APPLICATIONS TRADITIONNELLES ▸ Le navigateur demande la page d’accueil
  • 24. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) APPLICATIONS TRADITIONNELLES ▸ Le navigateur demande la page d’accueil
  • 25. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) APPLICATIONS TRADITIONNELLES ▸ Le navigateur demande la page d’accueil ▸ Le serveur valide l’usager dans la base de données
  • 26. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) APPLICATIONS TRADITIONNELLES ▸ Le navigateur demande la page d’accueil ▸ Le serveur valide l’usager dans la base de données 👍
  • 27. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) APPLICATIONS TRADITIONNELLES ▸ Le navigateur demande la page d’accueil ▸ Le serveur valide l’usager dans la base de données ▸ Une session est créée et un Cookie est envoyé 👍
  • 28. "
  • 29. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) POURTANT, ÇA FONCTIONNE, NON? ▸ Plusieurs plateformes tentent de se connecter
  • 30. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) POURTANT, ÇA FONCTIONNE, NON? ▸ Plusieurs plateformes tentent de se connecter ▸ Code étroitement couplé
  • 31. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) POURTANT, ÇA FONCTIONNE, NON? ▸ Plusieurs plateformes tentent de se connecter ▸ Code étroitement couplé ▸ Partager un mot de passe pour se connecter à un tier-parti (ugh!)
  • 32. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) POURTANT, ÇA FONCTIONNE, NON? ▸ Plusieurs plateformes tentent de se connecter ▸ Code étroitement couplé ▸ Partager un mot de passe pour se connecter à un tier-parti (ugh!) ▸ Les utilisateurs ont déjà des centaines de comptes, ce qui mène à la réutilisation des mots de passe et un bas taux de conversion
  • 33.
  • 34. OAUTH GRANTS LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
  • 35. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) AUTHORIZATION CODE
  • 36. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) AUTHORIZATION CODE
  • 37. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) AUTHORIZATION CODE
  • 38. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) AUTHORIZATION CODE 👍
  • 39. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) AUTHORIZATION CODE 👍
  • 40. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) AUTHORIZATION CODE
  • 41. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) AUTHORIZATION CODE
  • 42. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) AUTHORIZATION CODE
  • 43. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) AUTHORIZATION CODE
  • 44. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) AUTHORIZATION CODE
  • 45. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) AUTHORIZATION CODE ⛔
  • 46. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) AUTHORIZATION CODE
  • 47. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) AUTHORIZATION CODE
  • 48. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) IMPLICIT GRANT
  • 49. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) IMPLICIT GRANT
  • 50. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) IMPLICIT GRANT
  • 51. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) IMPLICIT GRANT
  • 52. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) IMPLICIT GRANT 👍
  • 53. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) IMPLICIT GRANT
  • 54. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) IMPLICIT GRANT
  • 55. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) IMPLICIT GRANT
  • 56. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) IMPLICIT GRANT 👍
  • 57. TOKENS 101 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI)
  • 58. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) TOKENS ▸ Access Token ▸ Autorise l’accès à une resources ▸ Contrôle les accès à un API ▸ Courte vie ▸ Refresh Tokens ▸ Permet d’obtenir un Access Token ▸ Longue durée de vie ▸ Peut être révoqué
  • 59. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) TOKENS ▸ Refresh Tokens ▸ Permet d’obtenir un Access Token ▸ Longue durée de vie ▸ Peut être révoqué
  • 60. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) TOKENS ▸ Refresh Tokens ▸ Permet d’obtenir un Access Token ▸ Longue durée de vie ▸ Peut être révoqué
  • 61. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) TOKENS ▸ WS Federated ▸ SAML ▸ Sur mesure ▸ …
  • 62. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) TOKENS ▸ WS Federated ▸ SAML ▸ Sur mesure ▸ JWT
  • 63. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) JSON WEB TOKENS eyJhbGciOiJIUzI1NiIsInR5cC I6IkpXVCJ9.eyJzdWIiOiIxMj M0NTY3ODkwIiwibmFtZSI6I kpvZWwgTG9yZCIsImFkbWl uIjp0cnVlLCJzY29wZSI6InBv c3RzOnJlYWQgcG9zdHM6 d3JpdGUifQ.XesR- pKdlscHfUwoKvHnACqfpe2 ywJ6t1BJKsq9rEcg
  • 64. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) JSON WEB TOKENS ▸ Entête (Header) ▸ Charge (Payload) ▸ Signature eyJhbGciOiJIUzI1NiIsInR5cC I6IkpXVCJ9.eyJzdWIiOiIxMj M0NTY3ODkwIiwibmFtZSI6I kpvZWwgTG9yZCIsImFkbWl uIjp0cnVlLCJzY29wZSI6InBv c3RzOnJlYWQgcG9zdHM6 d3JpdGUifQ.XesR- pKdlscHfUwoKvHnACqfpe2 ywJ6t1BJKsq9rEcg
  • 65. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) JSON WEB TOKENS ▸ Entête (Header) eyJhbGciOiJIUzI1NiIsInR5cC I6IkpXVCJ9.eyJzdWIiOiIxMj M0NTY3ODkwIiwibmFtZSI6I kpvZWwgTG9yZCIsImFkbWl uIjp0cnVlLCJzY29wZSI6InBv c3RzOnJlYWQgcG9zdHM6 d3JpdGUifQ.XesR- pKdlscHfUwoKvHnACqfpe2 ywJ6t1BJKsq9rEcg
  • 66. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) JSON WEB TOKENS ▸ Entête (Header) eyJhbGciOiJIUzI1NiIsInR5cC I6IkpXVCJ9
  • 67. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) JSON WEB TOKENS ▸ Entête (Header) atob(‘eyJhbGciOiJIUzI1NiIsI nR5cCI6IkpXVCJ9’);
  • 68. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) JSON WEB TOKENS ▸ Entête (Header) { "alg": "HS256", "typ": "JWT" }
  • 69. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) JSON WEB TOKENS ▸ Charge (Payload) eyJhbGciOiJIUzI1NiIsInR5cC I6IkpXVCJ9.eyJzdWIiOiIxMj M0NTY3ODkwIiwibmFtZSI6I kpvZWwgTG9yZCIsImFkbWl uIjp0cnVlLCJzY29wZSI6InBv c3RzOnJlYWQgcG9zdHM6 d3JpdGUifQ.XesR- pKdlscHfUwoKvHnACqfpe2 ywJ6t1BJKsq9rEcg
  • 70. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) JSON WEB TOKENS ▸ Charge (Payload) eyJzdWIiOiIxMjM0NTY3OD kwIiwibmFtZSI6IkpvZWwgT G9yZCIsImFkbWluIjp0cnVlL CJzY29wZSI6InBvc3RzOnJl YWQgcG9zdHM6d3JpdGUi fQ
  • 71. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) JSON WEB TOKENS ▸ Charge (Payload) atob(‘eyJzdWIiOiIxMjM0NT Y3ODkwIiwibmFtZSI6IkpvZ WwgTG9yZCIsImFkbWluIjp 0cnVlLCJzY29wZSI6InBvc3R zOnJlYWQgcG9zdHM6d3J pdGUifQ’);
  • 72. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) JSON WEB TOKENS ▸ Charge (Payload) { "sub": "1234567890", "name": "Joel Lord", "admin": true, "scope": "posts:read posts:write" }
  • 73. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) JSON WEB TOKENS ▸ Signature XesR- pKdlscHfUwoKvHnACqfpe2 ywJ6t1BJKsq9rEcg
  • 74. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) JSON WEB TOKENS ▸ Signature hmacsha256( `${header}.${payload}`, SECRET_KEY );
  • 75. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) JSON WEB TOKENS Image: https://jwt.io
  • 76. UN PEU DE CODE
  • 77. Serveur Auth API var express = require('express'); var Webtask = require('webtask-tools'); var bodyParser = require('body-parser'); var randopeep = require("randopeep"); var jwt = require("jsonwebtoken"); var app = express(); var users = [ {id: 1, username: "joellord", password: "joellord"}, {id: 2, username: "guest", password: "guest"} ]; app.use(bodyParser.json()); app.post("/login", function(req, res) { if (!req.body.username || !req.body.password) return res.status(400).send("Need username and password"); var user = users.find(function(u) { return u.username === req.body.username && u.password === req.body.password; }); if (!user) return res.status(401).send("User not found"); var token = jwt.sign({ sub: user.id, scope: "api:read", username: user.username }, "mysupersecret", {expiresIn: "10 minutes"}); var express = require('express'); var Webtask = require('webtask-tools'); var bodyParser = require('body-parser'); var jwt = require("jsonwebtoken"); var app = express(); var users = [ {id: 1, username: "joellord", password: "joellord"}, {id: 2, username: "guest", password: "guest"} ]; app.use(bodyParser.urlencoded()); app.get("/login", function(req, res) { var loginForm = "<form method='post'><input type=hidden name=callback value='" + req.query.callback + "'><input type=text name=username /><input type=text name=password /><input type=submit></form>"; res.status(200).send(loginForm); }); app.post("/login", function(req, res) { if (!req.body.username || !req.body.password) return res.status(400).send("Need username and password"); var user = users.find(function(u) { return u.username === req.body.username && u.password === req.body.password; }); if (!user) return res.status(401).send("User not found");
  • 78. @joel__lord #WAQ19 Serveur Auth var express = require('express'); var bodyParser = require('body-parser'); var jwt = require("jsonwebtoken"); var app = express(); // ...
  • 79. @joel__lord #WAQ19 Serveur Auth var express = require('express'); var bodyParser = require('body-parser'); var jwt = require("jsonwebtoken"); var app = express(); // ...
  • 80. @joel__lord #WAQ19 Serveur Auth var express = require('express'); var bodyParser = require('body-parser'); var jwt = require("jsonwebtoken"); var app = express(); // ...
  • 81. @joel__lord #WAQ19 Serveur Auth var express = require('express'); var bodyParser = require('body-parser'); var jwt = require("jsonwebtoken"); var app = express(); // ...
  • 82. @joel__lord #WAQ19 Serveur Auth // Requires ... var users = [ {id: 1, username: "joellord", password: "joellord"}, {id: 2, username: "guest", password: "guest"} ];
  • 83. @joel__lord #WAQ19 Serveur Auth // Requires ... var users = [...]; app.use(bodyParser.urlencoded()); app.post("/login", function(req, res) { // POST for login }); app.get('*', function (req, res) { res.sendStatus(404); });
  • 84. @joel__lord #WAQ19 Serveur Auth // Requires ... var users = [...]; app.use(bodyParser.urlencoded()); app.post("/login", function(req, res) { // POST for login }); app.get('*', function (req, res) { res.sendStatus(404); });
  • 85. @joel__lord #WAQ19 Serveur Auth app.post("/login", function(req, res) { // POST for login if (!req.body.username || !req.body.password) return res.status(400).send("Need username and password"); var user = users.find(function(u) { return u.username === req.body.username && u.password === req.body.password; }); if (!user) return res.status(401).send("User not found"); var token = jwt.sign({ sub: user.id, scope: "api:read", username: user.username }, "mysupersecret", {expiresIn: "10 minutes"}); res.redirect(req.body.callback + "#access_token=" + token); });
  • 86. @joel__lord #WAQ19 Serveur Auth app.post("/login", function(req, res) { // POST for login if (!req.body.username || !req.body.password) return res.status(400).send("Need username and password"); var user = users.find(function(u) { return u.username === req.body.username && u.password === req.body.password; }); if (!user) return res.status(401).send("User not found"); var token = jwt.sign({ sub: user.id, scope: "api:read", username: user.username }, "mysupersecret", {expiresIn: "10 minutes"}); res.redirect(req.body.callback + "#access_token=" + token); });
  • 87. @joel__lord #WAQ19 Serveur Auth app.post("/login", function(req, res) { // POST for login if (!req.body.username || !req.body.password) return res.status(400).send("Need username and password"); var user = users.find(function(u) { return u.username === req.body.username && u.password === req.body.password; }); if (!user) return res.status(401).send("User not found"); var token = jwt.sign({ sub: user.id, scope: "api:read", username: user.username }, "mysupersecret", {expiresIn: "10 minutes"}); res.redirect(req.body.callback + "#access_token=" + token); });
  • 88. @joel__lord #WAQ19 Serveur Auth app.post("/login", function(req, res) { // POST for login if (!req.body.username || !req.body.password) return res.status(400).send("Need username and password"); var user = users.find(function(u) { return u.username === req.body.username && u.password === req.body.password; }); if (!user) return res.status(401).send("User not found"); var token = jwt.sign({ sub: user.id, scope: "api:read", username: user.username }, "mysupersecret", {expiresIn: "10 minutes"}); res.redirect(req.body.callback + "#access_token=" + token); });
  • 89. @joel__lord #WAQ19 Serveur Auth // Requires ... var users = [...]; app.use(bodyParser.urlencoded()); app.post("/login", function(req, res) { // POST for login }); app.get('*', function (req, res) { res.sendStatus(404); }); app.listen(8080, () => console.log("Auth server running on 8080"));}
  • 90. @joel__lord #WAQ19 API var express = require('express'); var bodyParser = require('body-parser'); var randopeep = require("randopeep"); var expressjwt = require("express-jwt"); var app = express();
  • 91. @joel__lord #WAQ19 API var express = require('express'); var bodyParser = require('body-parser'); var randopeep = require("randopeep"); var expressjwt = require("express-jwt"); var app = express();
  • 92. @joel__lord #WAQ19 API var express = require('express'); var bodyParser = require('body-parser'); var randopeep = require("randopeep"); var expressjwt = require("express-jwt"); var app = express();
  • 93. @joel__lord #WAQ19 API var express = require('express'); var bodyParser = require('body-parser'); var randopeep = require("randopeep"); var expressjwt = require("express-jwt"); var app = express();
  • 94. @joel__lord #WAQ19 API var express = require('express'); var bodyParser = require('body-parser'); var randopeep = require("randopeep"); var expressjwt = require("express-jwt"); var app = express();
  • 95. @joel__lord #WAQ19 API // Requires ... var jwtCheck = expressjwt({ secret: "mysupersecret" });
  • 96. @joel__lord #WAQ19 API // Requires and config ... app.get("/headline", function(req, res) { // Unprotected res.status(200).send(randopeep.clickbait.headline()); }); app.get("/protected/headline", jwtCheck, function(req, res) { // Protected res.status(200).send(randopeep.clickbait.headline("Joel Lord")); }); app.get('*', function (req, res) { res.sendStatus(404); });
  • 97. @joel__lord #WAQ19 API // Requires and config ... app.get("/headline", function(req, res) { // Unprotected res.status(200).send(randopeep.clickbait.headline()); }); app.get("/protected/headline", jwtCheck, function(req, res) { // Protected res.status(200).send(randopeep.clickbait.headline("Joel Lord")); }); app.get('*', function (req, res) { res.sendStatus(404); });
  • 98. @joel__lord #WAQ19 API // Requires and config ... app.get("/headline", function(req, res) { // Unprotected res.status(200).send(randopeep.clickbait.headline()); }); app.get("/protected/headline", jwtCheck, function(req, res) { // Protected res.status(200).send(randopeep.clickbait.headline("Joel Lord")); }); app.get('*', function (req, res) { res.sendStatus(404); });
  • 99. @joel__lord #WAQ19 API // Requires and config ... app.get("/headline", function(req, res) { // Unprotected res.status(200).send(randopeep.clickbait.headline()); }); app.get("/protected/headline", jwtCheck, function(req, res) { // Protected res.status(200).send(randopeep.clickbait.headline("Joel Lord")); }); app.get('*', function (req, res) { res.sendStatus(404); });
  • 100. @joel__lord #WAQ19 API // Requires and config ... app.get("/headline", function(req, res) { // Unprotected }); app.get("/protected/headline", jwtCheck, function(req, res) { // Protected }); app.get('*', function (req, res) { res.sendStatus(404); }); app.listen(8888, () => console.log("API listening on 8888"));
  • 101.
  • 102. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) DIEUX DES DÉMOS, FAITES QUE ÇA FONCTIONNE ▸ https://github.com/joellord/ secure-spa-auth0
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111. INTRODUCTION À OPEN ID CONNECT
  • 112. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) OPEN ID CONNECT ▸ S’assois sur OAuth 2.0 ▸ OpenID Connect !== OpenId ▸ Fournit l’identité de l’utilisateur avec un JWT ▸ Utilise la route /userinfo pour fournir cette info
  • 113. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) OPEN ID CONNECT ▸ Utilise un “scope” pour fournir l’information de l’utilisateur ▸ openid ▸ Profile ▸ email ▸ address ▸ phone
  • 114. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) OPEN ID CONNECT scope=openid%20profile
  • 115. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) OPEN ID CONNECT 👍
  • 116. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) OPEN ID CONNECT 👍
  • 117. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) OPEN ID CONNECT
  • 118. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) OPEN ID CONNECT
  • 119. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) OPEN ID CONNECT
  • 120. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) OPEN ID CONNECT /userinfo
  • 121. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) OPEN ID CONNECT
  • 122. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) OPEN ID CONNECT Image: https://openidconnect.net
  • 123. LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) DIEUX DES DÉMOS, FAITES QUE ÇA FONCTIONNE ▸ https://github.com/joellord/ secure-spa-auth0
  • 125. @joel__lord #WAQ19 LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) RESSOURCES ▸ Plus sur les JWT ▸ https://jwt.io/ ▸ Plus sur OIDC ▸ https://openidconnect.net/ ▸ Exemples de code ▸ http://bit.ly/idontcareaboutsecurity
  • 126. @joel__lord joellord LA SÉCURITÉ, JE M’EN FICHE (VOUS DEVRIEZ AUSSI) Web à Québec 10 avril 2019 MERCI!
  • 127. TEXT
  • 128. TEXT