Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
I Don’t Care About Security
And Neither Should You
@joel__lord
#CoderCruise
About Me
@joel__lord
joellord
@joel__lord
#CoderCruise
OAuth - Flows
Authorization Code
@joel__lord
#CoderCruise
OAuth - Flows
Authorization Code
@joel__lord
#CoderCruise
OAuth - Flows
Authorization Code
That reminds me of OAuth!
@joel__lord
#CoderCruise
OAuth - Flows
Authorization Code
@joel__lord
#CoderCruise
OAuth - Flows
Authorization Code
@joel__lord
#CoderCruise
OAuth - Flows
Authorization Code
@joel__lord
#CoderCruise
OAuth - Flows
Authorization Code
@joel__lord
#CoderCruise
OAuth - Flows
Authorization Code
@joel__lord
#CoderCruise
OAuth - Flows
Authorization Code
But Why?
Delegation!
Traditional
Applications
! Browser requests a
login page
Traditional
Applications
! Browser requests a
login page
Traditional
Applications
! Browser requests a
login page
Traditional
Applications
! Browser requests a
login page
! The server validates
on its database
Traditional
Applications
! Browser requests a
login page
! The server validates
on its database
👍
Traditional
Applications
! Browser requests a
login page
! The server validates
on its database
! It creates a session
and...
What’s wrong with
traditional auth?
! Multiple platforms
connecting to your
application
What’s wrong with
traditional auth?
! Multiple platforms
connecting to your
application
! Tightly coupled
What’s wrong with
traditional auth?
! Multiple platforms
connecting to your
application
! Tightly coupled
! Sharing creden...
What’s wrong with
traditional auth?
! Multiple platforms
connecting to your
application
! Tightly coupled
! Sharing creden...
OAuth
OAuth - The Flows
Authorization Code
@joel__lord
#CoderCruise
Authentication Flows
Authorization Code
@joel__lord
#CoderCruise
Authentication Flows
Authorization Code
@joel__lord
#CoderCruise
Authentication Flows
Authorization Code
@joel__lord
#CoderCruise
Authentication Flows
Authorization Code
@joel__lord
#CoderCruise
Authentication Flows
Authorization Code
@joel__lord
#CoderCruise
Authentication Flows
Authorization Code
OAuth - The Flows
Implicit Flow
@joel__lord
#CoderCruise
Authentication Flows
Implicit Flow
@joel__lord
#CoderCruise
Authentication Flows
Implicit Flow
@joel__lord
#CoderCruise
Authentication Flows
Implicit Flow
@joel__lord
#CoderCruise
Authentication Flows
Implicit Flow
@joel__lord
#CoderCruise
Authentication Flows
Implicit Flow
@joel__lord
#CoderCruise
Authentication Flows
Implicit Flow
Tokens 101
@joel__lord
#CoderCruise
OAuth
Tokens
Access Token Refresh Token
! Give you access to a resource
! Controls access to your...
@joel__lord
#CoderCruise
OAuth
Tokens
Refresh Token
! Enables you to get a new token
! Longed lived
! Can be revoked
@joel__lord
#CoderCruise
OAuth
Tokens
Refresh Token
! Enables you to get a new token
! Longed lived
! Can be revoked
@joel__lord
#CoderCruise
OAuth
Tokens
! WS-Federated
! SAML
! JWT
! Custom stuff
! More…
JSON Web Token
! Header
! Payload
! Signature
Header
{
"alg": "HS256",
"typ": "JWT"
}
Payload
{
"sub": "1234567890",
"name...
JSON Web Token
! Header
! Payload
! Signature
Header
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload
eyJzdWIiOiIxMjM0NTY3ODkw...
JSON Web Token
! Header
! Payload
! Signature eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMj
M0NTY3ODkwIiwibmFtZSI6Ik...
JSON Web Token
! Header
! Payload
! Signature
Image: https://jwt.io
Codiiiing Time!
Auth Server API
var express = require('express');
var Webtask = require('webtask-tools');
var bodyParser = require('body-p...
@joel__lord
#midwestjs
Auth Server
var express = require('express');
var bodyParser = require('body-parser');
var jwt = re...
@joel__lord
#midwestjs
Auth Server
var express = require('express');
var bodyParser = require('body-parser');
var jwt = re...
@joel__lord
#midwestjs
Auth Server
var express = require('express');
var bodyParser = require('body-parser');
var jwt = re...
@joel__lord
#midwestjs
Auth Server
var express = require('express');
var bodyParser = require('body-parser');
var jwt = re...
@joel__lord
#midwestjs
Auth Server
// Requires ...
var users = [
{id: 1, username: "joellord", password: "joellord"},
{id:...
@joel__lord
#midwestjs
Auth Server
// Requires ...
var users = [...];
app.use(bodyParser.urlencoded());
app.post("/login",...
@joel__lord
#midwestjs
Auth Server
// Requires ...
var users = [...];
app.use(bodyParser.urlencoded());
app.post("/login",...
@joel__lord
#midwestjs
Auth Server
app.post("/login", function(req, res) {
// POST for login
if (!req.body.username || !re...
@joel__lord
#midwestjs
Auth Server
app.post("/login", function(req, res) {
// POST for login
if (!req.body.username || !re...
@joel__lord
#midwestjs
Auth Server
app.post("/login", function(req, res) {
// POST for login
if (!req.body.username || !re...
@joel__lord
#midwestjs
Auth Server
app.post("/login", function(req, res) {
// POST for login
if (!req.body.username || !re...
@joel__lord
#midwestjs
Auth Server
// Requires ...
var users = [...];
app.use(bodyParser.urlencoded());
app.post("/login",...
@joel__lord
#midwestjs
API
var express = require('express');
var bodyParser = require('body-parser');
var randopeep = requ...
@joel__lord
#midwestjs
API
var express = require('express');
var bodyParser = require('body-parser');
var randopeep = requ...
@joel__lord
#midwestjs
API
var express = require('express');
var bodyParser = require('body-parser');
var randopeep = requ...
@joel__lord
#midwestjs
API
var express = require('express');
var bodyParser = require('body-parser');
var randopeep = requ...
@joel__lord
#midwestjs
API
var express = require('express');
var bodyParser = require('body-parser');
var randopeep = requ...
@joel__lord
#midwestjs
API
// Requires ...
var jwtCheck = expressjwt({
secret: "mysupersecret"
});
@joel__lord
#midwestjs
API
// Requires and config ...
app.get("/headline", function(req, res) {
// Unprotected
res.status(...
@joel__lord
#midwestjs
API
// Requires and config ...
app.get("/headline", function(req, res) {
// Unprotected
res.status(...
@joel__lord
#midwestjs
API
// Requires and config ...
app.get("/headline", function(req, res) {
// Unprotected
res.status(...
@joel__lord
#midwestjs
API
// Requires and config ...
app.get("/headline", function(req, res) {
// Unprotected
res.status(...
@joel__lord
#midwestjs
API
// Requires and config ...
app.get("/headline", function(req, res) {
// Unprotected
});
app.get...
@joel__lord
#CoderCruise
Front-End
Add the headers
Live Demo
https://github.com/joellord/
secure-spa-auth0
Delegation!
Introducing OpenID Connect
@joel__lord
#CoderCruise
OpenID Connect
! Built on top of OAuth 2.0
! OpenID Connect (OIDC) is to OpenID what
Javascript i...
@joel__lord
#CoderCruise
OpenID Connect
Scopes
! openid
! profile
! email
! address
! phone
@joel__lord
#CoderCruise
OpenID Connect Flows
Authorization Code
scope=openid%20profile
@joel__lord
#CoderCruise
Authentication Flows
Authorization Code
@joel__lord
#CoderCruise
Authentication Flows
Authorization Code
@joel__lord
#CoderCruise
Authentication Flows
Authorization Code
/userinfo
@joel__lord
#CoderCruise
OpenID Connect
Full flow
https://openidconnect.net
@joel__lord
#CoderCruise
OpenID Connect
In Action
Delegation!
I Don’t Care About Security
@joel__lord
joellord
CoderCruise, The Bahamas
September 1st, 2018
I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)
Upcoming SlideShare
Loading in …5
×

I Don't Care About Security (And Neither Should You)

38 views

Published on

Remember when setting up an auth system was easy? Me neither. From the signup form, the login form, password reset form, and all the validation in between it can easily take weeks if not months to get something basic up and running. Then you have to deal with all the security considerations. No thanks. During this presentation, the attendees will be introduced to OpenID and OAuth. They will learn how to leverage these technologies to create secure applications, but most importantly, they will learn why and how to delegate authorization and authentication so they can focus on their real work and forget about all that security stuff.

Published in: Internet
  • Be the first to comment

  • Be the first to like this

I Don't Care About Security (And Neither Should You)

  1. 1. I Don’t Care About Security And Neither Should You
  2. 2. @joel__lord #CoderCruise About Me @joel__lord joellord
  3. 3. @joel__lord #CoderCruise OAuth - Flows Authorization Code
  4. 4. @joel__lord #CoderCruise OAuth - Flows Authorization Code
  5. 5. @joel__lord #CoderCruise OAuth - Flows Authorization Code
  6. 6. That reminds me of OAuth!
  7. 7. @joel__lord #CoderCruise OAuth - Flows Authorization Code
  8. 8. @joel__lord #CoderCruise OAuth - Flows Authorization Code
  9. 9. @joel__lord #CoderCruise OAuth - Flows Authorization Code
  10. 10. @joel__lord #CoderCruise OAuth - Flows Authorization Code
  11. 11. @joel__lord #CoderCruise OAuth - Flows Authorization Code
  12. 12. @joel__lord #CoderCruise OAuth - Flows Authorization Code
  13. 13. But Why?
  14. 14. Delegation!
  15. 15. Traditional Applications ! Browser requests a login page
  16. 16. Traditional Applications ! Browser requests a login page
  17. 17. Traditional Applications ! Browser requests a login page
  18. 18. Traditional Applications ! Browser requests a login page ! The server validates on its database
  19. 19. Traditional Applications ! Browser requests a login page ! The server validates on its database 👍
  20. 20. Traditional Applications ! Browser requests a login page ! The server validates on its database ! It creates a session and provides a cookie identifier
  21. 21. What’s wrong with traditional auth? ! Multiple platforms connecting to your application
  22. 22. What’s wrong with traditional auth? ! Multiple platforms connecting to your application ! Tightly coupled
  23. 23. What’s wrong with traditional auth? ! Multiple platforms connecting to your application ! Tightly coupled ! Sharing credentials to connect to another API
  24. 24. What’s wrong with traditional auth? ! Multiple platforms connecting to your application ! Tightly coupled ! Sharing credentials to connect to another API ! Users have a gazillion passwords to remember, which increases security risks
  25. 25. OAuth
  26. 26. OAuth - The Flows Authorization Code
  27. 27. @joel__lord #CoderCruise Authentication Flows Authorization Code
  28. 28. @joel__lord #CoderCruise Authentication Flows Authorization Code
  29. 29. @joel__lord #CoderCruise Authentication Flows Authorization Code
  30. 30. @joel__lord #CoderCruise Authentication Flows Authorization Code
  31. 31. @joel__lord #CoderCruise Authentication Flows Authorization Code
  32. 32. @joel__lord #CoderCruise Authentication Flows Authorization Code
  33. 33. OAuth - The Flows Implicit Flow
  34. 34. @joel__lord #CoderCruise Authentication Flows Implicit Flow
  35. 35. @joel__lord #CoderCruise Authentication Flows Implicit Flow
  36. 36. @joel__lord #CoderCruise Authentication Flows Implicit Flow
  37. 37. @joel__lord #CoderCruise Authentication Flows Implicit Flow
  38. 38. @joel__lord #CoderCruise Authentication Flows Implicit Flow
  39. 39. @joel__lord #CoderCruise Authentication Flows Implicit Flow
  40. 40. Tokens 101
  41. 41. @joel__lord #CoderCruise OAuth Tokens Access Token Refresh Token ! Give you access to a resource ! Controls access to your API ! Short lived ! Enables you to get a new token ! Longed lived ! Can be revoked
  42. 42. @joel__lord #CoderCruise OAuth Tokens Refresh Token ! Enables you to get a new token ! Longed lived ! Can be revoked
  43. 43. @joel__lord #CoderCruise OAuth Tokens Refresh Token ! Enables you to get a new token ! Longed lived ! Can be revoked
  44. 44. @joel__lord #CoderCruise OAuth Tokens ! WS-Federated ! SAML ! JWT ! Custom stuff ! More…
  45. 45. JSON Web Token ! Header ! Payload ! Signature Header { "alg": "HS256", "typ": "JWT" } Payload { "sub": "1234567890", "name": "Joel Lord", "scope": "posts:read posts:write" } Signature HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
  46. 46. JSON Web Token ! Header ! Payload ! Signature Header eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 Payload eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvZWwgTG 9yZCIsImFkbWluIjp0cnVlLCJzY29wZSI6InBvc3RzOnJlY WQgcG9zdHM6d3JpdGUifQ Signature XesR-pKdlscHfUwoKvHnACqfpe2ywJ6t1BJKsq9rEcg
  47. 47. JSON Web Token ! Header ! Payload ! Signature eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMj M0NTY3ODkwIiwibmFtZSI6IkpvZWwgTG9yZCIsImFkbWl uIjp0cnVlLCJzY29wZSI6InBvc3RzOnJlYWQgcG9zdHM6d 3JpdGUifQ.XesR- pKdlscHfUwoKvHnACqfpe2ywJ6t1BJKsq9rEcg
  48. 48. JSON Web Token ! Header ! Payload ! Signature Image: https://jwt.io
  49. 49. Codiiiing Time!
  50. 50. Auth Server 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"}); res.status(200).send({token: token}); }); app.get('*', function (req, res) { res.sendStatus(404); }); module.exports = Webtask.fromExpress(app); 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"); 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); }); app.get('*', function (req, res) { res.sendStatus(404); });
  51. 51. @joel__lord #midwestjs Auth Server var express = require('express'); var bodyParser = require('body-parser'); var jwt = require("jsonwebtoken"); var app = express(); // ...
  52. 52. @joel__lord #midwestjs Auth Server var express = require('express'); var bodyParser = require('body-parser'); var jwt = require("jsonwebtoken"); var app = express(); // ...
  53. 53. @joel__lord #midwestjs Auth Server var express = require('express'); var bodyParser = require('body-parser'); var jwt = require("jsonwebtoken"); var app = express(); // ...
  54. 54. @joel__lord #midwestjs Auth Server var express = require('express'); var bodyParser = require('body-parser'); var jwt = require("jsonwebtoken"); var app = express(); // ...
  55. 55. @joel__lord #midwestjs Auth Server // Requires ... var users = [ {id: 1, username: "joellord", password: "joellord"}, {id: 2, username: "guest", password: "guest"} ];
  56. 56. @joel__lord #midwestjs Auth Server // Requires ... var users = [...]; app.use(bodyParser.urlencoded()); app.post("/login", function(req, res) { // POST for login }); app.get('*', function (req, res) { res.sendStatus(404); });
  57. 57. @joel__lord #midwestjs Auth Server // Requires ... var users = [...]; app.use(bodyParser.urlencoded()); app.post("/login", function(req, res) { // POST for login }); app.get('*', function (req, res) { res.sendStatus(404); });
  58. 58. @joel__lord #midwestjs Auth Server 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); });
  59. 59. @joel__lord #midwestjs Auth Server 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); });
  60. 60. @joel__lord #midwestjs Auth Server 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); });
  61. 61. @joel__lord #midwestjs Auth Server 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); });
  62. 62. @joel__lord #midwestjs Auth Server // 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"));}
  63. 63. @joel__lord #midwestjs API var express = require('express'); var bodyParser = require('body-parser'); var randopeep = require("randopeep"); var expressjwt = require("express-jwt"); var app = express();
  64. 64. @joel__lord #midwestjs API var express = require('express'); var bodyParser = require('body-parser'); var randopeep = require("randopeep"); var expressjwt = require("express-jwt"); var app = express();
  65. 65. @joel__lord #midwestjs API var express = require('express'); var bodyParser = require('body-parser'); var randopeep = require("randopeep"); var expressjwt = require("express-jwt"); var app = express();
  66. 66. @joel__lord #midwestjs API var express = require('express'); var bodyParser = require('body-parser'); var randopeep = require("randopeep"); var expressjwt = require("express-jwt"); var app = express();
  67. 67. @joel__lord #midwestjs API var express = require('express'); var bodyParser = require('body-parser'); var randopeep = require("randopeep"); var expressjwt = require("express-jwt"); var app = express();
  68. 68. @joel__lord #midwestjs API // Requires ... var jwtCheck = expressjwt({ secret: "mysupersecret" });
  69. 69. @joel__lord #midwestjs 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); });
  70. 70. @joel__lord #midwestjs 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); });
  71. 71. @joel__lord #midwestjs 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); });
  72. 72. @joel__lord #midwestjs 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); });
  73. 73. @joel__lord #midwestjs 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"));
  74. 74. @joel__lord #CoderCruise Front-End Add the headers
  75. 75. Live Demo https://github.com/joellord/ secure-spa-auth0
  76. 76. Delegation!
  77. 77. Introducing OpenID Connect
  78. 78. @joel__lord #CoderCruise OpenID Connect ! Built on top of OAuth 2.0 ! OpenID Connect (OIDC) is to OpenID what Javascript is to Java ! Provides Identity Tokens in JWT format ! Uses a /userinfo endpoint to provide the info
  79. 79. @joel__lord #CoderCruise OpenID Connect Scopes ! openid ! profile ! email ! address ! phone
  80. 80. @joel__lord #CoderCruise OpenID Connect Flows Authorization Code scope=openid%20profile
  81. 81. @joel__lord #CoderCruise Authentication Flows Authorization Code
  82. 82. @joel__lord #CoderCruise Authentication Flows Authorization Code
  83. 83. @joel__lord #CoderCruise Authentication Flows Authorization Code /userinfo
  84. 84. @joel__lord #CoderCruise OpenID Connect Full flow https://openidconnect.net
  85. 85. @joel__lord #CoderCruise OpenID Connect In Action
  86. 86. Delegation!
  87. 87. I Don’t Care About Security @joel__lord joellord CoderCruise, The Bahamas September 1st, 2018

×