Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MB-2321 Allow revoking individual user sessions
**Description**: In order to obtain an ATO (Authority to Operate) for MilMove, we need to provide a way to revoke individual user sessions. Currently, session management is provided by JWTs per ADR 15, but JWTs aren't designed to be revoked on an individual basis. Instead, we need to store session data on the server. In this PR, we have chosen Redis because it automatically deletes expired sessions. With Postgres, we would need to run a routine periodically to clean up stale sessions. After researching various session management solutions, I chose `scs` because it was the easiest to integrate, and it supports various stores out of the box. It is the second most popular repo after `gorilla/sessions`. I didn't pick `gorilla/sessions` because it suffers from memory leak issues, and uses its own `context` instead of the `request.Context()` provided by Golang. The maintainers are aware of the issues and have opened a GitHub issue to propose improvements for v2. However, it doesn't look like any progress has been made over the past 2 years, while `scs` has implemented most of those improvements. The name of the Redis key that holds the session data is based on the format `scs:session:token`, where `token` is the session cookie value. In order to revoke an individual session, we need to know the token corresponding to the user's session. To facilitate that lookup, I added a new `session-id` to the RequestLogger. **Setup**: `docker pull redis` **Reviewer Notes**: Things to test: **milmovelocal auth** 1. Go to milmovelocal:3000 - [ ] Verify that a session cookie named "mil_session_token" is present (Developer Tools -> Application tab -> Cookies (under Storage in the left sidebar)) - [ ] Verify that the value in the `Expires/Max-Age` column is `Session` - [ ] Verify that the HttpOnly column is checked - [ ] Verify that the Path is `/` - [ ] Verify that `SameSite` is `Lax` 2. In your Terminal, run `redis-cli`, then type `KEYS *` - [ ] Verify there is an entry labeled `scs:session:token`, where `token` is the `Value` of the `mil_session_token` cookie 3. Sign in - [ ] Verify that after successful sign in, the `Value` of the `mil_session_token` cookie changes 4. Run `KEYS *` again in the Redis console - [ ] Verify that the previous entry is gone and that a new one corresponding to the new session cookie is present - [ ] Verify that there is a `session-id` entry in the `middleware/request_logger.go` output that is the same value as the current browser cookie, not the previous one before the user signed in 5. Sign out - [ ] Verify that the previous entry in Redis is gone and that a new one corresponding to the new session cookie is present - [ ] Verify that the session cookie changed in the browser 6. In `serve.go`, on line 504, change the IdleTimeout from 15 minutes to 1 minute 7. Sign in, then wait a little over a minute 8. Try to make a new request without refreshing the browser, for example, filling out the moves form and clicking the Next button - [ ] Verify that you are not able to make a request and that you see an Unauthorized Error. Ideally, the user would be redirected to the sign in page. I'm working on implementing that. **devlocal auth** - [ ] Verify you can sign in and out via devlocal auth flow: http://milmovelocal:3000/devlocal-auth/login - [ ] Verify you can create a New milmove User - [ ] Verify you can create a New dps User **Role based auth** 1. In your `.envrc.local`, add `export FEATURE_FLAG_ROLE_BASED_AUTH=true` 2. Stop the server, run `direnv allow` 3. run `echo $FEATURE_FLAG_ROLE_BASED_AUTH` to make sure it's `true` 4. run `make server_run` 5. Go to milmovelocal:3000 and make sure you can sign in and out **References**: [gorilla sessions issues](gorilla/sessions#105) [scs repo](https://github.com/alexedwards/scs)
- Loading branch information