-
Notifications
You must be signed in to change notification settings - Fork 51
/
SAMLFilter.java
137 lines (119 loc) · 5.09 KB
/
SAMLFilter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package org.zanata.servlet;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.inject.Inject;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.picketlink.common.constants.GeneralConstants;
import org.picketlink.identity.federation.bindings.wildfly.sp.SPFormAuthenticationMechanism;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zanata.security.AuthenticationManager;
import org.zanata.util.UrlUtil;
import io.undertow.security.idm.Account;
/**
* @author Patrick Huang
* <a href="mailto:pahuang@redhat.com">pahuang@redhat.com</a>
*/
@WebFilter(filterName = "ssoFilter")
public class SAMLFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(SAMLFilter.class);
@Inject
private AuthenticationManager authenticationManager;
@Inject
private UrlUtil urlUtil;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
HttpServletRequest r = (HttpServletRequest) request;
Object account = r.getSession().getAttribute(
SPFormAuthenticationMechanism.FORM_ACCOUNT_NOTE);
if (account != null && account instanceof Account) {
Account acc = (Account) account;
Optional<Map<String, List<String>>> samlAttributeMap =
getSAMLAttributeMap(r.getSession());
// These assumes IDP follow standard SAML assertion names
Optional<String> usernameFromSSO =
getValueFromSessionAttribute(samlAttributeMap, "uid");
Optional<String> emailFromSSO = getValueFromSessionAttribute(samlAttributeMap, "email");
Optional<String> nameFromSSO = getValueFromSessionAttribute(samlAttributeMap, "cn");
if (acc.getRoles().contains("authenticated")) {
String principalName = acc.getPrincipal().getName();
log.info("SSO login: username: {}, name: {}, uuid: {}",
usernameFromSSO, nameFromSSO, principalName);
authenticationManager.ssoLogin(acc,
usernameFromSSO.orElse(principalName),
emailFromSSO.orElse(""), nameFromSSO.orElse(""));
performRedirection((HttpServletResponse) response);
return;
}
}
}
chain.doFilter(request, response);
}
private static Optional<String> getValueFromSessionAttribute(
Optional<Map<String, List<String>>> samlAttributeMap, String key) {
return samlAttributeMap.flatMap(m -> m.get(key).stream().findFirst());
}
@SuppressWarnings("unchecked")
private Optional<Map<String, List<String>>>
getSAMLAttributeMap(HttpSession session) {
Object attributeMap =
session.getAttribute(GeneralConstants.SESSION_ATTRIBUTE_MAP);
return attributeMap != null && attributeMap instanceof Map
? Optional.of((Map<String, List<String>>) attributeMap)
: Optional.empty();
}
@Override
public void destroy() {
}
/**
* Performs the redirection based on the results from the authentication
* process.
* This is logic that would normally be in faces-config.xml, but as this is
* a servlet, it cannot take advantage of that.
*/
private void performRedirection(HttpServletResponse resp) throws IOException {
String authRedirectResult =
authenticationManager.getAuthenticationRedirect();
switch (authRedirectResult) {
case "login":
resp.sendRedirect(urlUtil.signInPage());
break;
case "edit":
resp.sendRedirect(urlUtil.createUserPage());
break;
case "inactive":
resp.sendRedirect(urlUtil.inactiveAccountPage());
break;
case "dashboard":
resp.sendRedirect(urlUtil.dashboardUrl());
break;
case "redirect":
// sso should not have any continue url. We just send to dashboard
resp.sendRedirect(urlUtil.dashboardUrl());
break;
case "home":
resp.sendRedirect(urlUtil.home());
break;
default:
throw new RuntimeException(
"Unexpected authentication manager result: " +
authRedirectResult);
}
}
}