-
Notifications
You must be signed in to change notification settings - Fork 15
/
cas_server.js
123 lines (101 loc) · 3.18 KB
/
cas_server.js
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
var Fiber = Npm.require('fibers');
var url = Npm.require('url');
var CAS = Npm.require('cas');
var _casCredentialTokens = {};
RoutePolicy.declare('/_cas/', 'network');
// Listen to incoming OAuth http requests
WebApp.connectHandlers.use(function(req, res, next) {
// Need to create a Fiber since we're using synchronous http calls and nothing
// else is wrapping this in a fiber automatically
Fiber(function () {
middleware(req, res, next);
}).run();
});
middleware = function (req, res, next) {
// Make sure to catch any exceptions because otherwise we'd crash
// the runner
try {
var barePath = req.url.substring(0, req.url.indexOf('?'));
var splitPath = barePath.split('/');
// Any non-cas request will continue down the default
// middlewares.
if (splitPath[1] !== '_cas') {
next();
return;
}
// get auth token
var credentialToken = splitPath[2];
if (!credentialToken) {
closePopup(res);
return;
}
// validate ticket
casTicket(req, credentialToken, function() {
closePopup(res);
});
} catch (err) {
console.log("account-cas: unexpected error : " + err.message);
closePopup(res);
}
};
var casTicket = function (req, token, callback) {
// get configuration
if (!Meteor.settings.cas && !Meteor.settings.cas.validate) {
console.log("accounts-cas: unable to get configuration");
callback();
}
// get ticket and validate.
var parsedUrl = url.parse(req.url, true);
var ticketId = parsedUrl.query.ticket;
var cas = new CAS({
base_url: Meteor.settings.cas.baseUrl,
service: Meteor.absoluteUrl() + "_cas/" + token
});
cas.validate(ticketId, function(err, status, username) {
if (err) {
console.log("accounts-cas: error when trying to validate " + err);
} else {
if (status) {
console.log("accounts-cas: user validated " + username);
_casCredentialTokens[token] = { id: username };
} else {
console.log("accounts-cas: unable to validate " + ticketId);
}
}
callback();
});
return;
};
/*
* Register a server-side login handle.
* It is call after Accounts.callLoginMethod() is call from client.
*
*/
Accounts.registerLoginHandler(function (options) {
if (!options.cas)
return undefined;
if (!_hasCredential(options.cas.credentialToken)) {
throw new Meteor.Error(Accounts.LoginCancelledError.numericError,
'no matching login attempt found');
}
var result = _retrieveCredential(options.cas.credentialToken);
var options = { profile: { name: result.id } };
var user = Accounts.updateOrCreateUserFromExternalService("cas", result, options);
return user;
});
var _hasCredential = function(credentialToken) {
return _.has(_casCredentialTokens, credentialToken);
}
/*
* Retrieve token and delete it to avoid replaying it.
*/
var _retrieveCredential = function(credentialToken) {
var result = _casCredentialTokens[credentialToken];
delete _casCredentialTokens[credentialToken];
return result;
}
var closePopup = function(res) {
res.writeHead(200, {'Content-Type': 'text/html'});
var content = '<html><body><div id="popupCanBeClosed"></div></body></html>';
res.end(content, 'utf-8');
}