-
Notifications
You must be signed in to change notification settings - Fork 150
Encode user info when calling withUserInfo() #248
Encode user info when calling withUserInfo() #248
Conversation
if ($password) { | ||
$info .= ':' . $password; | ||
$info .= ':' . $this->filterUserInfoPart($password); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This patch will fix most cases, however, if the password contains an apparently url encoded string literal, for example, "%3A" that will be decoded as ":" and therefore fail authentication. In discussion with @DASPRiD, fixing this would be a BC break.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On second thought, maybe we can change this to a BC compatible solution by not using self::CHAR_UNRESERVED
and self::CHAR_SUB_DELIMS
for user info. Instead, we can/should/must assume that input is already urlencoded if it comes from the uri string, and can/should/must assume it's not if it is set via withUserInfo
method.
$info = urlencode($user);
if ($password) {
$info .= ':' . urlencode($password);
}
Now, if that would be considered bc breaking, we could add a third optional arg to withUserInfo
. E.g.
public function withUserInfo($user, $password = null, $urlEncoded = true)
{
// snip
But I'd argue that if someone is already urlencoding this input, they're working around the bug, and we shouldn't worry about BC, and/or we just accept it as BC breaking, and increase the version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In discussion with @DASPRiD we realized that since the PSR-7 interface doesn't include the third argument, that suggests we shouldn't add it in Diactoros, even though PSR-7 does not specify if the input should be url encoded or not.
Also, @DASPRiD argues that using the core PHP urlencode is overkill because it encodes too many characters, but agrees that always encoding for the user info inputs is correct since it would be a pretty normal case for a password to contain a character combination that looks like an encoded character, but is in fact a string literal.
We agree that it's okay to always assume that a character combination that looks url encoded in the path component should not be re-encoded. That is, the way it functions already is fine for the path. The userInfo case is special.
test/UriTest.php
Outdated
$new = $uri->withUserInfo('foo:bar', 'baz:bat'); | ||
|
||
$this->assertSame('foo%3Abar:baz%3Abat', $new->getUserInfo()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably either a second assertion, or add %25
to the first input to cover that it's not getting accepted as urlencoded input.
public function testWithUserInfoDoesNotExpectUrlencodedCharactersInUsernameAndPassword()
{
$uri = new Uri('https://localhost');
$new = $uri->withUserInfo('%25', '%25');
$this->assertSame('%2525:%2525', $new->getUserInfo());
}
I've created a new commit that adds a data provider with both user and credential values to test against, as well as the expected value of The one issue I see with this is that it can lead to issues if you use the value retrieved from Interestingly, @akrabat ran into this issue this week as well, when using an email address as the user information (e.g., My suggestion is that any encoding is done when calling In reviewing the code, I also see that the To be honest, @akrabat @DASPRiD and @jeremiahsmall : Do my suggestions here make sense? |
The new data provider in the test looks good. Not sure what to make of the suggestion about encoding when calling |
I'm going to move this to the 1.5.0 milestone, so we can also address the other issues related to The only "con" I can see is that doing so puts the onus on the user to encode if they wish to use those values as part of a URI string). I think we can message that in the docblocks, however. |
So are we still saying that the arguments in
vs
|
If they're not encoded, why would we indicate they're encoded in the variable name? |
Right, well I guess that answers my question... I was making sure that you're not suggesting that these be encoded. |
Okay, re-read the specification, and this is not possible. Each of the docblocks for What this means, though, is that we need to ensure that the |
Allows testing common combinations of characters that may occur in both user and credential strings to ensure they are encoded properly.
Adds `%` to the initial character exclusion set in order to allow the latter `%(?!...)` pattern to match correctly, and thus prevent double-encoding of values.
@jeremiahsmall I've isolated the double-encoding issue, and have now pushed a test that verifies that calling |
Thanks, @DASPRiD and @jeremiahsmall |
+1 |
According to https://www.ietf.org/rfc/rfc3986.txt 3.2.1, the user info parts should actually be URL encoded.