comparison src/ur/openidUser.ur @ 46:72e942423f26

Based on a security suggestion by Robin Green, start a new session after authentication at an OP and after submission of a signup form
author Adam Chlipala <adam@chlipala.net>
date Sun, 03 Jul 2011 17:52:29 -0400
parents c39c3f63854a
children 9c83592de908 328a429dfedb
comparison
equal deleted inserted replaced
45:c39c3f63854a 46:72e942423f26
118 fun main wrap = 118 fun main wrap =
119 let 119 let
120 fun logout () = 120 fun logout () =
121 clearCookie auth; 121 clearCookie auth;
122 redirect M.afterLogout 122 redirect M.afterLogout
123
124 fun newSession identO =
125 ses <- nextval sessionIds;
126 now <- now;
127 key <- rand;
128 dml (INSERT INTO session (Id, Key, Identifier, Expires)
129 VALUES ({[ses]}, {[key]}, {[identO]}, {[addSeconds now M.sessionLifetime]}));
130 return {Session = ses, Key = key}
123 131
124 fun signupDetails after = 132 fun signupDetails after =
125 let 133 let
126 fun finishSignup uid data = 134 fun finishSignup uid data =
127 if not (validUser uid) then 135 if not (validUser uid) then
148 | Some (Some ident) => 156 | Some (Some ident) =>
149 cols <- M.choose user data; 157 cols <- M.choose user data;
150 case cols of 158 case cols of
151 Failure s => return (Some s) 159 Failure s => return (Some s)
152 | Success cols => 160 | Success cols =>
161 dml (DELETE FROM session
162 WHERE Id = {[ses.Session]});
163 ses <- newSession (Some ident);
153 setCookie auth {Value = LoggedIn ({User = uid} ++ ses), 164 setCookie auth {Value = LoggedIn ({User = uid} ++ ses),
154 Expires = None, 165 Expires = None,
155 Secure = M.secureCookies}; 166 Secure = M.secureCookies};
156 167
157 dml (insert user ({Id = (SQL {[uid]})} ++ @Sql.sqexps M.folder M.inj cols)); 168 dml (insert user ({Id = (SQL {[uid]})} ++ @Sql.sqexps M.folder M.inj cols));
197 WHERE session.Id = {[signup.Session]} 208 WHERE session.Id = {[signup.Session]}
198 AND session.Key = {[signup.Key]}); 209 AND session.Key = {[signup.Key]});
199 if invalid then 210 if invalid then
200 error <xml>Invalid or expired session</xml> 211 error <xml>Invalid or expired session</xml>
201 else 212 else
202 dml (UPDATE session 213 dml (DELETE FROM session
203 SET Identifier = {[Some ident]}
204 WHERE Id = {[signup.Session]}); 214 WHERE Id = {[signup.Session]});
215 ses <- newSession (Some ident);
216 setCookie auth {Value = SigningUp ses,
217 Expires = None,
218 Secure = M.secureCookies};
205 signupDetails after 219 signupDetails after
206 | Some (LoggedIn login) => 220 | Some (LoggedIn login) =>
207 if login.Session <> ses then 221 if login.Session <> ses then
208 error <xml>Session has changed suspiciously</xml> 222 error <xml>Session has changed suspiciously</xml>
209 else 223 else
212 WHERE session.Id = {[login.Session]} 226 WHERE session.Id = {[login.Session]}
213 AND session.Key = {[login.Key]}); 227 AND session.Key = {[login.Key]});
214 if invalid then 228 if invalid then
215 error <xml>Invalid or expired session</xml> 229 error <xml>Invalid or expired session</xml>
216 else 230 else
217 dml (UPDATE session 231 dml (DELETE FROM session
218 SET Identifier = {[Some ident]}
219 WHERE Id = {[login.Session]}); 232 WHERE Id = {[login.Session]});
233 ses <- newSession (Some ident);
234 setCookie auth {Value = LoggedIn ({User = login.User} ++ ses),
235 Expires = None,
236 Secure = M.secureCookies};
220 redirect (bless after) 237 redirect (bless after)
221 | None => error <xml>Missing session cookie</xml> 238 | None => error <xml>Missing session cookie</xml>
222 239
223 fun fakeCallback ident after ses = 240 fun fakeCallback ident after ses =
224 av <- getCookie auth; 241 av <- getCookie auth;
247 SET Identifier = {[Some ident]} 264 SET Identifier = {[Some ident]}
248 WHERE Id = {[login.Session]}); 265 WHERE Id = {[login.Session]});
249 redirect (bless after) 266 redirect (bless after)
250 | None => error <xml>Missing session cookie</xml> 267 | None => error <xml>Missing session cookie</xml>
251 268
252 fun newSession () =
253 ses <- nextval sessionIds;
254 now <- now;
255 key <- rand;
256 dml (INSERT INTO session (Id, Key, Identifier, Expires)
257 VALUES ({[ses]}, {[key]}, NULL, {[addSeconds now M.sessionLifetime]}));
258 return {Session = ses, Key = key}
259
260 fun logon after r = 269 fun logon after r =
261 ident <- oneOrNoRowsE1 (SELECT (identity.Identifier) 270 ident <- oneOrNoRowsE1 (SELECT (identity.Identifier)
262 FROM identity 271 FROM identity
263 WHERE identity.User = {[r.User]} 272 WHERE identity.User = {[r.User]}
264 LIMIT 1); 273 LIMIT 1);
265 case ident of 274 case ident of
266 None => error <xml>Username not found</xml> 275 None => error <xml>Username not found</xml>
267 | Some ident => 276 | Some ident =>
268 ses <- newSession (); 277 ses <- newSession None;
269 setCookie auth {Value = LoggedIn (r ++ ses), 278 setCookie auth {Value = LoggedIn (r ++ ses),
270 Expires = None, 279 Expires = None,
271 Secure = M.secureCookies}; 280 Secure = M.secureCookies};
272 ses <- return ses.Session; 281 ses <- return ses.Session;
273 if M.fakeId = Some ident then 282 if M.fakeId = Some ident then
278 Realm = M.realm, 287 Realm = M.realm,
279 Identifier = Openid.KnownIdentifier ident}; 288 Identifier = Openid.KnownIdentifier ident};
280 error <xml>Login with your identity provider failed: {[msg]}</xml> 289 error <xml>Login with your identity provider failed: {[msg]}</xml>
281 290
282 fun doSignup after r = 291 fun doSignup after r =
283 ses <- newSession (); 292 ses <- newSession None;
284 setCookie auth {Value = SigningUp ses, 293 setCookie auth {Value = SigningUp ses,
285 Expires = None, 294 Expires = None,
286 Secure = M.secureCookies}; 295 Secure = M.secureCookies};
287 ses <- return ses.Session; 296 ses <- return ses.Session;
288 if M.fakeId = Some r.Identifier then 297 if M.fakeId = Some r.Identifier then