loginHandler.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import {slug, getLdapUsername, getLdapEmail, getLdapUserUniqueID, syncUserData, addLdapUser} from './sync';
  2. import LDAP from './ldap';
  3. import { log_debug, log_info, log_warn, log_error } from './logger';
  4. function fallbackDefaultAccountSystem(bind, username, password) {
  5. if (typeof username === 'string') {
  6. if (username.indexOf('@') === -1) {
  7. username = {username};
  8. } else {
  9. username = {email: username};
  10. }
  11. }
  12. log_info('Fallback to default account system: ', username );
  13. const loginRequest = {
  14. user: username,
  15. password: {
  16. digest: SHA256(password),
  17. algorithm: 'sha-256',
  18. },
  19. };
  20. log_debug('Fallback options: ', loginRequest);
  21. return Accounts._runLoginHandlers(bind, loginRequest);
  22. }
  23. Accounts.registerLoginHandler('ldap', function(loginRequest) {
  24. if (!loginRequest.ldap || !loginRequest.ldapOptions) {
  25. return undefined;
  26. }
  27. log_info('Init LDAP login', loginRequest.username);
  28. if (LDAP.settings_get('LDAP_ENABLE') !== true) {
  29. return fallbackDefaultAccountSystem(this, loginRequest.username, loginRequest.ldapPass);
  30. }
  31. const self = this;
  32. const ldap = new LDAP();
  33. let ldapUser;
  34. try {
  35. ldap.connectSync();
  36. if (!!LDAP.settings_get('LDAP_USER_AUTHENTICATION')) {
  37. ldap.bindUserIfNecessary(loginRequest.username, loginRequest.ldapPass);
  38. ldapUser = ldap.searchUsersSync(loginRequest.username)[0];
  39. } else {
  40. const users = ldap.searchUsersSync(loginRequest.username);
  41. if (users.length !== 1) {
  42. log_info('Search returned', users.length, 'record(s) for', loginRequest.username);
  43. throw new Error('User not Found');
  44. }
  45. if (ldap.authSync(users[0].dn, loginRequest.ldapPass) === true) {
  46. if (ldap.isUserInGroup(loginRequest.username, users[0])) {
  47. ldapUser = users[0];
  48. } else {
  49. throw new Error('User not in a valid group');
  50. }
  51. } else {
  52. log_info('Wrong password for', loginRequest.username);
  53. }
  54. }
  55. } catch (error) {
  56. log_error(error);
  57. }
  58. if (!ldapUser) {
  59. if (LDAP.settings_get('LDAP_LOGIN_FALLBACK') === true) {
  60. return fallbackDefaultAccountSystem(self, loginRequest.username, loginRequest.ldapPass);
  61. }
  62. throw new Meteor.Error('LDAP-login-error', `LDAP Authentication failed with provided username [${ loginRequest.username }]`);
  63. }
  64. // Look to see if user already exists
  65. let userQuery;
  66. const Unique_Identifier_Field = getLdapUserUniqueID(ldapUser);
  67. let user;
  68. // Attempt to find user by unique identifier
  69. if (Unique_Identifier_Field) {
  70. userQuery = {
  71. 'services.ldap.id': Unique_Identifier_Field.value,
  72. };
  73. log_info('Querying user');
  74. log_debug('userQuery', userQuery);
  75. user = Meteor.users.findOne(userQuery);
  76. }
  77. // Attempt to find user by username
  78. let username;
  79. let email;
  80. if (LDAP.settings_get('LDAP_USERNAME_FIELD') !== '') {
  81. username = slug(getLdapUsername(ldapUser));
  82. } else {
  83. username = slug(loginRequest.username);
  84. }
  85. if(LDAP.settings_get('LDAP_EMAIL_FIELD') !== '') {
  86. email = getLdapEmail(ldapUser);
  87. }
  88. if (!user) {
  89. if(email && LDAP.settings_get('LDAP_EMAIL_MATCH_REQUIRE') === true) {
  90. if(LDAP.settings_get('LDAP_EMAIL_MATCH_VERIFIED') === true) {
  91. userQuery = {
  92. '_id' : username,
  93. 'emails.0.address' : email,
  94. 'emails.0.verified' : true
  95. };
  96. } else {
  97. userQuery = {
  98. '_id' : username,
  99. 'emails.0.address' : email
  100. };
  101. }
  102. } else {
  103. userQuery = {
  104. username
  105. };
  106. }
  107. log_debug('userQuery', userQuery);
  108. user = Meteor.users.findOne(userQuery);
  109. }
  110. // Attempt to find user by e-mail address only
  111. if (!user && email && LDAP.settings_get('LDAP_EMAIL_MATCH_ENABLE') === true) {
  112. log_info('No user exists with username', username, '- attempting to find by e-mail address instead');
  113. if(LDAP.settings_get('LDAP_EMAIL_MATCH_VERIFIED') === true) {
  114. userQuery = {
  115. 'emails.0.address': email,
  116. 'emails.0.verified' : true
  117. };
  118. } else {
  119. userQuery = {
  120. 'emails.0.address' : email
  121. };
  122. }
  123. log_debug('userQuery', userQuery);
  124. user = Meteor.users.findOne(userQuery);
  125. }
  126. // Login user if they exist
  127. if (user) {
  128. if (user.authenticationMethod !== 'ldap' && LDAP.settings_get('LDAP_MERGE_EXISTING_USERS') !== true) {
  129. log_info('User exists without "authenticationMethod : ldap"');
  130. throw new Meteor.Error('LDAP-login-error', `LDAP Authentication succeded, but there's already a matching Wekan account in MongoDB`);
  131. }
  132. log_info('Logging user');
  133. const stampedToken = Accounts._generateStampedLoginToken();
  134. const update_data = {
  135. $push: {
  136. 'services.resume.loginTokens': Accounts._hashStampedToken(stampedToken),
  137. },
  138. };
  139. if( LDAP.settings_get('LDAP_SYNC_GROUP_ROLES') === true ) {
  140. log_debug('Updating Groups/Roles');
  141. const groups = ldap.getUserGroups(username, ldapUser);
  142. if( groups.length > 0 ) {
  143. Roles.setUserRoles(user._id, groups );
  144. log_info(`Updated roles to:${ groups.join(',')}`);
  145. }
  146. }
  147. Meteor.users.update(user._id, update_data );
  148. syncUserData(user, ldapUser);
  149. if (LDAP.settings_get('LDAP_LOGIN_FALLBACK') === true) {
  150. Accounts.setPassword(user._id, loginRequest.ldapPass, {logout: false});
  151. }
  152. return {
  153. userId: user._id,
  154. token: stampedToken.token,
  155. };
  156. }
  157. // Create new user
  158. log_info('User does not exist, creating', username);
  159. if (LDAP.settings_get('LDAP_USERNAME_FIELD') === '') {
  160. username = undefined;
  161. }
  162. if (LDAP.settings_get('LDAP_LOGIN_FALLBACK') !== true) {
  163. loginRequest.ldapPass = undefined;
  164. }
  165. const result = addLdapUser(ldapUser, username, loginRequest.ldapPass);
  166. if( LDAP.settings_get('LDAP_SYNC_GROUP_ROLES') === true ) {
  167. const groups = ldap.getUserGroups(username, ldapUser);
  168. if( groups.length > 0 ) {
  169. Roles.setUserRoles(result.userId, groups );
  170. log_info(`Set roles to:${ groups.join(',')}`);
  171. }
  172. }
  173. if (result instanceof Error) {
  174. throw result;
  175. }
  176. return result;
  177. });