-
-
Save pengw00/40438bc707a2aa3fd2ce7df87708e20f to your computer and use it in GitHub Desktop.
Revisions
-
soulmachine revised this gist
Nov 15, 2017 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,7 +2,7 @@ First of all, please note that token expiration and revoking are two different t 1. Expiration only happens for web apps, not for native mobile apps, because native apps never expire. 2. Revoking only happens when (1) uses click the logout button on the website or native Apps;(2) users reset their passwords; (3) users revoke their tokens explicitly in the administration panel. ### 1. How to hadle JWT expiration A JWT token that never expires is dangerous if the token is stolen then someone can always access the user's data. @@ -60,7 +60,7 @@ There are three ways: Suggestions are welcomed, please correct me if I'm wrong. ### 3. How to use JWT tokens securely First, always use HTTPS to make sure JWT tokens transmission over network is safe. By using HTTPS nobody can sniff users' JWT tokens over network. -
soulmachine revised this gist
Nov 15, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -62,7 +62,7 @@ Suggestions are welcomed, please correct me if I'm wrong. ### 3. How to use JWT tokens Securely First, always use HTTPS to make sure JWT tokens transmission over network is safe. By using HTTPS nobody can sniff users' JWT tokens over network. Second, make sure JWT tokens are stored securely on users' Android, iOS and browser. -
soulmachine revised this gist
Nov 15, 2017 . 1 changed file with 5 additions and 14 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -62,26 +62,17 @@ Suggestions are welcomed, please correct me if I'm wrong. ### 3. How to use JWT tokens Securely First, always use HTTPS to make sure JWT tokens transmission over network is safe. Second, make sure JWT tokens are stored securely on users' Android, iOS and browser. * For Android, store tokens in KeyStore * For iOS, store tokens in KeyChain * For browsers, use `HttpOnly` and `Secure` cookies. cookie. The `HttpOnly` flag protects the cookies from being accessed by JavaScript and prevents XSS attack. The `Secure` flag will only allow cookies to be sent to servers over HTTPS connection. **As long as we make the browsers, user devices and tokens transmission safe, token revocation mechanism is not necessary anymore.We can still keep our RESTful services stateless.** ### Reference 1. [RFC 7519 - JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519) 2. [Use Redis to revoke Tokens generated from jsonwebtoken](http://www.kdelemme.com/2014/05/12/use-redis-to-revoke-tokens-generated-from-jsonwebtoken/) -
soulmachine revised this gist
Nov 15, 2017 . 1 changed file with 10 additions and 10 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -17,17 +17,17 @@ So the answer is obvious, set the expiration date in the `exp` claim and reject Quite easy, huh? The problem is that mobile apps never expire, for example, people can reopen the APP after a month without the need to login again. 1. For Web Apps: If you set the expiration time to 1 week, do not use the token for 1 week. Use it less than a week and get a new token before the old token expires. For example, make the browser send out a request to exchange for a new token at the sixth day. This is not different than the normal concept of session and cookies. Accordingly, on the server side, create a restful API named `/token/extend` which will return a new token if given a valid token. If the user does not use your application for a week, next time he goes to your app, he will have to login again and this is fine and widely accepted. 2. For native mobile Apps: you can use the same explained above, but that's not how mobile Apps work nowadays, e.g., an user can open the Facebook App after a month not using it and next time when he open the App he doesn't need to login again. One solution is to add an audience claim named `aud` to JWT tokens, for example, use the payload like `{"sub": "username", "exp": "2015-11-18T18:25:43.511Z", "aud":"iPhone-App"}`. On the server side if the token has an `aud` field that has the value `iPhone-App` then ignore the `exp` claim, so that tokens with `iPhone-App` never expire. However, you can still revoke this kind of tokens by using the methods described in Section 2. Another solution is to use a refresh token that never expires to fetch a new JWT token that does expire. Since the refresh token never expires, what happens if your phone is stolen? Again, refresh tokens are still valid JWT token, you can revoke refresh tokens using the methods described in Section 2. Normally to distinguish with different refresh tokens of one user, a good practice is to put the specific device name into the refresh token, for example, `{"sub": "username", "exp": "2015-11-18T18:25:43.511Z", "device":"Frank's iPhone"}`, so that when a user wants to revoke refresh tokens, he can know this refresh token is being used on his iPhone. @@ -40,14 +40,14 @@ Assume that each user has multiple devices, let's say, a browser, a native iPhon There are three ways: 1. Changing the secret key. This will revoke all tokens of all users, which is not acceptable. 2. Make each user has his own secret and just change the secret of a specified user. Now the RESTful backend is not stateless anymore. Every time a request comes in the server needs to query the database to get the secret of a user. To get better performance let's store the `(user, secret)` pairs in Redis instead of MySQL, use the `username` as the key and the `secret` as the value. This way will revoke all tokens of one user, much better, but still not good enough. 3. Store the revoked JWT tokens in Redis. Use the token as the key and the value is always a boolean `true`. @@ -64,13 +64,13 @@ Suggestions are welcomed, please correct me if I'm wrong. Assume that backend servers are safe so that the secret won't be leaked. We just need to make sure that the browsers and devices used by users are safe, and tokens transmission is safe. To make the browser safe, since the token will be stored in cookies, we need to use `HttpOnly` and `Secure` cookies. The `HttpOnly` flag protects the cookies from being accessed by JavaScript and prevents XSS attack. The `Secure` flag will only allow cookies to be sent to servers over HTTPS connection. To make the native App safe, please store the access token in KeyStore on Android and KeyChain on iOS. To make tokens transmission safe, always transmit tokens over HTTPS connection, so that no one can sniff the tokens on network. **As long as we make the browsers, user devices and tokens transmission safe, token revocation mechanism is not necessary anymore.We can still keep our RESTful services stateless.** -
soulmachine revised this gist
Nov 14, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -79,7 +79,7 @@ To make tokens transmission safe, only transmit tokens over HTTPS connection, * For Android, KeyStore * For iOS, KeyChain * For browsers, cookie. Make sure your cookie has `secure` and `httponly` properties, so that your cookie can not be accessed by JavaScript(to prevent XSS attack) and can only transport over HTTPS ### Reference -
soulmachine revised this gist
Nov 14, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -75,7 +75,7 @@ To make tokens transmission safe, only transmit tokens over HTTPS connection, **As long as we make the browsers, user devices and tokens transmission safe, token revocation mechanism is not necessary anymore.We can still keep our RESTful services stateless.** ## 4. How to store JWT token on users' device safely? * For Android, KeyStore * For iOS, KeyChain -
soulmachine revised this gist
Nov 14, 2017 . 1 changed file with 8 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -74,6 +74,14 @@ To make tokens transmission safe, only transmit tokens over HTTPS connection, **As long as we make the browsers, user devices and tokens transmission safe, token revocation mechanism is not necessary anymore.We can still keep our RESTful services stateless.** ## 4. How to safe JWT token safely on users' device? * For Android, KeyStore * For iOS, KeyChain * For browsers, TODO ### Reference 1. [RFC 7519 - JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519) 2. [Use Redis to revoke Tokens generated from jsonwebtoken](http://www.kdelemme.com/2014/05/12/use-redis-to-revoke-tokens-generated-from-jsonwebtoken/) -
soulmachine created this gist
Nov 14, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,83 @@ First of all, please note that token expiration and revoking are two different things. 1. Expiration only happens for web apps, not for native mobile apps, because native apps never expire. 2. Revoking only happens when (1) uses click the logout button on the website or native Apps;(2) users reset their passwords; (3) users revoke their tokens explicitly in the administration panel. ### 1. How to make a JWT token expire A JWT token that never expires is dangerous if the token is stolen then someone can always access the user's data. Quoted from [JWT RFC](https://tools.ietf.org/html/rfc7519): > The "exp" (expiration time) claim identifies the expiration time on or > after which the JWT MUST NOT be accepted for processing. The > processing of the "exp" claim requires that the current date/time MUST > be before the expiration date/time listed in the "exp" claim. So the answer is obvious, set the expiration date in the `exp` claim and reject the token on the server side if the date in the `exp` claim is before the current date. Quite easy, huh? The hard problem is, mobile apps never expire, for example, people can reopen the APP after a month without the need to login again. 1. For Web Apps: If you set the expiration time to 1 week, do not use the token for 1 week. Use it less than a week and get a new token before the old token expires. For example, make the browser send out a request to exchange for a new token at the sixth day. This is not different than the normal concept of session and cookies. Accordingly, on the server side, create a restful API named `/token/extend` which will return a new token if given a valid token. If the user does not use your application for a week, next time he goes to your app, he will have to login again and this is fine and widely accepted. 2. For native mobile Apps: you can use the same explained above, but that's not how most of the mobile Apps work these days, I can open the Facebook App after a month without using it and I'm sure I will not need to login again. One way is to add an audience claim named `aud` to JWT tokens, for example, use the payload like `{"sub": "username", "exp": "2015-11-18T18:25:43.511Z", "aud":"iPhone-App"}`. On the server side if the token has an `aud` field that has the value `iPhone-App` then ignore the `exp` claim, so that tokens with `iPhone-App` never expire. However, you can still revoke this kind of tokens by using the methods described in Section 2. Another way is to use a refresh token that never expires to fetch a new JWT token that does expire. Since the refresh token never expires, what happens if your phone is stolen? Again, refresh tokens are still valid JWT token, you can revoke refresh tokens using the methods described in Section 2. Normally to distinguish with different refresh tokens of one user, a good practice is to put the specific device name into the refresh token, for example, `{"sub": "username", "exp": "2015-11-18T18:25:43.511Z", "device":"Frank's iPhone"}`, so that when a user wants to revoke refresh tokens, he can know this refresh token is being used on his iPhone. ### 2. How to revoke a JWT token Sometimes users need to revoke a token, for example, clicking the logout button, or changing the password. Assume that each user has multiple devices, let's say, a browser, a native iPhone APP, and a native Android APP. There are three ways: 1. Changing the secret key. This will revoke all tokens of all users, which is too wild. 2. Make each user has his own secret and just change the secret of a specified user. Now the RESTful backend is not stateless anymore. Every time a request comes in the server needs to query the database to get the secret of a user. To get better performance let's store the `(user, secret)` pairs in Redis instead of MySQL, use the `username` as the key and the `secret` as the value. This way will revoke all tokens of one user, much better, but still not enough. 3. Store the revoked JWT tokens in Redis. Use the token as the key and the value is always a boolean `true`. The token will be stored only for a specific amount of time, which is the time in the `exp` claim, after the expiration time it will be deleted from Redis. This way only revokes just one token at a time, perfect! For more details please refer to this blog, [Use Redis to revoke Tokens generated from jsonwebtoken](http://www.kdelemme.com/2014/05/12/use-redis-to-revoke-tokens-generated-from-jsonwebtoken/) Suggestions are welcomed, please correct me if I'm wrong. ### 3. How to use JWT tokens Securely Assume that backend servers are safe so that the secret won't be leaked. We just need to make sure that the browsers and devices used by users are safe, and tokens transmission is safe. To make the browser safe, since the token will be stored in cookies, we need to use `HttpOnly` and `Secure` cookies. The `HttpOnly` flag protects the cookies from being accessed by JavaScript and prevents XSS attack. The `Secure` flag will only allow cookies to be sent to servers over HTTPS connection. To make the native App safe, please store the access token in a place that can not be touched by malicious Apps, this is beyond this article. To make tokens transmission safe, only transmit tokens over HTTPS connection, so that no one can sniff the tokens in the network. **As long as we make the browsers, user devices and tokens transmission safe, token revocation mechanism is not necessary anymore.We can still keep our RESTful services stateless.** ### Reference 1. [RFC 7519 - JSON Web Token (JWT)](https://tools.ietf.org/html/rfc7519) 2. [Use Redis to revoke Tokens generated from jsonwebtoken](http://www.kdelemme.com/2014/05/12/use-redis-to-revoke-tokens-generated-from-jsonwebtoken/) 3. [I don’t see the point in Revoking or Blacklisting JWT](http://www.dinochiesa.net/?p=1388) 4. [JSON Web Tokens | Hacker News](https://news.ycombinator.com/item?id=8283006) 5. [Blacklisting JSON Web Token API Keys](https://auth0.com/blog/2015/03/10/blacklist-json-web-token-api-keys/) 6. [Token Based Authentication for Single Page Apps (SPAs)](https://stormpath.com/blog/token-auth-spa/)