Add ability to get unencoded string
robjbrain opened this issue · 0 comments
I recently ran into a strange problem with the Google OAuth and this package.
For some unknown reason having +
replaced with %2B
in a redirect to a Google OAuth URL results in an error where the scopes query parameter is not properly picked up.
So this will work:
https://accounts.google.com/o/oauth2/auth?client_id=xxx.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fdomain.net%2Fauth%2Fsocial%2Freturn%2Fgoogle&scope=openid+profile+email&response_type=code&state=xieUxnLmQv9YzBdv9dd2d1GPxvlNFWzghluO8b1G
but this does not
https://accounts.google.com/o/oauth2/auth?client_id=xxx.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fdomain.net%2Fauth%2Fsocial%2Freturn%2Fgoogle&scope=openid%2Bprofile%2Bemail&response_type=code&state=xieUxnLmQv9YzBdv9dd2d1GPxvlNFWzghluO8b1G
Note the only change is from &scope=openid+profile+email
to &scope=openid%2Bprofile%2Bemail
Undoubtedly this an issue Google should fix rather than Spatie. However it does seem it would be preferable to have the option to get an unencoded string both for edge cases like this and it would probably be preferable to display the unencoded version when displaying a URL to a user on a page.
I would like to propose the following changes and am posting it as an issue first incase it needs further discussion but will happily do a pull request.
QueryParameterBag.php
From
public function __toString()
{
$keyValuePairs = Arr::map($this->parameters, function ($value, $key) {
return "{$key}=".rawurlencode($value);
});
return implode('&', $keyValuePairs);
}
public function __toString()
{
return $this->getString(true);
}
public function getString(bool $encoded = true)
{
$keyValuePairs = Arr::map($this->parameters, function ($value, $key) use ($encoded) {
return "{$key}=".($encoded ? rawurlencode($value) : $value);
});
return implode('&', $keyValuePairs);
}
And in Url.php
public function __toString()
{
return $this->getString(true);
}
public function getString(bool $encoded = true)
{
{
$url = '';
if ($this->getScheme() !== '' && $this->getScheme() != 'mailto') {
$url .= $this->getScheme().'://';
}
if ($this->getScheme() === 'mailto' && $this->getPath() !== '') {
$url .= $this->getScheme().':';
}
if ($this->getScheme() === '' && $this->getAuthority() !== '') {
$url .= '//';
}
if ($this->getAuthority() !== '') {
$url .= $this->getAuthority();
}
if ($this->getPath() !== '/') {
$url .= $this->getPath();
}
if ($this->getQuery() !== '') {
$url .= '?'.$this->query->getString($encoded);
}
if ($this->getFragment() !== '') {
$url .= '#'.$this->getFragment();
}
return $url;
}
For the sake of other searchers this is the error message that lead me to this:
Authorization Error
Error 400: invalid_scope
Some requested scopes were invalid. {invalid=[openid+profile+email]}