Skip to content

Commit

Permalink
Merge pull request #145 from dunglas/default-jwt-key
Browse files Browse the repository at this point in the history
Uniformize the default JWT key with the Symfony recipe
  • Loading branch information
dunglas committed Aug 28, 2019
2 parents f9d28aa + 3ed2ba5 commit ad376cf
Show file tree
Hide file tree
Showing 10 changed files with 24 additions and 23 deletions.
2 changes: 1 addition & 1 deletion .env
Expand Up @@ -8,7 +8,7 @@ CORS_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:8000
DB_PATH=
DEBUG=1
DEMO=
JWT_KEY=!UnsecureChangeMe!
JWT_KEY=!ChangeMe!
LOG_FORMAT=JSON
PUBLISH_ALLOWED_ORIGINS=http://localhost:3000,http://localhost:8000
PUBLISHER_JWT_KEY=
Expand Down
2 changes: 1 addition & 1 deletion LoadTest.scala
Expand Up @@ -21,7 +21,7 @@ class LoadTest extends Simulation {
/** The hub URL */
val HubUrl = Properties.envOrElse("HUB_URL", "http://localhost:3001/hub" )
/** JWT to use to publish */
val Jwt = Properties.envOrElse("JWT", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.LRLvirgONK13JgacQ_VbcjySbVhkSmHy3IznH3tA9PM")
val Jwt = Properties.envOrElse("JWT", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.afLx2f2ut3YgNVFStCx95Zm_UND1mZJ69OenXaDuZL8")
/** Number of concurrent subscribers to connect */
val ConcurrentSubscribers = Properties.envOrElse("SUBSCRIBERS", "10000").toInt
/** Number of concurent publishers */
Expand Down
6 changes: 3 additions & 3 deletions README.md
Expand Up @@ -111,7 +111,7 @@ req.end();
// but any HTTP client, written in any language, will be just fine.
```

The JWT must contain a `publish` property containing an array of targets. This array can be empty to allow publishing anonymous updates only. [Example publisher JWT](https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.LRLvirgONK13JgacQ_VbcjySbVhkSmHy3IznH3tA9PM) (demo key: `!UnsecureChangeMe!`).
The JWT must contain a `publish` property containing an array of targets. This array can be empty to allow publishing anonymous updates only. [Example publisher JWT](https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.afLx2f2ut3YgNVFStCx95Zm_UND1mZJ69OenXaDuZL8) (demo key: `!ChangeMe!`).

### Other Examples

Expand Down Expand Up @@ -177,8 +177,8 @@ To run it in production mode, and generate automatically a Let's Encrypt TLS cer
JWT_KEY='myJWTKey' ACME_HOSTS='example.com' ./mercure

The value of the `ACME_HOSTS` environment variable must be updated to match your domain name(s).
A Let's Enctypt TLS certificate will be automatically generated.
If you omit this variable, the server will be exposed on an (unsecure) HTTP connection.
A Let's Encrypt TLS certificate will be automatically generated.
If you omit this variable, the server will be exposed using a not encrypted HTTP connection.

When the server is up and running, the following endpoints are available:

Expand Down
2 changes: 1 addition & 1 deletion examples/chat-python-flask/chat.py
Expand Up @@ -35,7 +35,7 @@ def chat():
targets = [os.environ.get('TARGET', 'chan')]
token = jwt.encode(
{'mercure': {'subscribe': targets, 'publish': targets}},
os.environ.get('JWT_KEY', '!UnsecureChangeMe!'),
os.environ.get('JWT_KEY', '!ChangeMe!'),
algorithm='HS256'
)

Expand Down
3 changes: 2 additions & 1 deletion examples/publisher-node.js
@@ -1,7 +1,8 @@
const http = require('http');
const querystring = require('querystring');

const demoJwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.LRLvirgONK13JgacQ_VbcjySbVhkSmHy3IznH3tA9PM';

const demoJwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.afLx2f2ut3YgNVFStCx95Zm_UND1mZJ69OenXaDuZL8';

const postData = querystring.stringify({
'topic': 'http://localhost:3000/demo/books/1.jsonld',
Expand Down
2 changes: 1 addition & 1 deletion examples/publisher-php.php
@@ -1,6 +1,6 @@
<?php

define('DEMO_JWT', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.LRLvirgONK13JgacQ_VbcjySbVhkSmHy3IznH3tA9PM');
define('DEMO_JWT', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.afLx2f2ut3YgNVFStCx95Zm_UND1mZJ69OenXaDuZL8');

$postData = http_build_query([
'topic' => 'http://localhost:3000/demo/books/1.jsonld',
Expand Down
2 changes: 1 addition & 1 deletion examples/publisher-ruby.rb
@@ -1,7 +1,7 @@
require 'json'
require 'net/http'

token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.LRLvirgONK13JgacQ_VbcjySbVhkSmHy3IznH3tA9PM'
token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.afLx2f2ut3YgNVFStCx95Zm_UND1mZJ69OenXaDuZL8'

Net::HTTP.start('localhost', 3000) do |http|
req = Net::HTTP::Post.new('/hub')
Expand Down
22 changes: 11 additions & 11 deletions hub/authorization_test.go
Expand Up @@ -7,8 +7,8 @@ import (
"github.com/stretchr/testify/assert"
)

const validEmptyHeader = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.gciTwpaT-wC-s73qBP7OQ_BMp9Oosm8YXvIpqYWddzY"
const validFullHeader = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InB1Ymxpc2giOlsiZm9vIiwiYmFyIl0sInN1YnNjcmliZSI6WyJmb28iLCJiYXoiXX19.pylpKeHDlAN2HHBayzufKYc6VqDfhjCuzlH72r1W6Nw"
const validEmptyHeader = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30._esyynAyo2Z6PyGe0mM_SuQ3c-C7sMQJ1YxVLvlj80A"
const validFullHeader = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InB1Ymxpc2giOlsiZm9vIiwiYmFyIl0sInN1YnNjcmliZSI6WyJmb28iLCJiYXoiXX19.e7USPnr2YHHqLYSu9-jEVsynuTXGtAQUDAZuzoR8lxQ"

func TestAuthorizeMultipleAuthorizationHeader(t *testing.T) {
r, _ := http.NewRequest("GET", "http://example.com/hub", nil)
Expand Down Expand Up @@ -60,7 +60,7 @@ func TestAuthorizeAuthorizationHeaderNoContent(t *testing.T) {
r, _ := http.NewRequest("GET", "http://example.com/hub", nil)
r.Header.Add("Authorization", "Bearer "+validEmptyHeader)

claims, err := authorize(r, []byte("!UnsecureChangeMe!"), []string{})
claims, err := authorize(r, []byte("!ChangeMe!"), []string{})
assert.Nil(t, claims.Mercure.Publish)
assert.Nil(t, claims.Mercure.Subscribe)
assert.Nil(t, err)
Expand All @@ -70,7 +70,7 @@ func TestAuthorizeAuthorizationHeader(t *testing.T) {
r, _ := http.NewRequest("GET", "http://example.com/hub", nil)
r.Header.Add("Authorization", "Bearer "+validFullHeader)

claims, err := authorize(r, []byte("!UnsecureChangeMe!"), []string{})
claims, err := authorize(r, []byte("!ChangeMe!"), []string{})
assert.Equal(t, []string{"foo", "bar"}, claims.Mercure.Publish)
assert.Equal(t, []string{"foo", "baz"}, claims.Mercure.Subscribe)
assert.Nil(t, err)
Expand Down Expand Up @@ -98,7 +98,7 @@ func TestAuthorizeCookieNoContent(t *testing.T) {
r, _ := http.NewRequest("GET", "http://example.com/hub", nil)
r.AddCookie(&http.Cookie{Name: "mercureAuthorization", Value: validEmptyHeader})

claims, err := authorize(r, []byte("!UnsecureChangeMe!"), []string{})
claims, err := authorize(r, []byte("!ChangeMe!"), []string{})
assert.Nil(t, claims.Mercure.Publish)
assert.Nil(t, claims.Mercure.Subscribe)
assert.Nil(t, err)
Expand All @@ -108,7 +108,7 @@ func TestAuthorizeCookie(t *testing.T) {
r, _ := http.NewRequest("GET", "http://example.com/hub", nil)
r.AddCookie(&http.Cookie{Name: "mercureAuthorization", Value: validFullHeader})

claims, err := authorize(r, []byte("!UnsecureChangeMe!"), []string{})
claims, err := authorize(r, []byte("!ChangeMe!"), []string{})
assert.Equal(t, []string{"foo", "bar"}, claims.Mercure.Publish)
assert.Equal(t, []string{"foo", "baz"}, claims.Mercure.Subscribe)
assert.Nil(t, err)
Expand All @@ -118,7 +118,7 @@ func TestAuthorizeCookieNoOriginNoReferer(t *testing.T) {
r, _ := http.NewRequest("POST", "http://example.com/hub", nil)
r.AddCookie(&http.Cookie{Name: "mercureAuthorization", Value: validFullHeader})

claims, err := authorize(r, []byte("!UnsecureChangeMe!"), []string{})
claims, err := authorize(r, []byte("!ChangeMe!"), []string{})
assert.EqualError(t, err, "An \"Origin\" or a \"Referer\" HTTP header must be present to use the cookie-based authorization mechanism")
assert.Nil(t, claims)
}
Expand All @@ -128,7 +128,7 @@ func TestAuthorizeCookieOriginNotAllowed(t *testing.T) {
r.Header.Add("Origin", "http://example.com")
r.AddCookie(&http.Cookie{Name: "mercureAuthorization", Value: validFullHeader})

claims, err := authorize(r, []byte("!UnsecureChangeMe!"), []string{"http://example.net"})
claims, err := authorize(r, []byte("!ChangeMe!"), []string{"http://example.net"})
assert.EqualError(t, err, "The origin \"http://example.com\" is not allowed to post updates")
assert.Nil(t, claims)
}
Expand All @@ -138,7 +138,7 @@ func TestAuthorizeCookieRefererNotAllowed(t *testing.T) {
r.Header.Add("Referer", "http://example.com/foo/bar")
r.AddCookie(&http.Cookie{Name: "mercureAuthorization", Value: validFullHeader})

claims, err := authorize(r, []byte("!UnsecureChangeMe!"), []string{"http://example.net"})
claims, err := authorize(r, []byte("!ChangeMe!"), []string{"http://example.net"})
assert.EqualError(t, err, "The origin \"http://example.com\" is not allowed to post updates")
assert.Nil(t, claims)
}
Expand All @@ -148,7 +148,7 @@ func TestAuthorizeCookieInvalidReferer(t *testing.T) {
r.Header.Add("Referer", "http://192.168.0.%31/")
r.AddCookie(&http.Cookie{Name: "mercureAuthorization", Value: validFullHeader})

claims, err := authorize(r, []byte("!UnsecureChangeMe!"), []string{"http://example.net"})
claims, err := authorize(r, []byte("!ChangeMe!"), []string{"http://example.net"})
assert.EqualError(t, err, "parse http://192.168.0.%31/: invalid URL escape \"%31\"")
assert.Nil(t, claims)
}
Expand All @@ -159,7 +159,7 @@ func TestAuthorizeCookieOriginHasPriority(t *testing.T) {
r.Header.Add("Referer", "http://example.com")
r.AddCookie(&http.Cookie{Name: "mercureAuthorization", Value: validFullHeader})

claims, err := authorize(r, []byte("!UnsecureChangeMe!"), []string{"http://example.net"})
claims, err := authorize(r, []byte("!ChangeMe!"), []string{"http://example.net"})
assert.Equal(t, []string{"foo", "bar"}, claims.Mercure.Publish)
assert.Equal(t, []string{"foo", "baz"}, claims.Mercure.Subscribe)
assert.Nil(t, err)
Expand Down
2 changes: 1 addition & 1 deletion public/app.js
Expand Up @@ -3,7 +3,7 @@
(function () {
const origin = window.location.origin;
const defaultTopic = origin + '/demo/books/1.jsonld';
const defaultJwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.LRLvirgONK13JgacQ_VbcjySbVhkSmHy3IznH3tA9PM';
const defaultJwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.afLx2f2ut3YgNVFStCx95Zm_UND1mZJ69OenXaDuZL8';

const settingsForm = document.forms.settings;
const discoverForm = document.forms.discover;
Expand Down
4 changes: 2 additions & 2 deletions public/index.html
Expand Up @@ -63,8 +63,8 @@ <h1 class="title is-2">Settings</h1>
"publish": ["list of authorized targets, * for all, omit to not allow to publish"]
}
}</code></pre><br>
<a href="https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.LRLvirgONK13JgacQ_VbcjySbVhkSmHy3IznH3tA9PM" target="_blank" class="button is-link is-small">Create a token</a>
(demo key: <code>!UnsecureChangeMe!</code>)
<a href="https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6WyJmb28iLCJiYXIiXSwicHVibGlzaCI6WyJmb28iXX19.afLx2f2ut3YgNVFStCx95Zm_UND1mZJ69OenXaDuZL8" target="_blank" class="button is-link is-small">Create a token</a>
(demo key: <code>!ChangeMe!</code>)
</p>
</div>
</form>
Expand Down

0 comments on commit ad376cf

Please sign in to comment.