GUACAMOLE-839: Support deferred retrieval of authentication parameters.

This commit is contained in:
Michael Jumper
2023-01-27 13:49:18 -08:00
parent 9177cac3cc
commit b6ce477625

View File

@@ -26,9 +26,11 @@
* result of authentication operations: * result of authentication operations:
* *
* "guacLoginPending" * "guacLoginPending"
* An authentication request was submitted and we are awaiting the result. * An authentication request is being submitted and we are awaiting the
* This event receives an object containing the HTTP parameters submitted * result. The request may not yet have been submitted if the parameters
* as its sole parameter. * for that request are not ready. This event receives a promise that
* resolves with the HTTP parameters that were ultimately submitted as its
* sole parameter.
* *
* "guacLogin" * "guacLogin"
* Authentication was successful and a new token was created. This event * Authentication was successful and a new token was created. This event
@@ -66,6 +68,7 @@ angular.module('auth').factory('authenticationService', ['$injector',
var Error = $injector.get('Error'); var Error = $injector.get('Error');
// Required services // Required services
var $q = $injector.get('$q');
var $rootScope = $injector.get('$rootScope'); var $rootScope = $injector.get('$rootScope');
var localStorageService = $injector.get('localStorageService'); var localStorageService = $injector.get('localStorageService');
var requestService = $injector.get('requestService'); var requestService = $injector.get('requestService');
@@ -172,58 +175,69 @@ angular.module('auth').factory('authenticationService', ['$injector',
* *
* If a token is provided, it will be reused if possible. * If a token is provided, it will be reused if possible.
* *
* @param {Object} parameters * @param {Object|Promise} parameters
* Arbitrary parameters to authenticate with. * Arbitrary parameters to authenticate with. If a Promise is provided,
* that Promise must resolve with the parameters to be submitted when
* those parameters are available, and any error will be handled as if
* from the authentication endpoint of the REST API itself.
* *
* @returns {Promise} * @returns {Promise}
* A promise which succeeds only if the login operation was successful. * A promise which succeeds only if the login operation was successful.
*/ */
service.authenticate = function authenticate(parameters) { service.authenticate = function authenticate(parameters) {
// Notify that a fresh authentication request is being submitted // Coerce received parameters object into a Promise, if it isn't
// already a Promise
parameters = $q.resolve(parameters);
// Notify that a fresh authentication request is underway
$rootScope.$broadcast('guacLoginPending', parameters); $rootScope.$broadcast('guacLoginPending', parameters);
// Attempt authentication // Attempt authentication after auth parameters are available ...
return requestService({ return parameters.then(function requestParametersReady(requestParams) {
method: 'POST',
url: 'api/tokens',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: $.param(parameters)
})
// If authentication succeeds, handle received auth data return requestService({
.then(function authenticationSuccessful(data) { method: 'POST',
url: 'api/tokens',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: $.param(requestParams)
})
var currentToken = service.getCurrentToken(); // ... if authentication succeeds, handle received auth data ...
.then(function authenticationSuccessful(data) {
// If a new token was received, ensure the old token is invalidated, var currentToken = service.getCurrentToken();
// if any, and notify listeners of the new token
if (data.authToken !== currentToken) { // If a new token was received, ensure the old token is invalidated,
// if any, and notify listeners of the new token
if (data.authToken !== currentToken) {
// If an old token existed, request that the token be revoked
if (currentToken) {
service.revokeToken(currentToken).catch(angular.noop);
}
// Notify of login and new token
setAuthenticationResult(new AuthenticationResult(data));
$rootScope.$broadcast('guacLogin', data.authToken);
// If an old token existed, request that the token be revoked
if (currentToken) {
service.revokeToken(currentToken).catch(angular.noop);
} }
// Notify of login and new token // Update cached authentication result, even if the token remains
setAuthenticationResult(new AuthenticationResult(data)); // the same
$rootScope.$broadcast('guacLogin', data.authToken); else
setAuthenticationResult(new AuthenticationResult(data));
} // Authentication was successful
return data;
// Update cached authentication result, even if the token remains });
// the same
else
setAuthenticationResult(new AuthenticationResult(data));
// Authentication was successful
return data;
}) })
// If authentication fails, propogate failure to returned promise // ... if authentication fails, propogate failure to returned promise
['catch'](requestService.createErrorCallback(function authenticationFailed(error) { ['catch'](requestService.createErrorCallback(function authenticationFailed(error) {
// Notify of generic login failure, for any event consumers that // Notify of generic login failure, for any event consumers that