Browse code

BM-13081 Imp: IAuthProvider use IAuthContext to give already loaded values

Anthony Prades authored on 13/04/2018 08:49:56
Showing 8 changed files
... ...
@@ -7,6 +7,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8
7 7
 Require-Bundle: net.bluemind.core.commons;bundle-version="1.0.0";visibility:=reexport,
8 8
  net.bluemind.core.container.api;bundle-version="1.0.0";visibility:=reexport,
9 9
  net.bluemind.domain.api;visibility:=reexport,
10
- net.bluemind.core.context;visibility:=reexport
10
+ net.bluemind.core.context;visibility:=reexport,
11
+ net.bluemind.user.api
11 12
 Export-Package: net.bluemind.authentication.provider
12 13
 
... ...
@@ -1,9 +1,23 @@
1 1
 package net.bluemind.authentication.provider;
2 2
 
3 3
 import net.bluemind.core.api.fault.ServerFault;
4
+import net.bluemind.core.container.model.ItemValue;
4 5
 import net.bluemind.core.context.SecurityContext;
6
+import net.bluemind.domain.api.Domain;
7
+import net.bluemind.user.api.User;
5 8
 
6 9
 public interface IAuthProvider {
10
+	public interface IAuthContext {
11
+		public SecurityContext getSecurityContext();
12
+
13
+		public ItemValue<Domain> getDomain();
14
+
15
+		public ItemValue<User> getUser();
16
+
17
+		public String getRealUserLogin();
18
+
19
+		public String getUserPassword();
20
+	}
7 21
 
8 22
 	public enum AuthResult {
9 23
 		YES, NO, UNKNOWN
... ...
@@ -11,6 +25,5 @@ public interface IAuthProvider {
11 11
 
12 12
 	int priority();
13 13
 
14
-	AuthResult check(SecurityContext context, String domain, String login, String password) throws ServerFault;
15
-
14
+	AuthResult check(IAuthContext authContext) throws ServerFault;
16 15
 }
... ...
@@ -43,6 +43,7 @@ import net.bluemind.authentication.api.ValidationKind;
43 43
 import net.bluemind.authentication.api.incore.IInCoreAuthentication;
44 44
 import net.bluemind.authentication.provider.IAuthProvider;
45 45
 import net.bluemind.authentication.provider.IAuthProvider.AuthResult;
46
+import net.bluemind.authentication.provider.IAuthProvider.IAuthContext;
46 47
 import net.bluemind.authentication.provider.ILoginSessionValidator;
47 48
 import net.bluemind.authentication.provider.ILoginValidationListener;
48 49
 import net.bluemind.core.api.ParametersValidator;
... ...
@@ -93,10 +94,46 @@ public class Authentication implements IAuthentication, IInCoreAuthentication {
93 93
 		domains = context.su().provider().instance(IDomains.class);
94 94
 	}
95 95
 
96
-	private static class AuthContext {
97
-		ItemValue<Domain> domain;
98
-		ItemValue<User> user;
99
-		public String localPart;
96
+	private static class AuthContext implements IAuthContext {
97
+		public final SecurityContext securityContext;
98
+		public final ItemValue<Domain> domain;
99
+		public final ItemValue<User> user;
100
+		public final String localPart;
101
+		public final String userPassword;
102
+
103
+		public AuthContext(SecurityContext securityContext, ItemValue<Domain> domain, ItemValue<User> user,
104
+				String localPart, String userPassword) {
105
+			this.securityContext = securityContext;
106
+			this.domain = domain;
107
+			this.user = user;
108
+			this.localPart = localPart;
109
+			this.userPassword = userPassword;
110
+		}
111
+
112
+		@Override
113
+		public SecurityContext getSecurityContext() {
114
+			return securityContext;
115
+		}
116
+
117
+		@Override
118
+		public ItemValue<Domain> getDomain() {
119
+			return domain;
120
+		}
121
+
122
+		@Override
123
+		public ItemValue<User> getUser() {
124
+			return user;
125
+		}
126
+
127
+		@Override
128
+		public String getRealUserLogin() {
129
+			return user != null ? user.value.login : localPart;
130
+		}
131
+
132
+		@Override
133
+		public String getUserPassword() {
134
+			return userPassword;
135
+		}
100 136
 	}
101 137
 
102 138
 	@Override
... ...
@@ -125,7 +162,7 @@ public class Authentication implements IAuthentication, IInCoreAuthentication {
125 125
 			}
126 126
 		}
127 127
 
128
-		AuthContext authContext = buildAuthContext(login);
128
+		AuthContext authContext = buildAuthContext(login, password);
129 129
 
130 130
 		LoginResponse resp = new LoginResponse();
131 131
 
... ...
@@ -150,22 +187,13 @@ public class Authentication implements IAuthentication, IInCoreAuthentication {
150 150
 			}
151 151
 		}
152 152
 
153
-		String realLogin = authContext.user != null ? authContext.user.value.login : authContext.localPart;
154
-		String realDomain = authContext.domain.uid;
155
-
156 153
 		if (result != AuthResult.YES) {
157
-			result = checkProviders(realLogin, realDomain, password, origin);
154
+			result = checkProviders(authContext, origin);
158 155
 		}
159 156
 
160 157
 		// user created JIT
161 158
 		if (result == AuthResult.YES && authContext.user == null) {
162
-			authContext = buildAuthContext(login);
163
-		}
164
-
165
-		if (authContext.user != null && authContext.user.value.archived) {
166
-			logger.warn("user {} is archived", login);
167
-			resp.status = Status.Bad;
168
-			authContext.user = null;
159
+			authContext = buildAuthContext(login, password);
169 160
 		}
170 161
 
171 162
 		if (authContext.user == null) {
... ...
@@ -185,8 +213,8 @@ public class Authentication implements IAuthentication, IInCoreAuthentication {
185 185
 			if (context == null) {
186 186
 				logger.info("l: '{}', o: '{}' successfully authentified", login, origin);
187 187
 				resp.authKey = UUID.randomUUID().toString();
188
-				context = buildSecurityContext(resp.authKey, authContext.user.uid, realDomain, settings, origin,
189
-						interactive);
188
+				context = buildSecurityContext(resp.authKey, authContext.user.uid, authContext.domain.uid, settings,
189
+						origin, interactive);
190 190
 
191 191
 				for (ILoginSessionValidator v : sessionValidators) {
192 192
 					try {
... ...
@@ -225,8 +253,7 @@ public class Authentication implements IAuthentication, IInCoreAuthentication {
225 225
 		return resp;
226 226
 	}
227 227
 
228
-	private AuthContext buildAuthContext(String login) throws ServerFault {
229
-
228
+	private AuthContext buildAuthContext(String login, String password) throws ServerFault {
230 229
 		Iterator<String> splitted = atSplitter.split(login).iterator();
231 230
 		String localPart = splitted.next();
232 231
 		String domainPart = null;
... ...
@@ -249,10 +276,6 @@ public class Authentication implements IAuthentication, IInCoreAuthentication {
249 249
 			logger.debug("Found domain {}", theDomain.uid);
250 250
 		}
251 251
 
252
-		AuthContext ret = new AuthContext();
253
-		ret.domain = theDomain;
254
-		ret.localPart = localPart;
255
-
256 252
 		IUser userService = sp.instance(IUser.class, theDomain.uid);
257 253
 
258 254
 		ItemValue<User> internalUser = userService.byLogin(localPart);
... ...
@@ -262,34 +285,36 @@ public class Authentication implements IAuthentication, IInCoreAuthentication {
262 262
 
263 263
 		if (internalUser == null) {
264 264
 			logger.warn("no user found for login {}", login);
265
-			return ret;
266 265
 		} else {
267 266
 			logger.debug("found user {}", internalUser);
267
+
268
+			if (internalUser.value.archived) {
269
+				logger.warn("user {} is archived", login);
270
+				internalUser = null;
271
+			}
268 272
 		}
269 273
 
270
-		ret.user = internalUser;
271
-		return ret;
274
+		return new AuthContext(context.getSecurityContext(), theDomain, internalUser, localPart, password);
272 275
 	}
273 276
 
274
-	private AuthResult checkProviders(String localPart, String domainPart, String password, String origin)
275
-			throws ServerFault {
276
-
277
+	private AuthResult checkProviders(AuthContext authContext, String origin) throws ServerFault {
277 278
 		if (logger.isDebugEnabled()) {
278
-			logger.debug("[{}@{}] Auth attempt from {}", localPart, domainPart, origin);
279
+			logger.debug("[{}@{}] Auth attempt from {}", authContext.localPart, authContext.domain.value.name, origin);
279 280
 		}
280 281
 
281 282
 		AuthResult result = AuthResult.UNKNOWN;
282 283
 
283
-		ItemValue<Domain> domain = domains.get(domainPart);
284
-		if (domain == null) {
285
-			logger.warn("[{}] authenticate: {}", localPart + "@" + domainPart, result);
284
+		if (authContext.domain == null) {
285
+			logger.warn("[{}@{}] authenticate: {}", authContext.getRealUserLogin(), authContext.domain.value.name,
286
+					result);
286 287
 			return AuthResult.NO;
287 288
 		}
288 289
 		IAuthProvider matchingProvider = null;
289 290
 		for (IAuthProvider provider : authProviders) {
290
-			result = provider.check(context.getSecurityContext(), domain.uid, localPart, password);
291
+			result = provider.check(authContext);
291 292
 			if (logger.isDebugEnabled()) {
292
-				logger.debug("[{}] {} result: {}", localPart + "@" + domain.uid, provider, result);
293
+				logger.debug("[{}@{}] {} result: {}", authContext.getRealUserLogin(), authContext.domain.value.name,
294
+						provider, result);
293 295
 			}
294 296
 
295 297
 			if (result == AuthResult.YES || result == AuthResult.NO) {
... ...
@@ -301,12 +326,14 @@ public class Authentication implements IAuthentication, IInCoreAuthentication {
301 301
 
302 302
 		if (result == AuthResult.YES) {
303 303
 			for (ILoginValidationListener vl : loginListeners) {
304
-				vl.onValidLogin(matchingProvider, localPart, domain.uid, password);
304
+				vl.onValidLogin(matchingProvider, authContext.getRealUserLogin(), authContext.domain.uid,
305
+						authContext.userPassword);
305 306
 			}
306 307
 		}
307 308
 
308 309
 		if (logger.isDebugEnabled()) {
309
-			logger.debug("[{}] authenticate: {}", localPart + "@" + domain.uid, result);
310
+			logger.debug("[{}@{}] authenticate: {}", authContext.getRealUserLogin(), authContext.domain.value.name,
311
+					result);
310 312
 		}
311 313
 
312 314
 		return result;
... ...
@@ -458,7 +485,7 @@ public class Authentication implements IAuthentication, IInCoreAuthentication {
458 458
 	@Override
459 459
 	public ValidationKind validate(String login, String password, String origin) throws ServerFault {
460 460
 
461
-		AuthContext authContext = buildAuthContext(login);
461
+		AuthContext authContext = buildAuthContext(login, password);
462 462
 		if (authContext == null || authContext.user == null) {
463 463
 			logger.error("validate failed for login: {} origin: {} remoteIps: {}", login, origin,
464 464
 					securityContext.getRemoteAddresses());
... ...
@@ -472,7 +499,7 @@ public class Authentication implements IAuthentication, IInCoreAuthentication {
472 472
 			return ValidationKind.TOKEN;
473 473
 		}
474 474
 
475
-		if (checkProviders(authContext.user.value.login, authContext.domain.uid, password, origin) == AuthResult.YES) {
475
+		if (checkProviders(authContext, origin) == AuthResult.YES) {
476 476
 			return ValidationKind.PASSWORD;
477 477
 		} else {
478 478
 			logger.error("validate password or token failed for login: {} origin: {} remoteIps: {}", login, origin,
... ...
@@ -36,7 +36,6 @@ import net.bluemind.core.rest.IServiceProvider;
36 36
 import net.bluemind.core.rest.ServerSideServiceProvider;
37 37
 import net.bluemind.domain.api.Domain;
38 38
 import net.bluemind.domain.api.IDomainSettings;
39
-import net.bluemind.domain.api.IDomains;
40 39
 import net.bluemind.system.ldap.importation.internal.tools.ImportLdapParameters;
41 40
 import net.bluemind.system.ldap.importation.internal.tools.LdapHelper;
42 41
 import net.bluemind.system.ldap.importation.internal.tools.UuidMapper;
... ...
@@ -64,13 +63,11 @@ public class ImportLdapAuthenticationService implements IAuthProvider {
64 64
 	}
65 65
 
66 66
 	@Override
67
-	public AuthResult check(SecurityContext sc, String domainUid, String userLogin, String userPassword) {
67
+	public AuthResult check(IAuthContext authContext) {
68 68
 		ImportLdapParameters ldapParameters;
69
-		ItemValue<Domain> domain = null;
69
+		ItemValue<Domain> domain = authContext.getDomain();
70 70
 		Map<String, String> domainSettings = null;
71 71
 		try {
72
-			domain = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM).instance(IDomains.class)
73
-					.get(domainUid);
74 72
 			domainSettings = ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM)
75 73
 					.instance(IDomainSettings.class, domain.uid).get();
76 74
 		} catch (ServerFault e) {
... ...
@@ -83,29 +80,29 @@ public class ImportLdapAuthenticationService implements IAuthProvider {
83 83
 			return AuthResult.UNKNOWN;
84 84
 		}
85 85
 
86
-		String userDn = getLdapUserDn(ldapParameters, domain, userLogin);
86
+		String userDn = getLdapUserDn(ldapParameters, domain, authContext.getRealUserLogin());
87 87
 		if (userDn == null) {
88 88
 			if (logger.isDebugEnabled()) {
89
-				logger.debug("Can't find user: " + userLogin + "@" + domainUid + " in LDAP server: "
90
-						+ ldapParameters.getHostname() + ", return: " + AuthResult.UNKNOWN);
89
+				logger.debug("Can't find user: {}@{} in LDAP server: {}, return: {}", authContext.getRealUserLogin(),
90
+						domain.value.name, ldapParameters.getHostname(), AuthResult.UNKNOWN);
91 91
 			}
92 92
 
93 93
 			return AuthResult.UNKNOWN;
94 94
 		}
95 95
 
96 96
 		if (logger.isDebugEnabled()) {
97
-			logger.debug("Trying to authenticate user: " + userLogin + "@" + domain.value.name + ", Dn: " + userDn
98
-					+ ", against LDAP server: " + ldapParameters.getHostname());
97
+			logger.debug("Trying to authenticate user: {}@{}, Dn: {}, against LDAP server: {}",
98
+					authContext.getRealUserLogin(), domain.value.name, userDn, ldapParameters.getHostname());
99 99
 		}
100 100
 
101 101
 		String cachedPass = dnToPass.getIfPresent(userDn);
102
-		if (cachedPass != null && cachedPass.equals(userPassword)) {
102
+		if (cachedPass != null && cachedPass.equals(authContext.getUserPassword())) {
103 103
 			logger.debug("Allowed from dnToPass cache system");
104 104
 			return AuthResult.YES;
105 105
 		}
106 106
 
107
-		if (LdapHelper.checkLdapAuth(ldapParameters, userDn, userPassword)) {
108
-			dnToPass.put(userDn, userPassword);
107
+		if (LdapHelper.checkLdapAuth(ldapParameters, userDn, authContext.getUserPassword())) {
108
+			dnToPass.put(userDn, authContext.getUserPassword());
109 109
 			return AuthResult.YES;
110 110
 		} else {
111 111
 			return AuthResult.NO;
... ...
@@ -26,6 +26,7 @@ import net.bluemind.core.api.fault.ServerFault;
26 26
 import net.bluemind.core.container.model.ItemValue;
27 27
 import net.bluemind.core.context.SecurityContext;
28 28
 import net.bluemind.core.rest.ServerSideServiceProvider;
29
+import net.bluemind.domain.api.Domain;
29 30
 import net.bluemind.user.api.IUser;
30 31
 import net.bluemind.user.api.User;
31 32
 
... ...
@@ -39,23 +40,22 @@ public class APIKeyAuthProvider implements IAuthProvider {
39 39
 	}
40 40
 
41 41
 	@Override
42
-	public AuthResult check(SecurityContext sc, String domain, String login, String password) throws ServerFault {
43
-		if (domain == null || login == null || password == null) {
42
+	public AuthResult check(IAuthContext authContext) throws ServerFault {
43
+		ItemValue<Domain> domain = authContext.getDomain();
44
+		ItemValue<User> user = authContext.getUser();
45
+		String login = authContext.getRealUserLogin();
46
+		String password = authContext.getUserPassword();
47
+
48
+		if (domain == null || user == null || login == null || password == null) {
44 49
 			return AuthResult.UNKNOWN;
45 50
 		}
46 51
 
47 52
 		if (logger.isDebugEnabled()) {
48
-			logger.debug("check {} @ {} with password {}", login, domain, password);
53
+			logger.debug("check {} @ {} with password {}", login, domain.value.name, password);
49 54
 		}
50 55
 
51 56
 		UserService userService = (UserService) ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM)
52
-				.instance(IUser.class, domain);
53
-		ItemValue<User> user = userService.byLogin(login);
54
-		if (user != null) {
55
-			return userService.checkApiKey(user.uid, password) ? AuthResult.YES : AuthResult.UNKNOWN;
56
-		} else {
57
-			return AuthResult.UNKNOWN;
58
-		}
59
-
57
+				.instance(IUser.class, domain.uid);
58
+		return userService.checkApiKey(user.uid, password) ? AuthResult.YES : AuthResult.UNKNOWN;
60 59
 	}
61 60
 }
... ...
@@ -5,8 +5,10 @@ import org.slf4j.LoggerFactory;
5 5
 
6 6
 import net.bluemind.authentication.provider.IAuthProvider;
7 7
 import net.bluemind.core.api.fault.ServerFault;
8
+import net.bluemind.core.container.model.ItemValue;
8 9
 import net.bluemind.core.context.SecurityContext;
9 10
 import net.bluemind.core.rest.ServerSideServiceProvider;
11
+import net.bluemind.domain.api.Domain;
10 12
 import net.bluemind.user.api.IUser;
11 13
 
12 14
 public class DatabaseAuthProvider implements IAuthProvider {
... ...
@@ -14,19 +16,20 @@ public class DatabaseAuthProvider implements IAuthProvider {
14 14
 	private static final Logger logger = LoggerFactory.getLogger(DatabaseAuthProvider.class);
15 15
 
16 16
 	@Override
17
-	public AuthResult check(SecurityContext sc, String domain, String login, String password) throws ServerFault {
17
+	public AuthResult check(IAuthContext authContext) throws ServerFault {
18
+		ItemValue<Domain> domain = authContext.getDomain();
19
+		String login = authContext.getRealUserLogin();
18 20
 		if (domain == null || login == null) {
19 21
 			return AuthResult.UNKNOWN;
20 22
 		}
21 23
 
22 24
 		if (logger.isDebugEnabled()) {
23
-			logger.debug("check {}@{} with password {}", login, domain, password);
25
+			logger.debug("check {}@{} with password {}", login, domain.value.name, authContext.getUserPassword());
24 26
 		}
25 27
 
26 28
 		UserService userService = (UserService) ServerSideServiceProvider.getProvider(SecurityContext.SYSTEM)
27
-				.instance(IUser.class, domain);
28
-
29
-		return userService.checkPassword(login, password) ? AuthResult.YES : AuthResult.NO;
29
+				.instance(IUser.class, domain.uid);
30
+		return userService.checkPassword(login, authContext.getUserPassword()) ? AuthResult.YES : AuthResult.NO;
30 31
 	}
31 32
 
32 33
 	@Override
... ...
@@ -24,7 +24,9 @@ import org.slf4j.LoggerFactory;
24 24
 import net.bluemind.authentication.provider.IAuthProvider;
25 25
 import net.bluemind.config.Token;
26 26
 import net.bluemind.core.api.fault.ServerFault;
27
+import net.bluemind.core.container.model.ItemValue;
27 28
 import net.bluemind.core.context.SecurityContext;
29
+import net.bluemind.domain.api.Domain;
28 30
 
29 31
 public class TokenAuthProvider implements IAuthProvider {
30 32
 
... ...
@@ -36,14 +38,19 @@ public class TokenAuthProvider implements IAuthProvider {
36 36
 	}
37 37
 
38 38
 	@Override
39
-	public AuthResult check(SecurityContext sc, String domain, String login, String password) throws ServerFault {
39
+	public AuthResult check(IAuthContext authContext) throws ServerFault {
40
+		SecurityContext sc = authContext.getSecurityContext();
41
+		ItemValue<Domain> domain = authContext.getDomain();
42
+		String login = authContext.getRealUserLogin();
43
+		String password = authContext.getUserPassword();
44
+
40 45
 		AuthResult ret = AuthResult.UNKNOWN;
41 46
 
42 47
 		if (logger.isDebugEnabled()) {
43
-			logger.debug("check {}@{} with password {}", login, domain, password);
48
+			logger.debug("check {}@{} with password {}", login, domain.value.name, password);
44 49
 		}
45 50
 
46
-		if ("admin0".equals(login) && "global.virt".equals(domain)) {
51
+		if ("admin0".equals(login) && "global.virt".equals(domain.value.name)) {
47 52
 			if (Token.admin0().equals(password)) {
48 53
 				ret = AuthResult.YES;
49 54
 			} else {
... ...
@@ -30,7 +30,6 @@ import com.google.common.cache.CacheBuilder;
30 30
 import net.bluemind.authentication.provider.IAuthProvider;
31 31
 import net.bluemind.authentication.provider.ILoginValidationListener;
32 32
 import net.bluemind.core.api.fault.ServerFault;
33
-import net.bluemind.core.context.SecurityContext;
34 33
 
35 34
 public class Fail2Ban implements ILoginValidationListener, IAuthProvider {
36 35
 	private static final Logger logger = LoggerFactory.getLogger(Fail2Ban.class);
... ...
@@ -47,9 +46,8 @@ public class Fail2Ban implements ILoginValidationListener, IAuthProvider {
47 47
 	}
48 48
 
49 49
 	@Override
50
-	public AuthResult check(SecurityContext context, String domain, String userLogin, String password)
51
-			throws ServerFault {
52
-		String latd = userLogin + "@" + domain;
50
+	public AuthResult check(IAuthContext authContext) throws ServerFault {
51
+		String latd = authContext.getRealUserLogin() + "@" + authContext.getDomain().value.name;
53 52
 		AtomicInteger authCount = trials.getIfPresent(latd);
54 53
 		if (authCount == null) {
55 54
 			logger.debug("First attempt for {}", latd);
... ...
@@ -59,7 +57,7 @@ public class Fail2Ban implements ILoginValidationListener, IAuthProvider {
59 59
 			int val = authCount.incrementAndGet();
60 60
 			if (val > 3) {
61 61
 				logger.warn("Too many ({}) attempts for {}/{}. Wait 20sec to retry", val, latd,
62
-						context.getRemoteAddresses());
62
+						authContext.getSecurityContext().getRemoteAddresses());
63 63
 				return AuthResult.NO;
64 64
 			} else {
65 65
 				logger.info("** Attempt {} for {}", val, latd);