Problem/Motivation
Follow-up from #2238087: Rebase SessionManager onto Symfony NativeSessionStorage and #2245003: Use a random seed instead of the session_id for CSRF token generation.
Symfony provides a Session object that has a mechanism for handling data that would typically be stored in the $_SESSION super global variable. This mechanism is found in Symfony\Component\HttpFoundation\Session\Storage\MetadataBag . Using MetadataBag instead of the super global variable is recommended. Instead of having globally scoped variables (that make it difficult to use UnitTests to test functionality) we can have properly scoped variables.
This patch moves logic that involves handling Session variable storage to the Metadata object from the SessionManager.
In SessionManager
in regenerate() and isSessionObsolete()
two todos: .... the token seed
// can be moved onto Drupal\Core\Session\MetadataBag. The session manager
// then needs to notify the metadata bag when the token should be
// regenerated.
Proposed resolution
Move the token seed to the MetadataBag.
Remaining tasks
User interface changes
No.
API changes
?
| Comment | File | Size | Author |
|---|---|---|---|
| #23 | 2256257-move-token-seed-to-metadata-bag-23.diff | 15.01 KB | znerol |
| #23 | interdiff.txt | 429 bytes | znerol |
| #19 | interdiff_19.txt | 1.18 KB | cosmicdreams |
| #19 | 2256257_19.patch | 14.89 KB | cosmicdreams |
| #18 | interdiff.txt | 628 bytes | znerol |
Comments
Comment #1
znerol commentedComment #3
cosmicdreams commentedComment #4
znerol commented#2265789: Add an interface for CsrfTokenGenerator should help with the installer.
Comment #5
znerol commentedInstead of mocking
CsrfTokenGenerator(the initial goal of the issue referenced in#4), it also would be possible to fix the installer/update script with #2272987: Do not persist session manager.Comment #6
znerol commentedActive again after #2272987: Do not persist session manager. Now that
CsrfTokenGeneratorstops accessing$_SESSIONdirectly, code trying to use tokens for anonymous users really needs to make sure that there is a session before attempting to generate a token.Comment #7
znerol commentedReroll.
Comment #8
andypostRTBC except nits
s/Database/database
string|null
when no seed stored
Comment #9
znerol commentedThanks.
Comment #10
andypostnice
Comment #11
neclimdulWhy are we going through all this trouble to mock the object? Can't we just use an instantiated version of the object?
Comment #12
neclimdulNM, its because settings isn't test friendly. Opened #2329817: Add a Settings storage object
Comment #15
neclimdulI guess the retest passed? Going to move this back to RTBC.
Comment #16
cosmicdreams commentedpatch applies +!
Please update Docblock
Extra needless whitespace
if this proves to be important we should consider contributing this work back to Symfony
Comment #17
Crell commentedEr. How is a hard-coded token seed that cannot vary site to site in any way secure?
Assuming the constant is kept, there's extremely few reasons to use self:: anymore. Use static:: instead, by default.
Comment #18
znerol commented#16.1: done, thanks, #16.2: This is by intention. It is the single newline separating the last method from the closing brace of the class.
#16.3 Symfony has
Symfony\Component\Security\Csrfwhich provides anything anyone ever could wish including aSessionStorageclass. Because we do not have theSessionobject yet in Drupal we cannot just switch to those classes. We might want to revisit that later but at the moment the top priority for me is to advance the conversion of the session component. This patch is important especially because of the changes in the batch-system.Comment #19
cosmicdreams commented@Crell
17.1: Look closer, const CSRF_TOKEN_SEED isn't the seed, it's the array key. The value is created elsewhere and presumeably is random enough. Do we need the array key to be randomized as well?
Here's the change from self:: to static::
Comment #20
neclimdulI spent a good bit of time looking into this code too. It confused me at first but cosmicdreams nailed it.
Other concerns had and my internal resolution.
Comment #21
cosmicdreams commented@neclimdul so RTBC? (I can no longer mark it as RTBC myself)
Comment #22
dawehnerThis issue is a good step forward.
Can't we put that logic into the getCsrfTokenSeed method? So generate it on the fly? But yeah I see the point that the csrf token generator should handle the creation of csrf token seeds
Maybe we could document this and tell us, why we use 's' and not 'c' for exmaple
Comment #23
znerol commented#22.1: We cannot generate the seed in
MetadataBag::getCsrfTokenSeed(). Otherwise we'd forcibly open a session even when only callingCsrfTokenGenerator::validate()for anonymous users.#22.2: Added documentation for the token-seed. The reason we cannot use
'c'is that this is already taken by the parent SymfonyMetadataBagfor the creation time.Comment #24
cosmicdreams commentedYep that looks good to go.
Comment #25
alexpottThis looks really good. One small nit:
Let's typehint on the interface SessionBagInterface
Comment #26
neclimdulThat would be incorrect.
The only reference in the constructor is
and the parent sig is:
Comment #27
neclimdulMore information, those signatures a misleading as they're different bags. Our sig is our MetadataBag and the parent is Symfony's bag. We internally require methods specifically on our MetadataBag though. Specifically the CsrfToken Methods currently. Only matching the interface would not require this.
Comment #28
alexpottDiscussed with @neclimdul on IRC - I pointed out our metadata bag is service and therefore swappable which means that we perhaps we should be using an interface here - but we agreed that in reality you could just extend from
\Drupal\Core\Session\MetadataBagCommitted 0a12d85 and pushed to 8.0.x. Thanks!