BortalServerAuthModule.java
5.59 KB
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package fi.insomnia.bortal;
import java.io.IOException;
import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.message.AuthException;
import javax.security.auth.message.AuthStatus;
import javax.security.auth.message.MessageInfo;
import javax.security.auth.message.MessagePolicy;
import javax.security.auth.message.callback.CallerPrincipalCallback;
import javax.security.auth.message.callback.GroupPrincipalCallback;
import javax.security.auth.message.callback.PasswordValidationCallback;
import javax.security.auth.message.module.ServerAuthModule;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sun.jersey.core.util.Base64;
public class BortalServerAuthModule implements ServerAuthModule {
protected static final Class<?>[] supportedMessageTypes =
new Class[] {
HttpServletRequest.class,
HttpServletResponse.class
};
private MessagePolicy requestPolicy;
private MessagePolicy responsePolicy;
private CallbackHandler handler;
private Map<?, ?> options;
private String realmName = null;
private String defaultGroup[] = null;
private static final String REALM_PROPERTY_NAME = "realm.name";
private static final String GROUP_PROPERTY_NAME = "group.name";
private static final String BASIC = "Basic";
static final String AUTHORIZATION_HEADER = "authorization";
static final String AUTHENTICATION_HEADER = "WWW-Authenticate";
private static void log(String str) {
System.out.println(str);
}
public void initialize(MessagePolicy reqPolicy, MessagePolicy resPolicy,
CallbackHandler cBH, Map opts)
throws AuthException {
requestPolicy = reqPolicy;
responsePolicy = resPolicy;
handler = cBH;
options = opts;
if (options != null) {
realmName = (String) options.get(REALM_PROPERTY_NAME);
if (options.containsKey(GROUP_PROPERTY_NAME)) {
defaultGroup = new String[] { (String)
options.get(GROUP_PROPERTY_NAME) };
}
}
}
public Class<?>[] getSupportedMessageTypes() {
return supportedMessageTypes;
}
public AuthStatus validateRequest(MessageInfo msgInfo, Subject client, Subject server) throws AuthException {
try {
String username = processAuthorizationToken(msgInfo, client);
log("req pol mand: " + requestPolicy.isMandatory());
if (username == null && requestPolicy.isMandatory()) {
return sendAuthenticateChallenge(msgInfo);
}
setAuthenticationResult(username, client, msgInfo);
return AuthStatus.SUCCESS;
} catch (Exception e) {
AuthException ae = new AuthException();
ae.initCause(e);
throw ae;
}
}
private String processAuthorizationToken(MessageInfo msgInfo, Subject s) throws AuthException {
HttpServletRequest request = (HttpServletRequest) msgInfo.getRequestMessage();
String token = request.getHeader(AUTHORIZATION_HEADER);
log("Processing authentication: " + token);
if (token != null && token.startsWith(BASIC + " ")) {
token = token.substring(6).trim();
// Decode and parse the authorization token
String decoded = new String(Base64.decode(token.getBytes()));
int colon = decoded.indexOf(':');
if (colon <= 0 || colon == decoded.length() - 1) {
return (null);
}
String username = decoded.substring(0, colon);
log("Logging in as :" + username);
// use the callback to ask the container to
// validate the password
PasswordValidationCallback pVC = new PasswordValidationCallback(s, username,
decoded.substring(colon + 1).toCharArray());
try {
handler.handle(new Callback[] { pVC });
pVC.clearPassword();
} catch (Exception e) {
AuthException ae = new AuthException();
ae.initCause(e);
throw ae;
}
if (pVC.getResult()) {
return username;
}
}
return null;
}
private AuthStatus sendAuthenticateChallenge(MessageInfo msgInfo) {
log("Sending authenticate challenge!!!");
String realm = realmName;
// if the realm property is set use it,
// otherwise use the name of the server
// as the realm name.
if (realm == null) {
HttpServletRequest request = (HttpServletRequest) msgInfo.getRequestMessage();
realm = request.getServerName();
}
HttpServletResponse response = (HttpServletResponse) msgInfo.getResponseMessage();
String header = BASIC + " realm=\"" + realm + "\"";
response.setHeader(AUTHENTICATION_HEADER, header);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return AuthStatus.SEND_CONTINUE;
}
public AuthStatus secureResponse(MessageInfo msgInfo, Subject service) throws AuthException {
log("Resp mand: " + responsePolicy.isMandatory());
if (responsePolicy.isMandatory()) {
return sendAuthenticateChallenge(msgInfo);
}
return AuthStatus.SEND_SUCCESS;
}
public void cleanSubject(MessageInfo msgInfo, Subject subject) throws AuthException {
if (subject != null) {
subject.getPrincipals().clear();
}
}
private static final String AUTH_TYPE_INFO_KEY = "javax.servlet.http.authType";
// distinguish the caller principal
// and assign default groups
private void setAuthenticationResult(String name, Subject s, MessageInfo m) throws IOException, UnsupportedCallbackException {
handler.handle(new Callback[] { new CallerPrincipalCallback(s, name) });
if (name != null) {
// add the default group if the property is set
if (defaultGroup != null) {
handler.handle(new Callback[] { new GroupPrincipalCallback(s, defaultGroup) });
}
m.getMap().put(AUTH_TYPE_INFO_KEY, "BortalSAM");
}
}
}