Mercurial > openid
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 |