Add support for logging in with OAuth
This commit is contained in:
parent
a2dec2371d
commit
3dac4ae45c
@ -20,6 +20,7 @@
|
||||
If the device is not trusted, sessionStorage is used and all user data is deleted from the browser cache upon logout.
|
||||
If the device is trusted, localStorage is used and user data is cached indefinitely.
|
||||
- Initial support for XEP-0357 Push Notifications, specifically registering an "App Server".
|
||||
- Add support for logging in via OAuth (see the [oauth_providers](https://conversejs.org/docs/html/configurations.html#oauth-providers) setting)
|
||||
|
||||
### Bugfixes
|
||||
|
||||
|
@ -6947,13 +6947,17 @@ body.reset {
|
||||
#conversejs ul, #conversejs ol, #conversejs dl {
|
||||
font: inherit;
|
||||
margin: 0; }
|
||||
#conversejs a, #conversejs a:visited, #conversejs a:hover, #conversejs a:not([href]):not([tabindex]) {
|
||||
#conversejs a, #conversejs a:visited, #conversejs a:not([href]):not([tabindex]) {
|
||||
text-decoration: none;
|
||||
color: #578EA9;
|
||||
text-shadow: none; }
|
||||
#conversejs a.fa, #conversejs a:visited.fa, #conversejs a:hover.fa, #conversejs a:not([href]):not([tabindex]).fa {
|
||||
#conversejs a:hover, #conversejs a:visited:hover, #conversejs a:not([href]):not([tabindex]):hover {
|
||||
color: #345566;
|
||||
text-decoration: none;
|
||||
text-shadow: none; }
|
||||
#conversejs a.fa, #conversejs a:visited.fa, #conversejs a:not([href]):not([tabindex]).fa {
|
||||
color: #A8ABA1; }
|
||||
#conversejs a.fa:hover, #conversejs a:visited.fa:hover, #conversejs a:hover.fa:hover, #conversejs a:not([href]):not([tabindex]).fa:hover {
|
||||
#conversejs a.fa:hover, #conversejs a:visited.fa:hover, #conversejs a:not([href]):not([tabindex]).fa:hover {
|
||||
color: #818479; }
|
||||
#conversejs canvas {
|
||||
border-radius: 4px; }
|
||||
@ -7803,6 +7807,20 @@ body.reset {
|
||||
#conversejs.converse-fullscreen .chatbox .box-flyout .chatbox-buttons {
|
||||
flex: 0 0 25%;
|
||||
max-width: 25%; } }
|
||||
#conversejs .oauth-providers {
|
||||
text-align: center; }
|
||||
#conversejs .oauth-providers .oauth-provider {
|
||||
margin: 1em 0; }
|
||||
#conversejs .oauth-providers .oauth-provider .oauth-login {
|
||||
margin-left: 0;
|
||||
color: #578EA9;
|
||||
font-size: 16px; }
|
||||
#conversejs .oauth-providers .oauth-provider .oauth-login:hover {
|
||||
color: #345566; }
|
||||
#conversejs .oauth-providers .oauth-provider .oauth-login i {
|
||||
color: #578EA9;
|
||||
font-size: 20px;
|
||||
margin-right: 0.5em; }
|
||||
#conversejs .set-xmpp-status .fa-circle, #conversejs .xmpp-status .fa-circle, #conversejs .roster-contacts .fa-circle {
|
||||
color: #3AA569; }
|
||||
#conversejs .set-xmpp-status .fa-minus-circle, #conversejs .xmpp-status .fa-minus-circle, #conversejs .roster-contacts .fa-minus-circle {
|
||||
@ -7921,11 +7939,6 @@ body.reset {
|
||||
color: #578EA9; }
|
||||
#conversejs #controlbox .toggle-register-login {
|
||||
font-weight: bold; }
|
||||
#conversejs #controlbox .oauth-login {
|
||||
margin-left: 0;
|
||||
color: #666; }
|
||||
#conversejs #controlbox .oauth-login .icon-social:before {
|
||||
font-size: 16px; }
|
||||
#conversejs #controlbox .controlbox-pane .userinfo {
|
||||
padding-bottom: 1em; }
|
||||
#conversejs #controlbox .controlbox-pane .userinfo .username {
|
||||
@ -8000,6 +8013,7 @@ body.reset {
|
||||
#conversejs #controlbox .controlbox-pane .chatbox-btn {
|
||||
margin: 0; }
|
||||
#conversejs #controlbox .controlbox-pane .switch-form {
|
||||
text-align: center;
|
||||
padding: 2em 0; }
|
||||
#conversejs #controlbox .controlbox-pane .switch-form p {
|
||||
margin-top: 0.5em; }
|
||||
|
6418
dist/converse.js
vendored
6418
dist/converse.js
vendored
File diff suppressed because it is too large
Load Diff
@ -986,6 +986,39 @@ This option specifies which icon is shown in HTML5 notifications, as provided
|
||||
by the ``src/converse-notification.js`` plugin.
|
||||
|
||||
|
||||
oauth_providers
|
||||
---------------
|
||||
|
||||
* Default: ``[]``
|
||||
|
||||
Allows you to specify a list of OAuth providers that the user may use to log in
|
||||
with.
|
||||
|
||||
.. note::
|
||||
Your XMPP server will have to support Oauth logins
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
converse.initialize({
|
||||
oauth_providers: {
|
||||
'github': {
|
||||
'client_id': '1338d9f7ff52b1309b29',
|
||||
'host': 'chat.example.org',
|
||||
'class': 'fa-github-alt',
|
||||
'id': 'github',
|
||||
'name': 'Github'
|
||||
},
|
||||
'twitter': {
|
||||
'client_id': '0332d98cff83b1999b22',
|
||||
'host': 'chat.example.org',
|
||||
'class': 'fa-twitter',
|
||||
'id': 'twitter',
|
||||
'name': 'Twitter'
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
ping_interval
|
||||
-------------
|
||||
|
||||
@ -1069,7 +1102,7 @@ The hyperlink on the registration form which points to a directory of public
|
||||
XMPP servers.
|
||||
|
||||
push_app_servers
|
||||
-------------
|
||||
----------------
|
||||
|
||||
* Default: ``[]``
|
||||
|
||||
|
6
package-lock.json
generated
6
package-lock.json
generated
@ -6434,6 +6434,12 @@
|
||||
"integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
|
||||
"dev": true
|
||||
},
|
||||
"hellojs": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/hellojs/-/hellojs-1.16.1.tgz",
|
||||
"integrity": "sha1-rOoZ72LPr8WVF7N5vw+NnT9Dm9Q=",
|
||||
"dev": true
|
||||
},
|
||||
"hmac-drbg": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
||||
|
12
package.json
12
package.json
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "converse.js",
|
||||
"version": "3.3.4",
|
||||
"description": "Browser based XMPP instant messaging client",
|
||||
"main": "main.js",
|
||||
"description": "Browser based XMPP chat client",
|
||||
"main": "dist/converse.js",
|
||||
"directories": {
|
||||
"doc": "docs",
|
||||
"locale": "locale",
|
||||
@ -20,10 +20,13 @@
|
||||
"chatrooms",
|
||||
"webchat"
|
||||
],
|
||||
"author": "JC Brand",
|
||||
"author": {
|
||||
"name": "JC Brand",
|
||||
"email": "jc@opkode.com"
|
||||
},
|
||||
"license": "MPL-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/jcbrand/converse.js/issues"
|
||||
"url": "https://github.com/conversejs/converse.js/issues"
|
||||
},
|
||||
"engines": {
|
||||
"browser": "*"
|
||||
@ -51,6 +54,7 @@
|
||||
"exports-loader": "^0.7.0",
|
||||
"filesize": "^3.6.1",
|
||||
"font-awesome": "^4.7.0",
|
||||
"hellojs": "^1.16.1",
|
||||
"http-server": "^0.10.0",
|
||||
"imports-loader": "^0.8.0",
|
||||
"install": "^0.9.5",
|
||||
|
18
redirect.html
Normal file
18
redirect.html
Normal file
@ -0,0 +1,18 @@
|
||||
<!doctype html>
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>Converse</title>
|
||||
<link rel="shortcut icon" type="image/ico" href="css/images/favicon.ico"/>
|
||||
<link type="text/css" rel="stylesheet" media="screen" href="css/converse.css" />
|
||||
<script src="node_modules/hellojs/dist/hello.all.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="content">
|
||||
<div class="inner-content">
|
||||
<h1 class="brand-heading"><i class="icon-conversejs"></i> Converse</h1>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,4 +1,24 @@
|
||||
#conversejs {
|
||||
.oauth-providers {
|
||||
text-align: center;
|
||||
.oauth-provider {
|
||||
margin: 1em 0;
|
||||
|
||||
.oauth-login {
|
||||
margin-left: 0;
|
||||
color: $link-color;
|
||||
font-size: $font-size-large;
|
||||
&:hover {
|
||||
color: darken($link-color, 20%);
|
||||
}
|
||||
i {
|
||||
color: $link-color;
|
||||
font-size: $font-size-huge;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.set-xmpp-status, .xmpp-status, .roster-contacts {
|
||||
.fa-circle {
|
||||
@ -173,15 +193,6 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.oauth-login {
|
||||
margin-left: 0;
|
||||
color: $text-color;
|
||||
.icon-social:before {
|
||||
font-size: $font-size-large;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.controlbox-pane {
|
||||
.userinfo {
|
||||
padding-bottom: 1em;
|
||||
@ -296,6 +307,7 @@
|
||||
}
|
||||
|
||||
.switch-form {
|
||||
text-align: center;
|
||||
padding: 2em 0;
|
||||
p {
|
||||
margin-top: 0.5em;
|
||||
|
@ -176,10 +176,16 @@ body.reset {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a, a:visited, a:hover, a:not([href]):not([tabindex]) {
|
||||
a, a:visited, a:not([href]):not([tabindex]) {
|
||||
text-decoration: none;
|
||||
color: $link-color;
|
||||
text-shadow: none;
|
||||
&:hover {
|
||||
color: darken($link-color, 20%);
|
||||
text-decoration: none;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
&.fa {
|
||||
color: $subdued-color;
|
||||
&:hover {
|
||||
|
@ -85,6 +85,7 @@
|
||||
'converse-muc',
|
||||
'converse-muc-views',
|
||||
'converse-notification',
|
||||
'converse-oauth',
|
||||
'converse-ping',
|
||||
'converse-profile',
|
||||
'converse-push',
|
||||
|
146
src/converse-oauth.js
Normal file
146
src/converse-oauth.js
Normal file
@ -0,0 +1,146 @@
|
||||
// Converse.js
|
||||
// https://conversejs.org
|
||||
//
|
||||
// Copyright (c) 2013-2018, the Converse.js developers
|
||||
// Licensed under the Mozilla Public License (MPLv2)
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as a module called "myplugin"
|
||||
define(["converse-core", "templates/oauth_providers.html", "hellojs"], factory);
|
||||
} else {
|
||||
// Browser globals. If you're not using a module loader such as require.js,
|
||||
// then this line below executes. Make sure that your plugin's <script> tag
|
||||
// appears after the one from converse.js.
|
||||
factory(converse);
|
||||
}
|
||||
}(this, function (converse, tpl_oauth_providers, hello) {
|
||||
'use strict';
|
||||
const _ = converse.env._,
|
||||
Backbone = converse.env.Backbone,
|
||||
Strophe = converse.env.Strophe;
|
||||
|
||||
// The following line registers your plugin.
|
||||
converse.plugins.add("converse-oauth", {
|
||||
|
||||
/* Optional dependencies are other plugins which might be
|
||||
* overridden or relied upon, and therefore need to be loaded before
|
||||
* this plugin. They are called "optional" because they might not be
|
||||
* available, in which case any overrides applicable to them will be
|
||||
* ignored.
|
||||
*
|
||||
* NB: These plugins need to have already been loaded via require.js.
|
||||
*
|
||||
* It's possible to make optional dependencies non-optional.
|
||||
* If the setting "strict_plugin_dependencies" is set to true,
|
||||
* an error will be raised if the plugin is not found.
|
||||
*/
|
||||
'optional_dependencies': ['converse-register'],
|
||||
|
||||
/* If you want to override some function or a Backbone model or
|
||||
* view defined elsewhere in converse.js, then you do that under
|
||||
* the "overrides" namespace.
|
||||
*/
|
||||
'overrides': {
|
||||
/* For example, the private *_converse* object has a
|
||||
* method "onConnected". You can override that method as follows:
|
||||
*/
|
||||
'LoginPanel': {
|
||||
|
||||
insertOAuthProviders () {
|
||||
const { _converse } = this.__super__;
|
||||
if (_.isUndefined(this.oauth_providers_view)) {
|
||||
this.oauth_providers_view =
|
||||
new _converse.OAuthProvidersView({'model': _converse.oauth_providers});
|
||||
|
||||
this.oauth_providers_view.render();
|
||||
this.el.querySelector('.buttons').insertAdjacentElement(
|
||||
'afterend',
|
||||
this.oauth_providers_view.el
|
||||
);
|
||||
}
|
||||
this.oauth_providers_view.render();
|
||||
},
|
||||
|
||||
render (cfg) {
|
||||
const { _converse } = this.__super__;
|
||||
const result = this.__super__.render.apply(this, arguments);
|
||||
if (_converse.oauth_providers && !_converse.auto_login) {
|
||||
this.insertOAuthProviders();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
initialize () {
|
||||
/* The initialize function gets called as soon as the plugin is
|
||||
* loaded by converse.js's plugin machinery.
|
||||
*/
|
||||
const { _converse } = this,
|
||||
{ __ } = _converse;
|
||||
|
||||
_converse.api.settings.update({
|
||||
'oauth_providers': {},
|
||||
});
|
||||
|
||||
_converse.OAuthProviders = Backbone.Collection.extend({
|
||||
'sync': __.noop,
|
||||
|
||||
initialize () {
|
||||
_.each(_converse.user_settings.oauth_providers, (provider) => {
|
||||
const item = new Backbone.Model(_.extend(provider, {
|
||||
'login_text': __('Log in with %1$s', provider.name)
|
||||
}));
|
||||
this.add(item, {'silent': true});
|
||||
});
|
||||
}
|
||||
});
|
||||
_converse.oauth_providers = new _converse.OAuthProviders();
|
||||
|
||||
|
||||
_converse.OAuthProvidersView = Backbone.VDOMView.extend({
|
||||
'events': {
|
||||
'click .oauth-login': 'oauthLogin'
|
||||
},
|
||||
|
||||
toHTML () {
|
||||
return tpl_oauth_providers(
|
||||
_.extend({
|
||||
'_': _,
|
||||
'__': _converse.__,
|
||||
'providers': this.model.toJSON()
|
||||
}));
|
||||
},
|
||||
|
||||
fetchOAuthProfileDataAndLogin () {
|
||||
this.oauth_service.api('me').then((profile) => {
|
||||
const response = this.oauth_service.getAuthResponse();
|
||||
_converse.api.user.login({
|
||||
'jid': `${profile.name}@${this.provider.get('host')}`,
|
||||
'password': response.access_token
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
oauthLogin (ev) {
|
||||
ev.preventDefault();
|
||||
const id = ev.target.getAttribute('data-id');
|
||||
this.provider = _converse.oauth_providers.get(id);
|
||||
this.oauth_service = hello(id);
|
||||
|
||||
const data = {};
|
||||
data[id] = this.provider.get('client_id');
|
||||
hello.init(data, {
|
||||
'redirect_uri': '/redirect.html'
|
||||
});
|
||||
|
||||
this.oauth_service.login().then(
|
||||
() => this.fetchOAuthProfileDataAndLogin(),
|
||||
(error) => _converse.log(error.error_message, Strophe.LogLevel.ERROR)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}));
|
@ -67,7 +67,7 @@
|
||||
if (_.isUndefined(this.registerlinkview)) {
|
||||
this.registerlinkview = new _converse.RegisterLinkView({'model': this.model});
|
||||
this.registerlinkview.render();
|
||||
this.el.querySelector('.buttons').insertAdjacentElement('beforeend', this.registerlinkview.el);
|
||||
this.el.querySelector('.buttons').insertAdjacentElement('afterend', this.registerlinkview.el);
|
||||
}
|
||||
this.registerlinkview.render();
|
||||
},
|
||||
|
@ -22,10 +22,11 @@ if (typeof define !== 'undefined') {
|
||||
"converse-muc-views",
|
||||
"converse-muc-views", // Views related to MUC
|
||||
"converse-notification", // HTML5 Notifications
|
||||
"converse-oauth",
|
||||
"converse-ping", // XEP-0199 XMPP Ping
|
||||
"converse-roster",
|
||||
"converse-register", // XEP-0077 In-band registration
|
||||
"converse-roomslist", // Show currently open chat rooms
|
||||
"converse-roster",
|
||||
"converse-vcard", // XEP-0054 VCard-temp
|
||||
/* END: Removable components */
|
||||
], function (converse) {
|
||||
|
9
src/templates/oauth_providers.html
Normal file
9
src/templates/oauth_providers.html
Normal file
@ -0,0 +1,9 @@
|
||||
<fieldset class="oauth-providers">
|
||||
{[ o._.forEach(o.providers, function (provider) { ]}
|
||||
<p class="oauth-provider">
|
||||
<a class="oauth-login" href="#" data-id="{{provider.id}}">
|
||||
<i class="fa {{ provider.class}}"></i>{{provider.login_text}}</span>
|
||||
</a>
|
||||
</p>
|
||||
{[ }); ]}
|
||||
</fieldset>
|
@ -1,6 +1,6 @@
|
||||
<div class="switch-form">
|
||||
<fieldset class="switch-form">
|
||||
{[ if (!o._converse.auto_login && o._converse.CONNECTION_STATUS[o.connection_status] !== 'CONNECTING') { ]}
|
||||
<p>{{{ o.__("Don't have a chat account?") }}}</p>
|
||||
<p><a class="register-account toggle-register-login" href="#converse/register">{{{o.__("Create an account")}}}</a></p>
|
||||
{[ } ]}
|
||||
</div>
|
||||
</fieldset>
|
||||
|
Loading…
Reference in New Issue
Block a user