Securing Web Applications with Token Authentication Micah Silverman @afitnerd Co-Author, Mastering Enterprise JavaBeans 3.0 Java Developer Evangelist, Stormpath
About Stormpath • Authentication & User Management API • Hosted data store w/ advanced crypto • Centralize user login across your applications • Multi-tenant support for your SaaS • Active Directory, LDAP, social connections • API authentication & token authentication • Supported, Free tier for developers
Overview • Security Concerns for Modern Web Apps • Cookies: need to know • Session ID Problems • Token Authentication to the rescue! • OAuth2 & Java Example
Security Concerns for Modern Web Apps • SPAs and Mobile apps are ‘Untrusted Clients’ • Prevent malicious code • Secure user credentials • Secure server endpoints (API) • Expose Access Control rules to the Client
Prevent Malicious Code • Cross-Site Scripting (XSS) attacks are a real, huge threat
Prevent Malicious Code Cross-Site Scripting (XSS) attacks https://www.owasp.org/index.php/XSS
XSS Attack Demo https://www.google.com/about/appsecurity/ learning/xss/#BasicExample
XSS Attack – What Can I Do? Read EVERYTHING on this page: https://www.owasp.org/index.php/XSS And then do these things: https://www.owasp.org/index.php/ XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet
XSS Attack – What Can I Do? Escape Content! Dynamic HTML: use well-known, trusted libraries. Do NOT roll your own. DOM attacks: escape user input
XSS Attack – What Can I Do? SPAs: frameworks like Angular probably do a lot of work for you (e.g. preventing DOM attacks by escaping user input). You should still read up on it.
Secure User Credentials • Traditionally, we have used Session IDs • This is OK, as long as you do cookies ‘right’ • Authentication Tokens are better ☺ (more on this later)
Overview • Security Concerns for Modern Web Apps • Cookies: need to know • Session ID Problems • Token Authentication to the rescue! • Java Example
Session ID Cookies
Secure Server (API) Endpoints • Traditionally use Session ID Cookies • Session ID à Session à User identity • Use framework like Apache Shiro or Spring Security to assert security rules
Expose Access Control Rules to the Client • Traditional solution: • Session ID à Session à User data in your DB • Provide a /me or /profile endpoint • Access Tokens are better!
Let’s talk about cookies...
Cookies are OK! If you do them correctly Cookies can be easily compromised: • Man-in-the-Middle (MITM) attacks • Cross-Site Request Forgery (CSRF)
Someone ‘listening on the wire’ between the browser and server can see and copy the cookie. Solutions • Use HTTPS everywhere • TLS everywhere on internal networks
Cross-Site Request Forgery (CSRF) "... occurs when a malicious web site, email, blog, instant message or program causes a user’s web browser to perform an unwanted action on a trusted site for which the user is currently authenticated"
 https://www.owasp.org/index.php/ CrossSite_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
Cross-Site Request Forgery (CSRF) Attacker enables a user to request your server. Example:
 <a href="https://yoursite.com/ transferMoney?to=BadGuy&amount=10000"> See Cute Cats! </a> What happens?
Cross-Site Request Forgery (CSRF) • The attacker cannot see your cookie values, BUT: • The browser says, "The request is going to your server, so I’ll happily send you your cookies." • Your server transfers the money because it ‘sees’ a valid, non-expired session id cookie for an authenticated session.
Cross-Site Request Forgery (CSRF) Solutions • Synchronizer Token • Double-Submit Cookie • Origin header check
Synchronizer Token – Trusted Page
Synchronizer Token – Foreign Page
Synchronizer Token - Considerations • Requires cooperation from your rendering layer • Requires you to store tokens in a data store or cache • Difficult to do with static SPA content • Only protects against forged POST requests, not GET requests! Pro tip: never allow GETs to modify server state!
Double Submit Cookie • Send two cookies: Session ID + Random Value • Send random value explicitly, browser Same- Origin-Policy • Best Way: send as a custom header
Double Submit Cookie
Double Submit Cookie Considerations • Custom HTTP header, do what makes sense for your app • Still vulnerable to XSS - Random Value still accessible to the JS environment. • Protect against XSS!
Origin header check • Browsers send Origin header • Header value is the domain of the page initiating the request • Cannot be hacked via browser JS 
 (could still be modified by a malicious HTTP proxy server)
