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.
JWT! JWT!
Let it all out!
John SJ Anderson | @genehack | Hack Salem | 14 Sep 2016
Hack Salem | 14 Sep 2016 | @genehack 1
JSON Web Tokens
want to rule your world
John SJ Anderson | @genehack | Hack Salem | 14 Sep 2016
Hack Salem | 14 Sep 2016 |...
Hi, I'm John
Hack Salem | 14 Sep 2016 | @genehack 3
VP, Tech
Infinity
Interactive
Hack Salem | 14 Sep 2016 | @genehack 4
So, what's a JWT?
Hack Salem | 14 Sep 2016 | @genehack 5
jwt.io
Hack Salem | 14 Sep 2016 | @genehack 6
What
Does
That
Even
MeanHack Salem | 14 Sep 2016 | @genehack 7
Think of it as…
• A lightweight alternative to cookies
• A form of access control without authentication
• Cross-site sing...
Made of stuff you already know
• JSON Objects
• Cryptographically signed and hashed
• Transmitted during HTTP request
Hack...
JWT teardown
• dot-delimited string ('.')
• 3 parts
• header
• payload
• signature
• Example: xxx.yyyyy.zzz
Hack Salem | 1...
JWT teardown: header
• Plain ole JSON object
• Base64Url encoded
• Typically indicates token type and hashing algorithm
{
...
JWT teardown: payload
• Also plain ole JSON object
• Contains "claims" -- really just data
• Reserved, public, private
• A...
JWT teardown: signature
• Encoded header, plus
• Encoded payload, plus
• A secret, plus
• Signing algorithm from header
HM...
Putting it all together
Hack Salem | 14 Sep 2016 | @genehack 14
Putting it all together
Hack Salem | 14 Sep 2016 | @genehack 15
More advanced usage
• Encrypted payloads (JWE)
• Nested JWT
(Won't get any further into these tonight…)
Hack Salem | 14 Se...
Libraries for DAYS
• .NET, Python, Node, Java, Javascript, Ruby, Perl, Go, PHP
• Haskell, Rust, Lua, Scala, Clojure, Objec...
OK,
you've
got
my
attentionHack Salem | 14 Sep 2016 | @genehack 18
How
Do
I
Use
It?Hack Salem | 14 Sep 2016 | @genehack 19
Basic auth/authz usage
(stolen from jwt.io)
Hack Salem | 14 Sep 2016 | @genehack 20
Things to be aware of
• Payload/header NOT encrypted (in this setup)
• …don't send anything sensitive!
• Need to control e...
How is it actually transmitted?
• Up to you! Various methods:
• As part of the URL
• In the POST body
• In the Authorizati...
Authorization without authentication
• Scenario:
• You have an API
• You don't want to make anybody authenticate to use it...
Solution: JWT with RSA keys
• Alternative to secret in previous scenario: RSA key-pair
• Can include the public key in the...
To set it up:
• Give authorized user a RSA key-pair
• You can even let them generate it — you just need to:
• Record the fi...
On their side:
• They make JWT using the private key
• They include the public key in the header
• Include iat (issued-at)...
On our side:
• Get the public key out of the JWT header
• Validate the JWT signature using the key
• Validate that public ...
Things to be aware of:
• You still want to validate iat and exp and any other rules
• Your library should probably do that...
Let's see some code!
• May look a bit strange
• New experimental language, Nacre
• Transpiles to Javascript
Hack Salem | 1...
Client side
my $pri_key = Crypt::PK::RSA->new('./key.pri');
my $pub_key = Crypt::PK::RSA->new('./key.pub');
my $token = en...
Client side: making the token
my $token = encode_jwt(
alg => 'RS512',
extra_headers => {
jwk => $pub_key->export_key_jwk('...
Client side: adding the public key
extra_headers => {
jwk => $pub_key->export_key_jwk('public', 1),
},
Key: find an RSA lib...
BTW,
just
kidding
about
Nacre…Hack Salem | 14 Sep 2016 | @genehack 33
it's
Perl!
(of course)
Hack Salem | 14 Sep 2016 | @genehack 34
Server side
my $auth_header = request_header 'Authorization' ;
status_401 unless ( $token ) = $auth_header =~ /^Bearer (.*...
Server side: get the token
my $auth_header = request_header 'Authorization' ;
status_401 unless ( $token ) = $auth_header ...
Server side: decode the token
# try to decode it and confirm valid sig,
# and valid iat and exp claims
my( $header, $paylo...
Server side: decode the token
• Key in header wrong? FAILS
• Not right algorithm? FAILS
• Doesn't have iat and exp? FAILS
...
Server side: do more checks
# check that expiration time is less than one hour
status_401 unless $payload->{exp} - $payloa...
Server side: more checks
• We specify in the API docs that tokens can only be valid for
one hour
• Have to check that ours...
Server side: THAT'S ALL FOLKS
# if we get here, we're all good!
• If we know the public key in the header,
• then we know ...
IMPORTANT NOTE!
This does, of course, depend on the client keeping the private
key actually private
…
But access revocatio...
Conclusions
• JWTs solve some really common problems.
• JWTs solve them in a pretty elegant way.
• This is really pretty d...
Conclusions
• JWTs solve some really common problems.
• JWTs solve them in a pretty elegant way.
• This is really pretty d...
Questions?
Hack Salem | 14 Sep 2016 | @genehack 45
Thanks!
Hack Salem | 14 Sep 2016 | @genehack 46
Upcoming SlideShare
Loading in …5
×

JWT! JWT! Let it all out!

651 views

Published on

Brief talk on using JSON Web Tokens (JWTs) for authorization and access control of APIs

Published in: Internet
  • Be the first to comment

JWT! JWT! Let it all out!

  1. 1. JWT! JWT! Let it all out! John SJ Anderson | @genehack | Hack Salem | 14 Sep 2016 Hack Salem | 14 Sep 2016 | @genehack 1
  2. 2. JSON Web Tokens want to rule your world John SJ Anderson | @genehack | Hack Salem | 14 Sep 2016 Hack Salem | 14 Sep 2016 | @genehack 2
  3. 3. Hi, I'm John Hack Salem | 14 Sep 2016 | @genehack 3
  4. 4. VP, Tech Infinity Interactive Hack Salem | 14 Sep 2016 | @genehack 4
  5. 5. So, what's a JWT? Hack Salem | 14 Sep 2016 | @genehack 5
  6. 6. jwt.io Hack Salem | 14 Sep 2016 | @genehack 6
  7. 7. What Does That Even MeanHack Salem | 14 Sep 2016 | @genehack 7
  8. 8. Think of it as… • A lightweight alternative to cookies • A form of access control without authentication • Cross-site single sign on (SSO) without cross domain pain Hack Salem | 14 Sep 2016 | @genehack 8
  9. 9. Made of stuff you already know • JSON Objects • Cryptographically signed and hashed • Transmitted during HTTP request Hack Salem | 14 Sep 2016 | @genehack 9
  10. 10. JWT teardown • dot-delimited string ('.') • 3 parts • header • payload • signature • Example: xxx.yyyyy.zzz Hack Salem | 14 Sep 2016 | @genehack 10
  11. 11. JWT teardown: header • Plain ole JSON object • Base64Url encoded • Typically indicates token type and hashing algorithm { "alg": "HS256", "typ": "JWT" } Hack Salem | 14 Sep 2016 | @genehack 11
  12. 12. JWT teardown: payload • Also plain ole JSON object • Contains "claims" -- really just data • Reserved, public, private • Also Base64Url encoded { "name": "Hack Salem", "admin": false } Hack Salem | 14 Sep 2016 | @genehack 12
  13. 13. JWT teardown: signature • Encoded header, plus • Encoded payload, plus • A secret, plus • Signing algorithm from header HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret ) Hack Salem | 14 Sep 2016 | @genehack 13
  14. 14. Putting it all together Hack Salem | 14 Sep 2016 | @genehack 14
  15. 15. Putting it all together Hack Salem | 14 Sep 2016 | @genehack 15
  16. 16. More advanced usage • Encrypted payloads (JWE) • Nested JWT (Won't get any further into these tonight…) Hack Salem | 14 Sep 2016 | @genehack 16
  17. 17. Libraries for DAYS • .NET, Python, Node, Java, Javascript, Ruby, Perl, Go, PHP • Haskell, Rust, Lua, Scala, Clojure, ObjectiveC, Swift, Delphi • Support for your favorite language/platform is probably not an issue Hack Salem | 14 Sep 2016 | @genehack 17
  18. 18. OK, you've got my attentionHack Salem | 14 Sep 2016 | @genehack 18
  19. 19. How Do I Use It?Hack Salem | 14 Sep 2016 | @genehack 19
  20. 20. Basic auth/authz usage (stolen from jwt.io) Hack Salem | 14 Sep 2016 | @genehack 20
  21. 21. Things to be aware of • Payload/header NOT encrypted (in this setup) • …don't send anything sensitive! • Need to control expiration, re-issue, etc. • Some APIs will send a fresh JWT to the client per-request • Sites other than issuing site can receive JWT • …if they share the secret Hack Salem | 14 Sep 2016 | @genehack 21
  22. 22. How is it actually transmitted? • Up to you! Various methods: • As part of the URL • In the POST body • In the Authorization header using bearer scheme: Authorization: Bearer <token> Hack Salem | 14 Sep 2016 | @genehack 22
  23. 23. Authorization without authentication • Scenario: • You have an API • You don't want to make anybody authenticate to use it • You don't want it wide open to the Internet either • a/k/a authz without authn Hack Salem | 14 Sep 2016 | @genehack 23
  24. 24. Solution: JWT with RSA keys • Alternative to secret in previous scenario: RSA key-pair • Can include the public key in the JWT header using JWK • JSON Web Key, natch • Allows API client to produce claims in a verifiable way Hack Salem | 14 Sep 2016 | @genehack 24
  25. 25. To set it up: • Give authorized user a RSA key-pair • You can even let them generate it — you just need to: • Record the fingerprint of the public key (important later!) Hack Salem | 14 Sep 2016 | @genehack 25
  26. 26. On their side: • They make JWT using the private key • They include the public key in the header • Include iat (issued-at) and exp (expires) claims • Send JWT in Authorization header with API request Hack Salem | 14 Sep 2016 | @genehack 26
  27. 27. On our side: • Get the public key out of the JWT header • Validate the JWT signature using the key • Validate that public key fingerprint is white-listed • Signature produced with private key • Public key is white-listed • Therefore we know JWT is valid! Hack Salem | 14 Sep 2016 | @genehack 27
  28. 28. Things to be aware of: • You still want to validate iat and exp and any other rules • Your library should probably do that stuff for you, mostly • Again, nothing is encrypted, so don't plan on sensitive stuff in the payload or header Hack Salem | 14 Sep 2016 | @genehack 28
  29. 29. Let's see some code! • May look a bit strange • New experimental language, Nacre • Transpiles to Javascript Hack Salem | 14 Sep 2016 | @genehack 29
  30. 30. Client side my $pri_key = Crypt::PK::RSA->new('./key.pri'); my $pub_key = Crypt::PK::RSA->new('./key.pub'); my $token = encode_jwt( alg => 'RS512', extra_headers => { jwk => $pub_key->export_key_jwk('public', 1), nonce => undef , }, key => $pri_key , payload => { iat => time() }, relative_exp => 1800, ); HTTP::Request->new( 'POST' => 'https://example.com/endpoint', ['Authorization' => "Bearer $token"], encode_json({ request => 'body' }) ); Hack Salem | 14 Sep 2016 | @genehack 30
  31. 31. Client side: making the token my $token = encode_jwt( alg => 'RS512', extra_headers => { jwk => $pub_key->export_key_jwk('public', 1), nonce => undef , }, key => $pri_key , payload => { iat => time() }, relative_exp => 1800, ); Hack Salem | 14 Sep 2016 | @genehack 31
  32. 32. Client side: adding the public key extra_headers => { jwk => $pub_key->export_key_jwk('public', 1), }, Key: find an RSA library that supports export to JWK format! Hack Salem | 14 Sep 2016 | @genehack 32
  33. 33. BTW, just kidding about Nacre…Hack Salem | 14 Sep 2016 | @genehack 33
  34. 34. it's Perl! (of course) Hack Salem | 14 Sep 2016 | @genehack 34
  35. 35. Server side my $auth_header = request_header 'Authorization' ; status_401 unless ( $token ) = $auth_header =~ /^Bearer (.*)$/; # try to decode it and confirm valid sig, # and valid iat and exp claims my( $header, $payload ); try { ( $header, $payload ) = decode_jwt( token => $token , decode_header => 1 , accepted_alg => 'RS512' , verify_iat => 1 , verify_exp => 1 ); }; # no catch block, just drop the error, we're out of here in that case status_401 unless $header and $payload; # check that expiration time is less than one hour status_401 unless $payload->{exp} - $payload->{iat} < 3600; # check that the included public key is on the whitelist my $pk = Crypt::PK::RSA->new; $pk->import_key($header->{jwk}); my $thumbprint = $pk->export_key_jwk_thumbprint; status_401 unless config->{whitelist}{$thumbprint}; # if we get here, we're all good! ... Hack Salem | 14 Sep 2016 | @genehack 35
  36. 36. Server side: get the token my $auth_header = request_header 'Authorization' ; status_401 unless ( $token ) = $auth_header =~ /^Bearer (.*)$/; Hack Salem | 14 Sep 2016 | @genehack 36
  37. 37. Server side: decode the token # try to decode it and confirm valid sig, # and valid iat and exp claims my( $header, $payload ); try { ( $header, $payload ) = decode_jwt( token => $token , decode_header => 1 , accepted_alg => 'RS512' , verify_iat => 1 , verify_exp => 1 ); }; # no catch block, just drop the error, we're out of here in that case status_401 unless $header and $payload; Hack Salem | 14 Sep 2016 | @genehack 37
  38. 38. Server side: decode the token • Key in header wrong? FAILS • Not right algorithm? FAILS • Doesn't have iat and exp? FAILS ALL that validation is happening inside the library, so I don't have to worry about it. • Me? WINS Hack Salem | 14 Sep 2016 | @genehack 38
  39. 39. Server side: do more checks # check that expiration time is less than one hour status_401 unless $payload->{exp} - $payload->{iat} < 3600; # check that the included public key is on the whitelist my $pk = Crypt::PK::RSA->new; $pk->import_key($header->{jwk}); my $thumbprint = $pk->export_key_jwk_thumbprint; status_401 unless config->{whitelist}{$thumbprint}; Hack Salem | 14 Sep 2016 | @genehack 39
  40. 40. Server side: more checks • We specify in the API docs that tokens can only be valid for one hour • Have to check that ourselves • Also need to make sure this isn't some random RSA keypair • Need to make sure we know this public key Hack Salem | 14 Sep 2016 | @genehack 40
  41. 41. Server side: THAT'S ALL FOLKS # if we get here, we're all good! • If we know the public key in the header, • then we know the private key was used to sign the JWT • (or it wouldn't validate) • and therefore the JWT is from the private key holder • (who is, by definition, authorized!) Hack Salem | 14 Sep 2016 | @genehack 41
  42. 42. IMPORTANT NOTE! This does, of course, depend on the client keeping the private key actually private … But access revocation is as simple as removing a public keyprint from the whitelist. Hack Salem | 14 Sep 2016 | @genehack 42
  43. 43. Conclusions • JWTs solve some really common problems. • JWTs solve them in a pretty elegant way. • This is really pretty damn cool. Hack Salem | 14 Sep 2016 | @genehack 43
  44. 44. Conclusions • JWTs solve some really common problems. • JWTs solve them in a pretty elegant way. • This is really pretty damn cool!!! • You should think about using JWTs. Hack Salem | 14 Sep 2016 | @genehack 44
  45. 45. Questions? Hack Salem | 14 Sep 2016 | @genehack 45
  46. 46. Thanks! Hack Salem | 14 Sep 2016 | @genehack 46

×