Skip to content
This repository was archived by the owner on Apr 16, 2024. It is now read-only.

Conversation

@torss
Copy link
Collaborator

@torss torss commented Oct 12, 2018

Description

Closes #840

Switches the entire authentication system to use a single JWT stored and transmitted via a cookie.
The cookie is HttpOnly and has SameSite set to 'Strict' to protect against CSRF attacks.

Previously we had two tokens: A primary 'token' and a 'mediaToken', both stored in localStorage. The 'mediaToken' was a relatively recent addition in #807 to secure the static 'uploads' route for images and such. In contrast to a cookie this 'mediaToken' had to be sent via URL query parameter, see the #807 PR for details.

Improvements

  • Reduced XSS attack surface: localStorage tokens could (only) be read via JavaScript. Now the new HttpOnly cookie token can't be accessed via JavaScript at all, it is (re)set via HTTP requests.
  • General simplification of the authentication system: The cookie is sent automatically by the browser, while the localStorage tokens had to be handled via JavaScript.
  • Removal of the 'mediaToken' system: Since the 'mediaToken' system was only implemented due to browser API limitations Bugfix/#729 secure static uploads #807 it was now possible to removed it completely, including the 'JwtPipe'.
  • Stricter 'uploads' route securiy: A user now has to be logged-in to access files of the 'uploads' route, making it impossible to accidentially share/leak a URL with attached 'mediaToken'.

Known Issues

  • The cookie does not have the Secure attribute (i.e. HTTPS-only) set - maybe this should be configurable to implicitly prevent accidental non-HTTP hosting.
  • The stricter 'uploads' route security also implies that it is now impossible for users to quickly share a non-public file URL with people who don't have an account / aren't logged-in. This should probably be solved by providing proper, explicit public URL creation facilities. (This isn't really a new issue because it was only possible to share such URLs due to the lax / non-existent security.)
  • Apparently the chat system is currently broken (independent of this PR), so I couldn't test whether the switch to cookie authentication works.
  • I also haven't been able to fully conduct manual testing for file access because the course media editor seems to be broken right now; possibly related to the broken chat system?

torss added 20 commits October 12, 2018 18:25
This package isn't strictly necessary since a possibly more performant
custom implementation could be written for the intended singular
cookie parsing use case.
Also rectifies the missing 'mediaToken' documentation part
and does some very minor refactoring.
This is now possible because of the JWT-cookie layer.
Through this change the mediaToken system becomes obsolete.
Note that there seems to be some issue with the chat system that
already existed prior to the transition to cookie-based authentication.
Also deactivates extractJwtFromAuthHeaderWithScheme by default,
so that only extractJwtFromCookie is active, and removes the
mediaTokenInsufficient error code.
This should be the last mediaToken remnant on the API-side.
Removes the obsolete localStorage tokens (token & mediaToken) as well as
the obsolete authHeader method and adjusts isLoggedIn accordingly.
Since there still is an old "## [NEXT]" section I added a new one
with an identifier for the next "Release [08.11.2018]".
@torss torss added enhancement This issue improves geli api All Backend related Issues web-frontend All frontend related issues 🔒 security This directly pertains to geli's security! labels Oct 12, 2018
@torss
Copy link
Collaborator Author

torss commented Oct 12, 2018

While this should be complete, please don't merge this to develop quite yet, because we still have to complete release 0.8 first and this PR basically overwrites its predecessor from that time!

# Conflicts:
#	CHANGELOG.md
#	api/package-lock.json
#	api/package.json
# Conflicts:
#	CHANGELOG.md
#	api/package-lock.json
#	api/package.json
@kesselb
Copy link
Contributor

kesselb commented Oct 30, 2018

@torss i merged latest develop and resolved merge conflicts. Could you have another look at @types/cookie dependency? I think (https://stackoverflow.com/questions/45176661/how-do-i-decide-whether-types-goes-into-dependencies-or-devdependencies) it should be save to place it in devDependencies but i'm note sure 😄

@coveralls
Copy link

coveralls commented Oct 30, 2018

Pull Request Test Coverage Report for Build 408

  • 10 of 14 (71.43%) changed or added relevant lines in 3 files are covered.
  • 27 unchanged lines in 3 files lost coverage.
  • Overall coverage decreased (-1.4%) to 72.924%

Changes Missing Coverage Covered Lines Changed/Added Lines %
api/src/Chatserver.ts 0 1 0.0%
api/src/controllers/AuthController.ts 6 9 66.67%
Files with Coverage Reduction New Missed Lines %
api/src/security/passportJwtStrategyFactory.ts 2 81.82%
api/src/controllers/DownloadController.ts 5 74.55%
api/src/models/units/CodeKataUnit.ts 20 58.78%
Totals Coverage Status
Change from base Build 403: -1.4%
Covered Lines: 1715
Relevant Lines: 2243

💛 - Coveralls

@torss
Copy link
Collaborator Author

torss commented Oct 30, 2018

@danielkesselberg Probably yes! At least iirc I had no specific reason not to install that under devDependencies. Could the same thing apply to @types/sharp and @types/socket.io (the only other two @types/[...] installed under dependencies)?

(Also a sidenote re. the cookie package: I've only used it in passportJwtStrategyFactory.ts and it thus shouldn't be hard to remove it completely as a dependency, if desired.)

@kesselb
Copy link
Contributor

kesselb commented Oct 30, 2018

I have no objections to cookie as dependency 👍

Copy link
Contributor

@kesselb kesselb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍 Its pretty common to pass a jwt token as header but you made strong arguments for the cookie approach. I assume you did a lot of research about this topic so i'm fine with it. Big plus we need much less code than before and access to images / videos is much easier (no need for jwtpipe anymore 🎉)

@torss
Copy link
Collaborator Author

torss commented Oct 31, 2018

@danielkesselberg Well, I don't know if I would call it "a lot" of research, but hopefully it was enough. xD
Regarding the @types/[...] in dependencies vs. devDependencies I see you have already changed / fixed that for @types/cookie, but - to reiterate my question above - what about @types/sharp and @types/socket.io under dependencies? Does someone know whether they too can be moved to devDependencies? (I assume so, but maybe I'm missing something.)

@kesselb
Copy link
Contributor

kesselb commented Oct 31, 2018

https://stackoverflow.com/questions/45176661/how-do-i-decide-whether-types-goes-into-dependencies-or-devdependencies

I guess @types/sharp and @types/socket.io belongs to devDependencies as well. But this is another story.

…840-jwt-cookie-auth

# Conflicts:
#	CHANGELOG.md
#	api/package.json
@dboschm dboschm merged commit bbd985f into develop Nov 1, 2018
@dboschm dboschm deleted the feature/#840-jwt-cookie-auth branch November 1, 2018 11:46
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

api All Backend related Issues enhancement This issue improves geli 🔒 security This directly pertains to geli's security! web-frontend All frontend related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants