1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package edu.internet2.middleware.shibboleth.idp.util;
18
19 import java.util.UUID;
20
21 import javax.servlet.ServletContext;
22 import javax.servlet.http.Cookie;
23 import javax.servlet.http.HttpServletRequest;
24 import javax.servlet.http.HttpServletResponse;
25
26 import org.opensaml.saml2.metadata.EntityDescriptor;
27 import org.opensaml.saml2.metadata.provider.MetadataProviderException;
28 import org.opensaml.util.URLBuilder;
29 import org.opensaml.util.storage.StorageService;
30 import org.opensaml.xml.util.DatatypeHelper;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 import edu.internet2.middleware.shibboleth.common.attribute.filtering.AttributeFilteringEngine;
35 import edu.internet2.middleware.shibboleth.common.attribute.provider.SAML1AttributeAuthority;
36 import edu.internet2.middleware.shibboleth.common.attribute.provider.SAML2AttributeAuthority;
37 import edu.internet2.middleware.shibboleth.common.attribute.resolver.AttributeResolver;
38 import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfigurationManager;
39 import edu.internet2.middleware.shibboleth.common.relyingparty.provider.SAMLMDRelyingPartyConfigurationManager;
40 import edu.internet2.middleware.shibboleth.common.session.SessionManager;
41 import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
42 import edu.internet2.middleware.shibboleth.idp.authn.LoginContextEntry;
43 import edu.internet2.middleware.shibboleth.idp.profile.IdPProfileHandlerManager;
44 import edu.internet2.middleware.shibboleth.idp.session.Session;
45
46
47 public class HttpServletHelper {
48
49
50 public static final String COOKIE_DOMAIN_PARAM = "cookieDomain";
51
52
53 public static final String IDP_SESSION_COOKIE = "_idp_session";
54
55
56 public static final String LOGIN_CTX_KEY_NAME = "_idp_authn_lc_key";
57
58
59 public static final String ATTRIBUTE_FILTER_ENGINE_SID_CTX_PARAM = "AttributeFilterEngineId";
60
61
62 public static final String ATTRIBUTE_RESOLVER_SID_CTX_PARAM = "AttributeResolverId";
63
64
65
66
67
68 public static final String LOGIN_CTX_PARTITION_CTX_PARAM = "loginContextPartitionName";
69
70
71 public static final String PROFILE_HANDLER_MNGR_SID_CTX_PARAM = "ProfileHandlerMngrId";
72
73
74
75
76
77 public static final String RP_CONFIG_MNGR_SID_CTX_PARAM = "RelyingPartyConfigurationManagerId";
78
79
80 public static final String SAML1_AA_SID_CTX_PARAM = "SAML1AttributeAuthorityId";
81
82
83 public static final String SAML2_AA_SID_CTX_PARAM = "SAML2AttributeAuthorityId";
84
85
86 public static final String SESSION_MNGR_SID_CTX_PARAM = "SessionManagerId";
87
88
89 public static final String STORAGE_SERVICE_SID_CTX_PARAM = "StorageServiceId";
90
91
92 public static final String DEFAULT_ATTRIBUTE_FILTER_ENGINE_SID = "shibboleth.AttributeFilterEngine";
93
94
95 public static final String DEFAULT_ATTRIBUTE_RESOLVER_SID = "shibboleth.AttributeResolver";
96
97
98 public static final String DEFAULT_LOGIN_CTX_PARITION = "loginContexts";
99
100
101 public static final String DEFAULT_PROFILE_HANDLER_MNGR_SID = "shibboleth.HandlerManager";
102
103
104 public static final String DEFAULT_RP_CONFIG_MNGR_SID = "shibboleth.RelyingPartyConfigurationManager";
105
106
107 public static final String DEFAULT_SAML1_AA_SID = "shibboleth.SAML1AttributeAuthority";
108
109
110 public static final String DEFAULT_SAML2_AA_SID = "shibboleth.SAML2AttributeAuthority";
111
112
113 public static final String DEFAULT_SESSION_MNGR_SID = "shibboleth.SessionManager";
114
115
116 public static final String DEFAULT_STORAGE_SERVICE_SID = "shibboleth.StorageService";
117
118
119 private static final Logger log = LoggerFactory.getLogger(HttpServletHelper.class);
120
121
122
123
124
125
126
127
128
129 public static void bindLoginContext(LoginContext loginContext, HttpServletRequest httpRequest) {
130 if (httpRequest == null) {
131 throw new IllegalArgumentException("HTTP request may not be null");
132 }
133 httpRequest.setAttribute(LOGIN_CTX_KEY_NAME, loginContext);
134 }
135
136
137
138
139
140
141
142
143
144
145
146 public static void bindLoginContext(LoginContext loginContext, StorageService storageService,
147 ServletContext context, HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
148 if (storageService == null) {
149 throw new IllegalArgumentException("Storage service may not be null");
150 }
151 if (httpRequest == null) {
152 throw new IllegalArgumentException("HTTP request may not be null");
153 }
154 if (loginContext == null) {
155 return;
156 }
157
158 String parition = getContextParam(context, LOGIN_CTX_PARTITION_CTX_PARAM, DEFAULT_LOGIN_CTX_PARITION);
159
160 String contextKey = UUID.randomUUID().toString();
161 while (storageService.contains(parition, contextKey)) {
162 contextKey = UUID.randomUUID().toString();
163 }
164
165 LoginContextEntry entry = new LoginContextEntry(loginContext, 1800000);
166 log.debug("Storing LoginContext to StorageService partition {}, key {}", parition, contextKey);
167 storageService.put(parition, contextKey, entry);
168
169 String cookieDomain = getCookieDomain(context);
170
171 Cookie contextKeyCookie = new Cookie(LOGIN_CTX_KEY_NAME, contextKey);
172 contextKeyCookie.setVersion(1);
173 if (cookieDomain != null) {
174 contextKeyCookie.setDomain(cookieDomain);
175 }
176 contextKeyCookie.setPath("".equals(httpRequest.getContextPath()) ? "/" : httpRequest.getContextPath());
177 contextKeyCookie.setSecure(httpRequest.isSecure());
178 httpResponse.addCookie(contextKeyCookie);
179 }
180
181
182
183
184
185
186
187
188 public static String getCookieDomain(ServletContext context) {
189 return context.getInitParameter(COOKIE_DOMAIN_PARAM);
190 }
191
192
193
194
195
196
197
198
199 public static AttributeFilteringEngine<?> getAttributeFilterEnginer(ServletContext context) {
200 return getAttributeFilterEnginer(context, getContextParam(context, ATTRIBUTE_FILTER_ENGINE_SID_CTX_PARAM,
201 DEFAULT_ATTRIBUTE_FILTER_ENGINE_SID));
202 }
203
204
205
206
207
208
209
210
211
212 public static AttributeFilteringEngine<?> getAttributeFilterEnginer(ServletContext context, String serviceId) {
213 return (AttributeFilteringEngine<?>) context.getAttribute(serviceId);
214 }
215
216
217
218
219
220
221
222
223 public static AttributeResolver<?> getAttributeResolver(ServletContext context) {
224 return getAttributeResolver(context, getContextParam(context, ATTRIBUTE_RESOLVER_SID_CTX_PARAM,
225 DEFAULT_ATTRIBUTE_RESOLVER_SID));
226 }
227
228
229
230
231
232
233
234
235
236 public static AttributeResolver<?> getAttributeResolver(ServletContext context, String serviceId) {
237 return (AttributeResolver<?>) context.getAttribute(serviceId);
238 }
239
240
241
242
243
244
245
246
247
248
249
250 public static String getContextParam(ServletContext context, String name, String defaultValue) {
251 String value = DatatypeHelper.safeTrimOrNullString(context.getInitParameter(name));
252 if (value == null) {
253 value = defaultValue;
254 }
255 return value;
256 }
257
258
259
260
261
262
263
264
265
266 public static Cookie getCookie(HttpServletRequest httpRequest, String cookieName) {
267 Cookie[] requestCookies = httpRequest.getCookies();
268 if (requestCookies != null) {
269 for (Cookie requestCookie : requestCookies) {
270 if (requestCookie != null && DatatypeHelper.safeEquals(requestCookie.getName(), cookieName)) {
271 return requestCookie;
272 }
273 }
274 }
275
276 return null;
277 }
278
279
280
281
282
283
284
285
286
287
288 public static LoginContext getLoginContext(HttpServletRequest httpRequest) {
289 return (LoginContext) httpRequest.getAttribute(LOGIN_CTX_KEY_NAME);
290 }
291
292
293
294
295
296
297
298
299
300
301
302 public static LoginContext getLoginContext(StorageService storageService, ServletContext context,
303 HttpServletRequest httpRequest) {
304 if (storageService == null) {
305 throw new IllegalArgumentException("Storage service may not be null");
306 }
307 if (context == null) {
308 throw new IllegalArgumentException("Servlet context may not be null");
309 }
310 if (httpRequest == null) {
311 throw new IllegalArgumentException("HTTP request may not be null");
312 }
313
314 Cookie loginContextKeyCookie = getCookie(httpRequest, LOGIN_CTX_KEY_NAME);
315 if (loginContextKeyCookie == null) {
316 log.debug("LoginContext key cookie was not present in request");
317 return null;
318 }
319
320 String loginContextKey = DatatypeHelper.safeTrimOrNullString(loginContextKeyCookie.getValue());
321 if (loginContextKey == null) {
322 log.warn("Corrupted LoginContext Key cookie, it did not contain a value");
323 }
324
325 String partition = getContextParam(context, LOGIN_CTX_PARTITION_CTX_PARAM, DEFAULT_LOGIN_CTX_PARITION);
326 log.debug("Looking up LoginContext with key {} from StorageService parition: {}", loginContextKey, partition);
327 LoginContextEntry entry = (LoginContextEntry) storageService.get(partition, loginContextKey);
328 if (entry != null) {
329 if (entry.isExpired()) {
330 log.debug("LoginContext found but it was expired");
331 } else {
332 log.debug("Retrieved LoginContext with key {} from StorageService parition: {}", loginContextKey,
333 partition);
334 return entry.getLoginContext();
335 }
336 } else {
337 log.debug("No login context in storage service");
338 }
339
340 return null;
341 }
342
343
344
345
346
347
348
349
350 public static IdPProfileHandlerManager getProfileHandlerManager(ServletContext context) {
351 return getProfileHandlerManager(context, getContextParam(context, PROFILE_HANDLER_MNGR_SID_CTX_PARAM,
352 DEFAULT_PROFILE_HANDLER_MNGR_SID));
353 }
354
355
356
357
358
359
360
361
362
363 public static IdPProfileHandlerManager getProfileHandlerManager(ServletContext context, String serviceId) {
364 return (IdPProfileHandlerManager) context.getAttribute(serviceId);
365 }
366
367
368
369
370
371
372
373
374 public static RelyingPartyConfigurationManager getRelyingPartyConfigurationManager(ServletContext context) {
375 return getRelyingPartyConfigurationManager(context, getContextParam(context, RP_CONFIG_MNGR_SID_CTX_PARAM,
376 DEFAULT_RP_CONFIG_MNGR_SID));
377 }
378
379
380
381
382
383
384
385
386
387 public static RelyingPartyConfigurationManager getRelyingPartyConfigurationManager(ServletContext context,
388 String serviceId) {
389 return (RelyingPartyConfigurationManager) context.getAttribute(serviceId);
390 }
391
392
393
394
395
396
397
398
399
400
401 public static RelyingPartyConfigurationManager getRelyingPartyConfirmationManager(ServletContext context) {
402 return getRelyingPartyConfirmationManager(context, getContextParam(context, RP_CONFIG_MNGR_SID_CTX_PARAM,
403 DEFAULT_RP_CONFIG_MNGR_SID));
404 }
405
406
407
408
409
410
411
412
413
414
415
416
417 public static RelyingPartyConfigurationManager getRelyingPartyConfirmationManager(ServletContext context,
418 String serviceId) {
419 return (RelyingPartyConfigurationManager) context.getAttribute(serviceId);
420 }
421
422
423
424
425
426
427
428
429
430 public static EntityDescriptor getRelyingPartyMetadata(String relyingPartyEntityId,
431 RelyingPartyConfigurationManager rpConfigMngr) {
432 if (rpConfigMngr instanceof SAMLMDRelyingPartyConfigurationManager) {
433 SAMLMDRelyingPartyConfigurationManager samlRpConfigMngr = (SAMLMDRelyingPartyConfigurationManager) rpConfigMngr;
434 try {
435 return samlRpConfigMngr.getMetadataProvider().getEntityDescriptor(relyingPartyEntityId);
436 } catch (MetadataProviderException e) {
437
438 }
439 }
440
441 return null;
442 }
443
444
445
446
447
448
449
450
451 public static SAML1AttributeAuthority getSAML1AttributeAuthority(ServletContext context) {
452 return getSAML1AttributeAuthority(context, getContextParam(context, SAML1_AA_SID_CTX_PARAM,
453 DEFAULT_SAML1_AA_SID));
454 }
455
456
457
458
459
460
461
462
463
464 public static SAML1AttributeAuthority getSAML1AttributeAuthority(ServletContext context, String serviceId) {
465 return (SAML1AttributeAuthority) context.getAttribute(serviceId);
466 }
467
468
469
470
471
472
473
474
475 public static SAML2AttributeAuthority getSAML2AttributeAuthority(ServletContext context) {
476 return getSAML2AttributeAuthority(context, getContextParam(context, SAML2_AA_SID_CTX_PARAM,
477 DEFAULT_SAML2_AA_SID));
478 }
479
480
481
482
483
484
485
486
487
488 public static SAML2AttributeAuthority getSAML2AttributeAuthority(ServletContext context, String serviceId) {
489 return (SAML2AttributeAuthority) context.getAttribute(serviceId);
490 }
491
492
493
494
495
496
497
498
499 public static SessionManager<Session> getSessionManager(ServletContext context) {
500 return getSessionManager(context,
501 getContextParam(context, SESSION_MNGR_SID_CTX_PARAM, DEFAULT_SESSION_MNGR_SID));
502 }
503
504
505
506
507
508
509
510
511
512 public static SessionManager<Session> getSessionManager(ServletContext context, String serviceId) {
513 return (SessionManager<Session>) context.getAttribute(serviceId);
514 }
515
516
517
518
519
520
521
522
523 public static StorageService<?, ?> getStorageService(ServletContext context) {
524 return getStorageService(context, getContextParam(context, STORAGE_SERVICE_SID_CTX_PARAM,
525 DEFAULT_STORAGE_SERVICE_SID));
526 }
527
528
529
530
531
532
533
534
535
536 public static StorageService<?, ?> getStorageService(ServletContext context, String serviceId) {
537 return (StorageService<?, ?>) context.getAttribute(serviceId);
538 }
539
540
541
542
543
544
545
546
547
548 public static Session getUserSession(HttpServletRequest httpRequest) {
549 return (Session) httpRequest.getAttribute(Session.HTTP_SESSION_BINDING_ATTRIBUTE);
550 }
551
552
553
554
555
556
557
558
559
560
561
562
563 public static LoginContext unbindLoginContext(StorageService storageService, ServletContext context,
564 HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
565 log.debug("Unbinding LoginContext");
566 if (storageService == null) {
567 throw new IllegalArgumentException("Storage service may not be null");
568 }
569 if (context == null) {
570 throw new IllegalArgumentException("Servlet context may not be null");
571 }
572 if (httpRequest == null) {
573 throw new IllegalArgumentException("HTTP request may not be null");
574 }
575 if (httpResponse == null) {
576 throw new IllegalArgumentException("HTTP request may not be null");
577 }
578
579 Cookie loginContextKeyCookie = getCookie(httpRequest, LOGIN_CTX_KEY_NAME);
580 if (loginContextKeyCookie == null) {
581 log.debug("No LoginContext cookie available, no unbinding necessary.");
582 return null;
583 }
584
585 String loginContextKey = DatatypeHelper.safeTrimOrNullString(loginContextKeyCookie.getValue());
586 if (loginContextKey == null) {
587 log.warn("Corrupted LoginContext Key cookie, it did not contain a value");
588 return null;
589 }
590
591 log.debug("Expiring LoginContext cookie");
592 loginContextKeyCookie.setMaxAge(0);
593 loginContextKeyCookie.setPath("".equals(httpRequest.getContextPath()) ? "/" : httpRequest.getContextPath());
594 loginContextKeyCookie.setVersion(1);
595 httpResponse.addCookie(loginContextKeyCookie);
596
597 String storageServicePartition = getContextParam(context, LOGIN_CTX_PARTITION_CTX_PARAM,
598 DEFAULT_LOGIN_CTX_PARITION);
599
600 log.debug("Removing LoginContext, with key {}, from StorageService partition {}", loginContextKey,
601 storageServicePartition);
602 LoginContextEntry entry = (LoginContextEntry) storageService.remove(storageServicePartition, loginContextKey);
603 if (entry != null && !entry.isExpired()) {
604 return entry.getLoginContext();
605 }
606
607 return null;
608 }
609
610
611
612
613
614
615
616
617 public static URLBuilder getServletContextUrl(HttpServletRequest httpRequest) {
618 URLBuilder urlBuilder = new URLBuilder();
619 urlBuilder.setScheme(httpRequest.getScheme());
620 urlBuilder.setHost(httpRequest.getServerName());
621 urlBuilder.setPort(httpRequest.getServerPort());
622 urlBuilder.setPath(httpRequest.getContextPath());
623 return urlBuilder;
624 }
625 }