The document discusses the OAuth authorization framework and JSON Web Tokens (JWT). It describes some issues with traditional login methods, such as having separate user accounts and passwords for each application. OAuth aims to solve this using authorization codes and tokens to allow users to securely grant access to third-party applications without sharing their credentials directly. JWTs are also discussed as a way to encode tokens as JSON objects for secure transmission.
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é
👍
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
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
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();
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
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