Overview • Security Concerns for Modern Web Apps • Cookies: need to know • Session ID Problems • Token Authentication to the rescue! • Java Example
Session ID Problems • They’re opaque and have no meaning themselves (they’re just ‘pointers’). • Service-oriented architectures might need a centralized ID de-referencing service
Session ID Problems • Opaque IDs mean clients can’t inspect them and find out what it is allowed to do or not - it needs to make more requests for this information.
Session ID Problems • Sessions = Server State! • You need to store that state somewhere • Session ID à look up server state on *every request*. • Really not good for distributed/clustered apps • Really not good for scale
Overview • Security Concerns for Modern Web Apps • Cookies: need to know • Session ID Problems • Token Authentication to the rescue! • Java Example
Token Authentication • What is Authentication? • What is a Token?
JSON Web Tokens (JWT) • A URL-safe, compact, self-contained string with meaningful information that is usually digitally signed or encrypted. • The string is ‘opaque’ and can be used as a ‘token’. • Many OAuth2 implementations use JWTs as OAuth2 Access Tokens.
JSON Web Tokens (JWT) • You can store them in cookies! But all those cookie rules still apply. • You can entirely replace your session ID with a JWT.
JSON Web Tokens (JWT) In the wild they look like just another ugly string: eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJ   pc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQo   gImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnV   lfQ.dBjftJeZ4CVPmB92K27uhbUJU1p1r_wW1gFWFOEj   Xk
JSON Web Tokens (JWT) In the wild they look like just another ugly string: eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJ   pc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQo   gImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnV   lfQ.dBjftJeZ4CVPmB92K27uhbUJU1p1r_wW1gFWFOEj   Xk
JSON Web Tokens (JWT) In the wild they look like just another ugly string: eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJ   pc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQo   gImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnV   lfQ.dBjftJeZ4CVPmB92K27uhbUJU1p1r_wW1gFWFOEj   Xk
JSON Web Tokens (JWT) But they do have a three part structure. Each part is a Base64-encoded string: eyJ0eXAiOiJKV1QiLA0KICJhb   GciOiJIUzI1NiJ9   .   eyJpc3MiOiJqb2UiLA0KICJle   HAiOjEzMDA4MTkzODAsDQogIm   h0dHA6Ly9leGFtcGxlLmNvbS9   pc19yb290Ijp0cnVlfQ   .   dBjftJeZ4CVPmB92K27uhbUJU   1p1r_wW1gFWFOEjXk Header Body  (‘Claims’) Cryptographic  Signature
JSON Web Tokens (JWT) Base64-decode the parts to find the juicy bits: {    "typ":"JWT",    "alg":"HS256"   } {    "iss":"http://trustyapp.com/",    "exp":  1300819380,    "sub":  "users/8983462",    "scope":  "self  api/buy"   } tß´—™à%O˜v+nî…SZu¯ˉµ€U…8H× Header Body  (‘Claims’) Cryptographic  Signature
JSON Web Tokens (JWT) The claims body is the best part! It can tell: {    "iss":"http://trustyapp.com/",    "exp":  1300819380,    "sub":  "users/8983462",    "scope":  "self  api/buy"   } Who  issued  the  token
JSON Web Tokens (JWT) The claims body is the best part! It can tell: {    "iss":"http://trustyapp.com/",    "exp":  1300819380,    "sub":  "users/8983462",    "scope":  "self  api/buy"   } Who  issued  the  token When  it  expires
JSON Web Tokens (JWT) The claims body is the best part! It can tell: {    "iss":"http://trustyapp.com/",    "exp":  1300819380,    "sub":  "users/8983462",    "scope":  "self  api/buy"   } Who  issued  the  token When  it  expires Who  it  represents
JSON Web Tokens (JWT) The claims body is the best part! It can tell: {    "iss":"http://trustyapp.com/",    "exp":  1300819380,    "sub":  "users/8983462",    "scope":  "self  api/buy"   } Who  issued  the  token When  it  expires Who  it  represents What  they  can  do
JSON Web Tokens (JWT) Great! Why is this useful?
 • Implicitly trusted because it is cryptographically signed (verified not tampered). • It is structured, enabling inter-op between services • It can inform your client about basic access control rules (permissions)* • And the big one: statelessness! *servers must always enforce access control policies
JSON Web Tokens (JWT) So, what’s the catch?
 • Implicit trust is a tradeoff – how long should the token be good for? how will you revoke it? (Another talk: refresh tokens) • You still have to secure your cookies! • You have to be mindful of what you store in the JWT if they are not encrypted. No sensitive info!
