|
|
@@ -1,113 +1,51 @@
|
|
1
|
|
-Token authentication Prosody plugin
|
|
|
1
|
+JWT token authentication Prosody plugin
|
|
2
|
2
|
==================
|
|
3
|
3
|
|
|
4
|
|
-This plugin implements Prosody authentication provider that verifies client connection based on authentication token.
|
|
|
4
|
+This plugin implements Prosody authentication provider that verifies client connection based on JWT token described in [RFC7519].
|
|
5
|
5
|
It allows to use any external form of authentication with lib-jitsi-meet. Once your user authenticates you need to
|
|
6
|
|
-generate the token with formula described in "Token generation mechanism" and pass it to your client app. When it
|
|
7
|
|
-connects using valid token is considered authenticated by jitsi-meet system.
|
|
|
6
|
+generate the JWT token as described in the RFC and pass it to your client app. Once it connects with valid token is considered authenticated by jitsi-meet system.
|
|
8
|
7
|
|
|
9
|
|
-From XMPP perspective this is SASL PLAIN authentication where token is passed as a password. The username can be
|
|
10
|
|
-supplied by your application. By default it is generated randomly in lib-jitsi-meet. Keep in mind that JiCoFo is using
|
|
11
|
|
-"focus" as it's MUC nickname, so you should avoid allowing this name for other users.
|
|
|
8
|
+During configuration you will need to provide the *application ID* that identifies the client and a *secret* shared by both server and JWT token generator. Like described in the RFC, secret is used to compute HMAC hash value which allows to authenticate generated token. There are many existing libraries which can be used to implement token generator. More info can be found here: [http://jwt.io/#libraries-io]
|
|
12
|
9
|
|
|
13
|
|
-### Token generation mechanism
|
|
|
10
|
+[RFC7519]: https://tools.ietf.org/html/rfc7519
|
|
|
11
|
+[http://jwt.io/#libraries-io]: http://jwt.io/#libraries-io
|
|
14
|
12
|
|
|
15
|
|
-Authentication token is SHA256 hash of the following string:
|
|
|
13
|
+### Token structure
|
|
16
|
14
|
|
|
17
|
|
-*roomName + ts + appId + appSecret*
|
|
|
15
|
+The following JWT claims are used in authentication token:
|
|
|
16
|
+- 'issuer' specifies *application ID* which identifies the client app connecting to the server
|
|
|
17
|
+- 'room' contains the name of the room for which the token has been allocated. This is *NOT* full MUC room address. Example assuming that we have full MUC 'conference1@muc.server.net' then 'conference1' should be used here.
|
|
|
18
|
+- 'exp' token expiration timstamp as defined in the RFC
|
|
18
|
19
|
|
|
19
|
|
-- *roomName* - the name of the conference room(must be lowercase)
|
|
20
|
|
-
|
|
21
|
|
-- *ts* - UTC token timestamp in milliseconds which indicates the time when token has been created
|
|
22
|
|
-
|
|
23
|
|
-- *appId* - application identifier used to distinguish between applications that are using the system. It can be any random string if you're using only one application at a time.
|
|
24
|
|
-
|
|
25
|
|
-- *appSecret* - application secret which should be known only to the token generator and Prosody server
|
|
26
|
|
-
|
|
27
|
|
-Example:
|
|
28
|
|
-
|
|
29
|
|
-```
|
|
30
|
|
-roomName = angrywhalesgrowhigh
|
|
31
|
|
-
|
|
32
|
|
-ts = 1446573136000 -- corresponds to 11/03/2015 @ 5:52pm (UTC)
|
|
33
|
|
-
|
|
34
|
|
-appId = myTestApp
|
|
35
|
|
-
|
|
36
|
|
-appSecret = blablabla
|
|
37
|
|
-```
|
|
38
|
|
-
|
|
39
|
|
-Text to be hashed:
|
|
40
|
|
-
|
|
41
|
|
-```
|
|
42
|
|
-angrywhalesgrowhigh1446573136000myTestAppblablabla
|
|
43
|
|
-```
|
|
44
|
|
-
|
|
45
|
|
-The token is Sha256 hash of the text above:
|
|
46
|
|
-
|
|
47
|
|
-```
|
|
48
|
|
-0daad82d1ad81c718d643b71b46793af2295bb20e3eb436079e9bbd130ba1ad9
|
|
49
|
|
-```
|
|
50
|
|
-
|
|
51
|
|
-Once we have the token generated we concatenate it with timestamp and room name like described in "Token verification"
|
|
52
|
|
-section. It is passed as user's password during authentication process.
|
|
|
20
|
+Secret is used to compute HMAC hash value and verify the token.
|
|
53
|
21
|
|
|
54
|
22
|
### Token verification
|
|
55
|
23
|
|
|
56
|
|
-When user connects to Prosody then SASL PLAIN authentication is being used for token authentication purpose. Username is supplied by the application and in case of jitsi-meet it is randomly generated string(can be also overridden with *config.id* property). The password is a token plus name of the conference room and UTC timestamp in milliseconds:
|
|
57
|
|
-
|
|
58
|
|
-```
|
|
59
|
|
-password = token + "_" + roomName + "_" + ts;
|
|
60
|
|
-```
|
|
61
|
|
-
|
|
62
|
|
-The password for the example from "Token generation mechanism" section would look like this:
|
|
63
|
|
-
|
|
64
|
|
-```
|
|
65
|
|
-0daad82d1ad81c718d643b71b46793af2295bb20e3eb436079e9bbd130ba1ad9_angrywhalesgrowhigh_1446573136000
|
|
66
|
|
-```
|
|
67
|
|
-
|
|
68
|
|
-When user connects the authentication plugin first verifies the timestamp. By default the token is valid for 24 hours
|
|
69
|
|
-and it is compared against UTC timestamp returned by the server's system clock.
|
|
70
|
|
-
|
|
71
|
|
-When the timestamp is fine the token is being verified. The name of the room and timestamp are extracted from the
|
|
72
|
|
-password. Application id and secret come from Prosody host config(see "Manual plugin configuration" section for detailed
|
|
73
|
|
-info). The hash computed by the plugin is compared with the one supplied as part of the user's password.
|
|
74
|
|
-
|
|
75
|
|
-The token is also verified whenever users tries to create new MUC room. This prevents from creating multiple rooms using
|
|
76
|
|
-the same hash which may cause troubles in case it's stolen. Unless the user is an admin it must include it as part of
|
|
77
|
|
-the presence stanza that creates the room:
|
|
78
|
|
-
|
|
79
|
|
-```xml
|
|
80
|
|
-<presence
|
|
81
|
|
- from='user1@example.com/desktop'
|
|
82
|
|
- to='angrywhalesgrowhigh@muc.example.com/somenickname'>
|
|
83
|
|
- <x xmlns='http://jabber.org/protocol/muc'/>
|
|
84
|
|
- <token xmlns='http://jitsi.org/jitmeet/auth-token'>
|
|
85
|
|
- 0daad82d1ad81c718d643b7...e9bbd130ba1ad9_angrywhalesgrowhigh_1446573136000
|
|
86
|
|
- </token>
|
|
87
|
|
-</presence>
|
|
88
|
|
-```
|
|
|
24
|
+JWT token is currently checked in 3 places:
|
|
|
25
|
+- when user connects to Prosody. SASL PLAIN authentication is being used for token authentication purpose. Username is supplied by the application and in case of jitsi-meet it is randomly generated string(can be also overridden with *config.id* property). JWT token is apssed as user's password.
|
|
|
26
|
+- by Jicofo in *conference IQ* which is used to invite the focus and create the room. JWT token is sent in 'session-id' attribute.
|
|
|
27
|
+- when MUC room is being created. This prevents from abusing stolen token by unathorized users. Unless the user is an admin it must include it as part of the presence stanza that creates the room. *FIXME this is redundant as we can config Prosody to allow only admins to create the rooms and let Jicofo verify the token*.
|
|
89
|
28
|
|
|
90
|
29
|
### Lib-jitsi-meet options
|
|
91
|
30
|
|
|
92
|
|
-When token authentication is used with *lib-jitsi-meet* the token is passed to *JitsiConference* constructor:
|
|
|
31
|
+When JWT authentication is used with *lib-jitsi-meet* the token is passed to *JitsiConference* constructor:
|
|
93
|
32
|
|
|
94
|
33
|
```
|
|
95
|
34
|
var token = {token is provided by your application possibly after some authentication}
|
|
96
|
|
-var tokenPassword = token + "_" + roomName + "_" + ts;
|
|
97
|
|
-
|
|
98
|
|
-JitsiMeetJS.init();
|
|
99
|
35
|
|
|
100
|
|
-var connection = new JitsiMeetJS.JitsiConnection(APP_ID, tokenPassword, options);
|
|
|
36
|
+JitsiMeetJS.init(initOptions).then(function(){
|
|
|
37
|
+ connection = new JitsiMeetJS.JitsiConnection(APP_ID, token, options);
|
|
|
38
|
+ ...
|
|
|
39
|
+ connection.connect();
|
|
|
40
|
+});
|
|
101
|
41
|
|
|
102
|
|
-connection.connect();
|
|
103
|
42
|
```
|
|
104
|
43
|
|
|
105
|
44
|
### Jitsi-meet options
|
|
106
|
45
|
|
|
107
|
46
|
In order to start jitsi-meet conference with token you need to specify the token as URL param:
|
|
108
|
47
|
```
|
|
109
|
|
-https://example.com/angrywhalesgrowhigh#config.token="0daad82d1ad81c718d643b71b46793af2295bb20
|
|
110
|
|
-e3eb436079e9bbd130ba1ad9_angrywhalesgrowhigh_1446573136000"
|
|
|
48
|
+https://example.com/angrywhalesgrowhigh#config.token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ"
|
|
111
|
49
|
```
|
|
112
|
50
|
At current level of integration every user that joins the conference has to provide the token and not just the one who
|
|
113
|
51
|
creates the room. It should be possible to change that by using second anonymous domain, but that hasn't been tested
|
|
|
@@ -115,9 +53,12 @@ yet.
|
|
115
|
53
|
|
|
116
|
54
|
### Installing token plugin
|
|
117
|
55
|
|
|
118
|
|
-Token authentication can be integrated automatically using Debian package install. Once you have jitsi-meet installed
|
|
|
56
|
+FIXME: JWT token install using Debian packages is not implemented yet
|
|
|
57
|
+
|
|
|
58
|
+~~Token authentication can be integrated automatically using Debian package install. Once you have jitsi-meet installed
|
|
119
|
59
|
just install 'jitsi-meet-tokens' on top of it. In order to have it configured automatically at least version 721 of
|
|
120
|
|
-jitsi-meet is required which comes with special Prosody config template.
|
|
|
60
|
+jitsi-meet is required which comes with special Prosody config template.~~
|
|
|
61
|
+
|
|
121
|
62
|
```
|
|
122
|
63
|
apt-get install jitsi-meet-token
|
|
123
|
64
|
```
|
|
|
@@ -150,3 +91,10 @@ VirtualHost "jitmeet.example.com"
|
|
150
|
91
|
Component "conference.jitmeet.example.com" "muc"
|
|
151
|
92
|
modules_enabled = { "token_verification" }
|
|
152
|
93
|
```
|
|
|
94
|
+
|
|
|
95
|
+4. Configure JWT properties in jicofo config file located usually at /etc/jitsi/jicofo/sip-cumminicator.properties.
|
|
|
96
|
+
|
|
|
97
|
+```
|
|
|
98
|
+org.jitsi.jicofo.auth.jwt.APP_ID=example_app_id
|
|
|
99
|
+org.jitsi.jicofo.auth.jwt.SECRET=example_app_secret
|
|
|
100
|
+```
|