Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normalized login and passwordlessLogin usage to make it work in embedded and hosted scenarios #646

Merged
merged 5 commits into from
Feb 1, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,13 @@ <h2>Login with database connection:</h2>
<input type="button" class="login-db" value="login" />
</div>

<div>
<h2>Login with database connection (from universal login):</h2>
<input class="login-username" value="johnfoo@gmail.com" />
<input class="login-password" value="1234" />
<input type="button" class="universal-login" value="login" />
</div>

<div>
<h2>Login with passwordless connection:</h2>
<div>
Expand Down Expand Up @@ -261,6 +268,15 @@ <h2>Console:</h2>
}, htmlConsole.dumpCallback.bind(htmlConsole));
});

$('.universal-login').click(function (e) {
e.preventDefault();
webAuth._hostedPages.login({
connection: 'acme',
username: $('.login-username').val(),
password: $('.login-password').val()
}, htmlConsole.dumpCallback.bind(htmlConsole));
});

$('.passwordless-login-verify').click(function (e) {
e.preventDefault();
webAuthPasswordless.passwordlessLogin({
Expand Down
98 changes: 98 additions & 0 deletions src/web-auth/hosted-pages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
var UsernamePassword = require('./username-password');
var objectHelper = require('../helper/object');
var windowHelper = require('../helper/window');
var Warn = require('../helper/warn');
var assert = require('../helper/assert');

function HostedPages(client, options) {
this.baseOptions = options;
this.client = client;

this.warn = new Warn({
disableWarnings: !!options._disableDeprecationWarnings
});
}

/**
* @callback credentialsCallback
* @param {Error} [err] error returned by Auth0 with the reason of the Auth failure
* @param {Object} [result] result of the AuthN request
* @param {String} result.accessToken token that can be used with {@link userinfo}
* @param {String} [result.idToken] token that identifies the user
* @param {String} [result.refreshToken] token that can be used to get new access tokens from Auth0. Note that not all clients can request them or the resource server might not allow them.
*/

/**
* Performs authentication with username/email and password with a database connection
*
* This method is not compatible with API Auth so if you need to fetch API tokens with audience
* you should use {@link authorize} or {@link login}.
*
* @method loginWithCredentials
* @param {Object} options
* @param {String} [options.redirectUri] url that the Auth0 will redirect after Auth with the Authorization Response
* @param {String} [options.responseType] type of the response used. It can be any of the values `code` and `token`
* @param {String} [options.responseMode] how the AuthN response is encoded and redirected back to the client. Supported values are `query` and `fragment`
* @param {String} [options.scope] scopes to be requested during AuthN. e.g. `openid email`
* @param {credentialsCallback} cb
*/
HostedPages.prototype.login = function(options, cb) {
if (windowHelper.getWindow().location.host !== this.baseOptions.domain) {
throw new Error('This method is meant to be used only inside the Universal Login Page.');
}
var usernamePassword;

var params = objectHelper
.merge(this.baseOptions, [
'clientID',
'redirectUri',
'tenant',
'responseType',
'responseMode',
'scope',
'audience',
'_csrf',
'state',
'_intstate',
'nonce'
])
.with(options);

assert.check(
params,
{ type: 'object', message: 'options parameter is not valid' },
{
responseType: { type: 'string', message: 'responseType option is required' }
}
);

usernamePassword = new UsernamePassword(this.baseOptions);
return usernamePassword.login(params, function(err, data) {
if (err) {
return cb(err);
}
return usernamePassword.callback(data);
});
};

/**
* Signs up a new user and automatically logs the user in after the signup.
*
* @method signupAndLogin
* @param {Object} options
* @param {String} options.email user email address
* @param {String} options.password user password
* @param {String} options.connection name of the connection where the user will be created
* @param {credentialsCallback} cb
*/
HostedPages.prototype.signupAndLogin = function(options, cb) {
var _this = this;
return _this.client.client.dbConnection.signup(options, function(err) {
if (err) {
return cb(err);
}
return _this.login(options, cb);
});
};

module.exports = HostedPages;
2 changes: 2 additions & 0 deletions src/web-auth/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var Popup = require('./popup');
var SilentAuthenticationHandler = require('./silent-authentication-handler');
var CrossOriginAuthentication = require('./cross-origin-authentication');
var WebMessageHandler = require('./web-message-handler');
var HostedPages = require('./hosted-pages');

/**
* Handles all the browser's AuthN/AuthZ flows
Expand Down Expand Up @@ -107,6 +108,7 @@ function WebAuth(options) {
this.popup = new Popup(this, this.baseOptions);
this.crossOriginAuthentication = new CrossOriginAuthentication(this, this.baseOptions);
this.webMessageHandler = new WebMessageHandler(this);
this._hostedPages = new HostedPages(this, this.baseOptions);
}

/**
Expand Down
55 changes: 55 additions & 0 deletions src/web-auth/username-password.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
var urljoin = require('url-join');

var objectHelper = require('../helper/object');
var RequestBuilder = require('../helper/request-builder');
var responseHandler = require('../helper/response-handler');
var windowHelper = require('../helper/window');
var TransactionManager = require('./transaction-manager');

function UsernamePassword(options) {
this.baseOptions = options;
this.request = new RequestBuilder(options);
this.transactionManager = new TransactionManager(this.baseOptions.transaction);
}

UsernamePassword.prototype.login = function(options, cb) {
var url;
var body;

url = urljoin(this.baseOptions.rootUrl, 'usernamepassword', 'login');

options.username = options.username || options.email; // eslint-disable-line

options = objectHelper.blacklist(options, ['email']); // eslint-disable-line

body = objectHelper
.merge(this.baseOptions, [
'clientID',
'redirectUri',
'tenant',
'responseType',
'responseMode',
'scope',
'audience'
])
.with(options);
body = this.transactionManager.process(body);

body = objectHelper.toSnakeCase(body, ['auth0Client']);

return this.request.post(url).send(body).end(responseHandler(cb));
};

UsernamePassword.prototype.callback = function(formHtml) {
var div;
var form;
var _document = windowHelper.getDocument();

div = _document.createElement('div');
div.innerHTML = formHtml;
form = _document.body.appendChild(div).children[0];

form.submit();
};

module.exports = UsernamePassword;
Loading