( userId: string, redirectTo: string, )
| 166 | } |
| 167 | |
| 168 | export async function createUserSession( |
| 169 | userId: string, |
| 170 | redirectTo: string, |
| 171 | ): Promise<Response> { |
| 172 | const [csrf, csrfSignature] = await generateCsrf() |
| 173 | const headers = new Headers() |
| 174 | const expires = new Date(new Date().getTime() + sessionMaxAgeSeconds * 1000) |
| 175 | const cookie = await sessionCM.serialize( |
| 176 | new SignJWT({}) |
| 177 | .setSubject(userId) |
| 178 | // use 256-bit csrf as JTI https://www.rfc-editor.org/rfc/rfc7519#section-4.1.7 https://security.stackexchange.com/a/220810 https://security.stackexchange.com/a/248434 |
| 179 | .setJti(csrf) |
| 180 | // .setNotBefore() // highTODO |
| 181 | // .setIssuedAt() |
| 182 | // .setIssuer("urn:example:issuer") |
| 183 | // .setAudience("urn:example:audience") |
| 184 | .setExpirationTime(expires), |
| 185 | env().hubSessionSecret, |
| 186 | ) |
| 187 | headers.append('Set-Cookie', cookie) |
| 188 | // https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#double-submit-cookie |
| 189 | // If you ever separate csrf from the session cookie https://security.stackexchange.com/a/220810 https://security.stackexchange.com/a/248434 |
| 190 | // REST endpoints may need csrf https://security.stackexchange.com/q/166724 |
| 191 | headers.append('Set-Cookie', csrfSignatureCM.serialize(csrfSignature)) |
| 192 | headers.append('Set-Cookie', oauthStateCM.clear()) |
| 193 | headers.append('Set-Cookie', oauthCodeVerifierCM.clear()) |
| 194 | return redirect(redirectTo, { |
| 195 | headers, |
| 196 | }) |
| 197 | } |
| 198 | |
| 199 | export async function createLoginHeaders( |
| 200 | oauthState: string, |
no test coverage detected