How do you do it on the JVM? JJWT is awesome https://github.com/jwtk/jjwt
How do you do it on the JVM? import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; byte[] key = getSignatureKey(); String jwt = Jwts.builder().setIssuer("http://trustyapp.com/") .setSubject("users/1300819380") .setExpiration(expirationDate) .put("scope", "self api/buy") .signWith(SignatureAlgorithm.HS256,key) .compact(); Create  a  JWT:
How do you do it on the JVM? Verify  a  JWT: try { Jws<Claims> jwtClaims = Jwts.parser().setSigningKey(key).parseClaimsJws(jwt); //OK, we can trust this JWT } catch (SignatureException e) { //don't trust the JWT! }
How do you get a Token?
Example: your SPA, your server
1. Token Request POST /oauth/token HTTP/1.1 Origin: https://foo.com Content-Type: application/x-www-form-urlencoded grant_type=password&username=username&password=p assword *Assert  allowed  origin  for  browser-­‐based  apps
2. Token Response HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache { "access_token":"2YotnFZFEjr1zCsicMWpAA...", "token_type":"example", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA...", "example_parameter":"example_value" }
3. Resource Request GET /admin HTTP/1.1 Authorization: Bearer 2YotnFZFEjr1zCsicMW...
Example: Token Request using an API Key POST /token HTTP/1.1 Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=apiKeyId&clie nt_secret=apiKeySecret *Assert  allowed  origin  for  browser-­‐based  apps
Demo!
Thanks! @afitnerd @goStormpath • Token Authentication for Java, JEE, Spring and Spring Boot • Free Supported Developer Tier • Elegant API • OSS Java SDKs + Tutorials Get a Free-Forever Account: Stormpath.com

Securing Web Applications with Token Authentication

  • 1.
    Securing Web Applications withToken Authentication Micah Silverman @afitnerd Co-Author, Mastering Enterprise JavaBeans 3.0 Java Developer Evangelist, Stormpath
  • 2.
    About Stormpath • Authentication& User Management API • Hosted data store w/ advanced crypto • Centralize user login across your applications • Multi-tenant support for your SaaS • Active Directory, LDAP, social connections • API authentication & token authentication • Supported, Free tier for developers
  • 3.
    Overview • Security Concernsfor Modern Web Apps • Cookies: need to know • Session ID Problems • Token Authentication to the rescue! • OAuth2 & Java Example
  • 4.
    Security Concerns forModern Web Apps • SPAs and Mobile apps are ‘Untrusted Clients’ • Prevent malicious code • Secure user credentials • Secure server endpoints (API) • Expose Access Control rules to the Client
  • 5.
    Prevent Malicious Code •Cross-Site Scripting (XSS) attacks are a real, huge threat
  • 6.
    Prevent Malicious Code Cross-SiteScripting (XSS) attacks https://www.owasp.org/index.php/XSS
  • 7.
  • 8.
    XSS Attack –What Can I Do? Read EVERYTHING on this page: https://www.owasp.org/index.php/XSS And then do these things: https://www.owasp.org/index.php/ XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet
  • 9.
    XSS Attack –What Can I Do? Escape Content! Dynamic HTML: use well-known, trusted libraries. Do NOT roll your own. DOM attacks: escape user input
  • 10.
    XSS Attack –What Can I Do? SPAs: frameworks like Angular probably do a lot of work for you (e.g. preventing DOM attacks by escaping user input). You should still read up on it.
  • 11.
    Secure User Credentials •Traditionally, we have used Session IDs • This is OK, as long as you do cookies ‘right’ • Authentication Tokens are better ☺ (more on this later)
  • 12.
    Overview • Security Concernsfor Modern Web Apps • Cookies: need to know • Session ID Problems • Token Authentication to the rescue! • Java Example
  • 13.
  • 14.
    Secure Server (API)Endpoints • Traditionally use Session ID Cookies • Session ID à Session à User identity • Use framework like Apache Shiro or Spring Security to assert security rules
  • 15.
    Expose Access ControlRules to the Client • Traditional solution: • Session ID à Session à User data in your DB • Provide a /me or /profile endpoint • Access Tokens are better!
  • 16.
  • 17.
    Cookies are OK!If you do them correctly Cookies can be easily compromised: • Man-in-the-Middle (MITM) attacks • Cross-Site Request Forgery (CSRF)
  • 18.
    Someone ‘listening onthe wire’ between the browser and server can see and copy the cookie. Solutions • Use HTTPS everywhere • TLS everywhere on internal networks
  • 19.
    Cross-Site Request Forgery(CSRF) "... occurs when a malicious web site, email, blog, instant message or program causes a user’s web browser to perform an unwanted action on a trusted site for which the user is currently authenticated"
 https://www.owasp.org/index.php/ CrossSite_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
  • 20.
    Cross-Site Request Forgery(CSRF) Attacker enables a user to request your server. Example:
 <a href="https://yoursite.com/ transferMoney?to=BadGuy&amount=10000"> See Cute Cats! </a> What happens?
  • 21.
    Cross-Site Request Forgery(CSRF) • The attacker cannot see your cookie values, BUT: • The browser says, "The request is going to your server, so I’ll happily send you your cookies." • Your server transfers the money because it ‘sees’ a valid, non-expired session id cookie for an authenticated session.
  • 22.
    Cross-Site Request Forgery(CSRF) Solutions • Synchronizer Token • Double-Submit Cookie • Origin header check
  • 23.
  • 24.
  • 25.
    Synchronizer Token -Considerations • Requires cooperation from your rendering layer • Requires you to store tokens in a data store or cache • Difficult to do with static SPA content • Only protects against forged POST requests, not GET requests! Pro tip: never allow GETs to modify server state!
  • 26.
    Double Submit Cookie •Send two cookies: Session ID + Random Value • Send random value explicitly, browser Same- Origin-Policy • Best Way: send as a custom header
  • 27.
  • 28.
    Double Submit CookieConsiderations • Custom HTTP header, do what makes sense for your app • Still vulnerable to XSS - Random Value still accessible to the JS environment. • Protect against XSS!
  • 29.
    Origin header check •Browsers send Origin header • Header value is the domain of the page initiating the request • Cannot be hacked via browser JS 
 (could still be modified by a malicious HTTP proxy server)
  • 30.
    Overview • Security Concernsfor Modern Web Apps • Cookies: need to know • Session ID Problems • Token Authentication to the rescue! • Java Example
  • 31.
    Session ID Problems •They’re opaque and have no meaning themselves (they’re just ‘pointers’). • Service-oriented architectures might need a centralized ID de-referencing service
  • 32.
    Session ID Problems •Opaque IDs mean clients can’t inspect them and find out what it is allowed to do or not - it needs to make more requests for this information.
  • 33.
    Session ID Problems •Sessions = Server State! • You need to store that state somewhere • Session ID à look up server state on *every request*. • Really not good for distributed/clustered apps • Really not good for scale
  • 34.
    Overview • Security Concernsfor Modern Web Apps • Cookies: need to know • Session ID Problems • Token Authentication to the rescue! • Java Example
  • 35.
    Token Authentication • Whatis Authentication? • What is a Token?
  • 36.
    JSON Web Tokens(JWT) • A URL-safe, compact, self-contained string with meaningful information that is usually digitally signed or encrypted. • The string is ‘opaque’ and can be used as a ‘token’. • Many OAuth2 implementations use JWTs as OAuth2 Access Tokens.
  • 37.
    JSON Web Tokens(JWT) • You can store them in cookies! But all those cookie rules still apply. • You can entirely replace your session ID with a JWT.
  • 38.
    JSON Web Tokens(JWT) In the wild they look like just another ugly string: eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJ   pc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQo   gImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnV   lfQ.dBjftJeZ4CVPmB92K27uhbUJU1p1r_wW1gFWFOEj   Xk
  • 39.
    JSON Web Tokens(JWT) In the wild they look like just another ugly string: eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJ   pc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQo   gImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnV   lfQ.dBjftJeZ4CVPmB92K27uhbUJU1p1r_wW1gFWFOEj   Xk
  • 40.
    JSON Web Tokens(JWT) In the wild they look like just another ugly string: eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJ   pc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQo   gImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnV   lfQ.dBjftJeZ4CVPmB92K27uhbUJU1p1r_wW1gFWFOEj   Xk
  • 41.
    JSON Web Tokens(JWT) But they do have a three part structure. Each part is a Base64-encoded string: eyJ0eXAiOiJKV1QiLA0KICJhb   GciOiJIUzI1NiJ9   .   eyJpc3MiOiJqb2UiLA0KICJle   HAiOjEzMDA4MTkzODAsDQogIm   h0dHA6Ly9leGFtcGxlLmNvbS9   pc19yb290Ijp0cnVlfQ   .   dBjftJeZ4CVPmB92K27uhbUJU   1p1r_wW1gFWFOEjXk Header Body  (‘Claims’) Cryptographic  Signature
  • 42.
    JSON Web Tokens(JWT) Base64-decode the parts to find the juicy bits: {    "typ":"JWT",    "alg":"HS256"   } {    "iss":"http://trustyapp.com/",    "exp":  1300819380,    "sub":  "users/8983462",    "scope":  "self  api/buy"   } tß´—™à%O˜v+nî…SZu¯ˉµ€U…8H× Header Body  (‘Claims’) Cryptographic  Signature
  • 43.
    JSON Web Tokens(JWT) The claims body is the best part! It can tell: {    "iss":"http://trustyapp.com/",    "exp":  1300819380,    "sub":  "users/8983462",    "scope":  "self  api/buy"   } Who  issued  the  token
  • 44.
    JSON Web Tokens(JWT) The claims body is the best part! It can tell: {    "iss":"http://trustyapp.com/",    "exp":  1300819380,    "sub":  "users/8983462",    "scope":  "self  api/buy"   } Who  issued  the  token When  it  expires
  • 45.
    JSON Web Tokens(JWT) The claims body is the best part! It can tell: {    "iss":"http://trustyapp.com/",    "exp":  1300819380,    "sub":  "users/8983462",    "scope":  "self  api/buy"   } Who  issued  the  token When  it  expires Who  it  represents
  • 46.
    JSON Web Tokens(JWT) The claims body is the best part! It can tell: {    "iss":"http://trustyapp.com/",    "exp":  1300819380,    "sub":  "users/8983462",    "scope":  "self  api/buy"   } Who  issued  the  token When  it  expires Who  it  represents What  they  can  do
  • 47.
    JSON Web Tokens(JWT) Great! Why is this useful?
 • Implicitly trusted because it is cryptographically signed (verified not tampered). • It is structured, enabling inter-op between services • It can inform your client about basic access control rules (permissions)* • And the big one: statelessness! *servers must always enforce access control policies
  • 48.
    JSON Web Tokens(JWT) So, what’s the catch?
 • Implicit trust is a tradeoff – how long should the token be good for? how will you revoke it? (Another talk: refresh tokens) • You still have to secure your cookies! • You have to be mindful of what you store in the JWT if they are not encrypted. No sensitive info!
  • 49.
    How do youdo it on the JVM? JJWT is awesome https://github.com/jwtk/jjwt
  • 50.
    How do youdo it on the JVM? import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; byte[] key = getSignatureKey(); String jwt = Jwts.builder().setIssuer("http://trustyapp.com/") .setSubject("users/1300819380") .setExpiration(expirationDate) .put("scope", "self api/buy") .signWith(SignatureAlgorithm.HS256,key) .compact(); Create  a  JWT:
  • 51.
    How do youdo it on the JVM? Verify  a  JWT: try { Jws<Claims> jwtClaims = Jwts.parser().setSigningKey(key).parseClaimsJws(jwt); //OK, we can trust this JWT } catch (SignatureException e) { //don't trust the JWT! }
  • 52.
    How do youget a Token?
  • 53.
    Example: your SPA,your server
  • 54.
    1. Token Request POST/oauth/token HTTP/1.1 Origin: https://foo.com Content-Type: application/x-www-form-urlencoded grant_type=password&username=username&password=p assword *Assert  allowed  origin  for  browser-­‐based  apps
  • 55.
    2. Token Response HTTP/1.1200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache { "access_token":"2YotnFZFEjr1zCsicMWpAA...", "token_type":"example", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA...", "example_parameter":"example_value" }
  • 56.
    3. Resource Request GET/admin HTTP/1.1 Authorization: Bearer 2YotnFZFEjr1zCsicMW...
  • 57.
    Example: Token Requestusing an API Key POST /token HTTP/1.1 Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=apiKeyId&clie nt_secret=apiKeySecret *Assert  allowed  origin  for  browser-­‐based  apps
  • 58.
  • 59.
    Thanks! @afitnerd @goStormpath • TokenAuthentication for Java, JEE, Spring and Spring Boot • Free Supported Developer Tier • Elegant API • OSS Java SDKs + Tutorials Get a Free-Forever Account: Stormpath.com