/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* JavaScript for Authentication */ (function() { /* jshint validthis: true */ 'use strict'; angular.module('SOGo.Authentication', ['ngCookies']) .constant('passwordPolicyConfig', { PolicyPasswordChangeUnsupported: -3, PolicyPasswordSystemUnknown: -2, PolicyPasswordUnknown: -1, PolicyPasswordExpired: 0, PolicyAccountLocked: 1, PolicyChangeAfterReset: 2, PolicyPasswordModNotAllowed: 3, PolicyMustSupplyOldPassword: 4, PolicyInsufficientPasswordQuality: 5, PolicyPasswordTooShort: 6, PolicyPasswordTooYoung: 7, PolicyPasswordInHistory: 8, PolicyPasswordRecoveryFailed: 9, PolicyPasswordRecoveryInvalidToken: 10, PolicyNoError: 65535 }) .provider('Authentication', Authentication); function Authentication() { function redirectUrl(username, domain) { var userName, address, baseAddress, parts, hostpart, protocol, newAddress; userName = username; if (domain) userName += '@' + domain; address = '' + window.location.href; baseAddress = ApplicationBaseURL + encodeURIComponent(userName); if (baseAddress[0] == '/') { parts = address.split('/'); hostpart = parts[2]; protocol = parts[0]; baseAddress = protocol + '//' + hostpart + baseAddress; } if (address.startsWith(baseAddress) && !address.endsWith('/logoff')) newAddress = address; else newAddress = baseAddress; return newAddress; } this.$get = getService; /** * @ngInject */ getService.$inject = ['$q', '$http', '$cookies', 'passwordPolicyConfig']; function getService($q, $http, $cookies, passwordPolicyConfig) { var service; service = { login: function(data) { var d = $q.defer(), username = data.username, password = data.password, verificationCode = data.verificationCode, domain = data.domain, language, rememberLogin = data.rememberLogin ? 1 : 0; if (data.loginSuffix && !username.endsWith(data.loginSuffix)) { username += loginSuffix; domain = false; } if (data.language && data.language != 'WONoSelectionString') { language = data.language; } $http({ method: 'POST', url: '/SOGo/connect', data: { userName: username, password: password, verificationCode: verificationCode, domain: domain, language: language, rememberLogin: rememberLogin } }).then(function(response) { var data = response.data; // Make sure browser's cookies are enabled if (navigator && !navigator.cookieEnabled) { d.reject({error: l('cookiesNotEnabled')}); } else { // Check for TOTP if (typeof data.totpMissingKey != 'undefined' && response.status == 202) { d.resolve({totpmissingkey: 1}); } else if (typeof data.totpDisabled != 'undefined') { d.resolve({ cn: data.cn, url: redirectUrl(data.username, domain), totpdisabled: 1 }); } // Check password policy else if (typeof data.expire != 'undefined' && typeof data.grace != 'undefined') { if (data.expire < 0 && data.grace > 0) { d.reject({ cn: data.cn, url: redirectUrl(username, domain), grace: data.grace }); } else if (data.expire > 0 && data.grace == -1) { d.reject({ cn: data.cn, url: redirectUrl(username, domain), expire: data.expire }); } else { d.resolve({ cn: data.cn, url: redirectUrl(data.username, domain) }); } } else { d.resolve({ url: redirectUrl(data.username, domain) }); } } }, function(error) { var response, perr, data = error.data; if (data && data.totpInvalidKey) { response = {error: l('You provided an invalid TOTP key.')}; } else if (data && angular.isDefined(data.LDAPPasswordPolicyError)) { perr = data.LDAPPasswordPolicyError; if (perr == passwordPolicyConfig.PolicyNoError) { response = {error: l('Wrong username or password.')}; } else if (perr == passwordPolicyConfig.PolicyAccountLocked) { response = {error: l('Your account was locked due to too many failed attempts.')}; } else if (perr == passwordPolicyConfig.PolicyPasswordExpired || perr == passwordPolicyConfig.PolicyChangeAfterReset) { response = { passwordexpired: 1, userPolicies: data.additionalInfos.userPolicies, url: redirectUrl(username, domain) }; } else if (perr == passwordPolicyConfig.PolicyChangeAfterReset) { response = { passwordexpired: 1, userPolicies: data.additionalInfos.userPolicies, url: redirectUrl(username, domain) }; } else if (perr == passwordPolicyConfig.PolicyInsufficientPasswordQuality) { response = { passwordexpired: 2, userPolicies: data.additionalInfos.userPolicies, url: redirectUrl(username, domain) }; } else { response = {error: l('Login failed due to unhandled error case: ') + perr}; } } else { response = {error: l('Unhandled error response')}; } d.reject(response); }); return d.promise; }, // login: function(data) { ... loginName: function(data) { var d = $q.defer(), username = data.username, language; if (data.language && data.language != 'WONoSelectionString') { language = data.language; } $http({ method: 'POST', url: '/SOGo/connectName?userName='+username, // data: JSON.stringify({userName: username}), data: {userName: username}, // headers: { // //'Content-Type': undefined // //'Content-Type': "application/x-www-form-urlencoded" // 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8' // } }).then(function(response) { var data = response.data; // Make sure browser's cookies are enabled if (navigator && !navigator.cookieEnabled) { d.reject({error: l('cookiesNotEnabled')}); } else { if(data.redirect) { //Redirection in case of openID d.resolve({ url: data.redirect }); } } }, function(error) { var response, perr, data = error.data; d.reject(response); }); return d.promise; }, changePassword: function(userName, domain, newPassword, oldPassword, token) { var d = $q.defer(), xsrfCookie = $cookies.get('XSRF-TOKEN'); $cookies.remove('XSRF-TOKEN', {path: '/SOGo/'}); $http({ method: 'POST', url: '/SOGo/so/changePassword', headers: { 'X-XSRF-TOKEN' : xsrfCookie }, data: { userName: userName, newPassword: newPassword, oldPassword: oldPassword, token: token } }).then(function (response) { if (response && response.data && response.data.username) { d.resolve({ url: redirectUrl(response.data.username, domain) }); } else { d.resolve({ url: redirectUrl(userName, domain) }); } }, function(response) { var error, data = response.data, perr = data.LDAPPasswordPolicyError; if (!perr) { perr = passwordPolicyConfig.PolicyPasswordSystemUnknown; error = _("Unhandled error response"); } else if (perr == passwordPolicyConfig.PolicyNoError || perr == passwordPolicyConfig.PolicyPasswordUnknown) { error = l("Password change failed"); } else if (perr == passwordPolicyConfig.PolicyPasswordModNotAllowed) { error = l("Password change failed - Permission denied"); } else if (perr == passwordPolicyConfig.PolicyInsufficientPasswordQuality) { error = l("Password change failed - Insufficient password quality"); } else if (perr == passwordPolicyConfig.PolicyPasswordTooShort) { error = l("Password change failed - Password is too short"); } else if (perr == passwordPolicyConfig.PolicyPasswordTooYoung) { error = l("Password change failed - Password is too young"); } else if (perr == passwordPolicyConfig.PolicyPasswordInHistory) { error = l("Password change failed - Password is in history"); } else if (perr == passwordPolicyConfig.PolicyPasswordRecoveryInvalidToken) { error = l("Invalid token. Could not change password"); } else { error = l("Unhandled policy error: %{0}").formatted(perr); perr = passwordPolicyConfig.PolicyPasswordUnknown; } // Restore the cookie $cookies.put('XSRF-TOKEN', xsrfCookie, {path: '/SOGo/'}); d.reject(error); }); return d.promise; }, passwordRecovery: function (userName, domain) { var self = this; var d = $q.defer(), xsrfCookie = $cookies.get('XSRF-TOKEN'); $cookies.remove('XSRF-TOKEN', { path: '/SOGo/' }); $http({ method: 'POST', url: '/SOGo/so/passwordRecovery', headers: { 'X-XSRF-TOKEN': xsrfCookie }, data: { userName: userName, domain: domain } }).then(function (response) { d.resolve(Object.assign( { url: redirectUrl(userName, domain) }, response.data, 'SecretQuestion' === response.data.mode ? { secretQuestionLabel: l('passwordRecovery_' + response.data.secretQuestion) } : {}, 'SecondaryEmail' === response.data.mode ? { obfuscatedRecoveryEmail: response.data.obfuscatedSecondaryEmail } : {} )); }, function () { // Restore the cookie $cookies.put('XSRF-TOKEN', xsrfCookie, { path: '/SOGo/' }); d.reject(l("Unhandled policy error: %{0}").formatted(passwordPolicyConfig.PolicyPasswordRecoveryFailed)); }); return d.promise; }, passwordRecoveryEmail: function (userName, domain, mode, mailDomain) { var self = this; var d = $q.defer(), xsrfCookie = $cookies.get('XSRF-TOKEN'); $cookies.remove('XSRF-TOKEN', { path: '/SOGo/' }); $http({ method: 'POST', url: '/SOGo/so/passwordRecoveryEmail', headers: { 'X-XSRF-TOKEN': xsrfCookie }, data: { userName: userName, domain: domain, mode: mode, mailDomain: mailDomain } }).then(function (response) { d.resolve(response.data.jwt); }, function (response) { // Restore the cookie $cookies.put('XSRF-TOKEN', xsrfCookie, { path: '/SOGo/' }); d.reject(l(response.data)); }); return d.promise; }, passwordRecoveryCheck: function (userName, domain, mode, question, answer, mailDomain) { var self = this; var d = $q.defer(), xsrfCookie = $cookies.get('XSRF-TOKEN'); $cookies.remove('XSRF-TOKEN', { path: '/SOGo/' }); $http({ method: 'POST', url: '/SOGo/so/passwordRecoveryCheck', headers: { 'X-XSRF-TOKEN': xsrfCookie }, data: { userName: userName, domain: domain, mode: mode, question: question, answer: answer, mailDomain: mailDomain } }).then(function (response) { d.resolve(response.data.jwt); }, function (response) { // Restore the cookie $cookies.put('XSRF-TOKEN', xsrfCookie, { path: '/SOGo/' }); d.reject(l(response.data)); }); return d.promise; }, passwordRecoveryEnabled: function (userName, domain) { var self = this; var d = $q.defer(); $http({ method: 'POST', url: '/SOGo/so/passwordRecoveryEnabled', data: { userName: userName, domain: domain } }).then(function (response) { d.resolve(response.data.domain); }, function () { d.reject(); }); return d.promise; } }; return service; } } })();