mirror of
https://github.com/pixelfed/pixelfed.git
synced 2025-01-09 13:50:44 +00:00
Fix oauth oob (urn:ietf:wg:oauth:2.0:oob) support. Fixes #2522
This commit is contained in:
parent
8c39ef449a
commit
8afbdb03a8
3 changed files with 187 additions and 0 deletions
99
app/Http/Controllers/OAuth/OobAuthorizationController.php
Normal file
99
app/Http/Controllers/OAuth/OobAuthorizationController.php
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\OAuth;
|
||||||
|
|
||||||
|
use Laravel\Passport\Http\Controllers\ApproveAuthorizationController;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||||
|
use Nyholm\Psr7\Response as Psr7Response;
|
||||||
|
|
||||||
|
class OobAuthorizationController extends ApproveAuthorizationController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Approve the authorization request.
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function approve(Request $request)
|
||||||
|
{
|
||||||
|
$this->assertValidAuthToken($request);
|
||||||
|
|
||||||
|
$authRequest = $this->getAuthRequestFromSession($request);
|
||||||
|
$authRequest->setAuthorizationApproved(true);
|
||||||
|
|
||||||
|
return $this->withErrorHandling(function () use ($authRequest) {
|
||||||
|
$response = $this->server->completeAuthorizationRequest($authRequest, new Psr7Response);
|
||||||
|
|
||||||
|
if ($this->isOutOfBandRequest($authRequest)) {
|
||||||
|
$code = $this->extractAuthorizationCode($response);
|
||||||
|
return response()->json([
|
||||||
|
'code' => $code,
|
||||||
|
'state' => $authRequest->getState()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->convertResponse($response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the request is an out-of-band OAuth request.
|
||||||
|
*
|
||||||
|
* @param \League\OAuth2\Server\RequestTypes\AuthorizationRequest $authRequest
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isOutOfBandRequest($authRequest)
|
||||||
|
{
|
||||||
|
return $authRequest->getRedirectUri() === 'urn:ietf:wg:oauth:2.0:oob';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the authorization code from the PSR-7 response.
|
||||||
|
*
|
||||||
|
* @param \Psr\Http\Message\ResponseInterface $response
|
||||||
|
* @return string
|
||||||
|
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||||
|
*/
|
||||||
|
protected function extractAuthorizationCode($response)
|
||||||
|
{
|
||||||
|
$location = $response->getHeader('Location')[0] ?? '';
|
||||||
|
|
||||||
|
if (empty($location)) {
|
||||||
|
throw OAuthServerException::serverError('Missing authorization code in response');
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_str(parse_url($location, PHP_URL_QUERY), $params);
|
||||||
|
|
||||||
|
if (!isset($params['code'])) {
|
||||||
|
throw OAuthServerException::serverError('Invalid authorization code format');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $params['code'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle OAuth errors for both redirect and OOB flows.
|
||||||
|
*
|
||||||
|
* @param \Closure $callback
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
protected function withErrorHandling($callback)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return $callback();
|
||||||
|
} catch (OAuthServerException $e) {
|
||||||
|
if ($this->isOutOfBandRequest($this->getAuthRequestFromSession(request()))) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => $e->getErrorType(),
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
'hint' => $e->getHint()
|
||||||
|
], $e->getHttpStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->convertResponse(
|
||||||
|
$e->generateHttpResponse(new Psr7Response)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ class AuthServiceProvider extends ServiceProvider
|
||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
if(config('pixelfed.oauth_enabled') == true) {
|
if(config('pixelfed.oauth_enabled') == true) {
|
||||||
|
Passport::ignoreRoutes();
|
||||||
Passport::tokensExpireIn(now()->addDays(config('instance.oauth.token_expiration', 356)));
|
Passport::tokensExpireIn(now()->addDays(config('instance.oauth.token_expiration', 356)));
|
||||||
Passport::refreshTokensExpireIn(now()->addDays(config('instance.oauth.refresh_expiration', 400)));
|
Passport::refreshTokensExpireIn(now()->addDays(config('instance.oauth.refresh_expiration', 400)));
|
||||||
Passport::enableImplicitGrant();
|
Passport::enableImplicitGrant();
|
||||||
|
|
|
@ -45,6 +45,93 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
||||||
Route::get('auth/forgot/email', 'UserEmailForgotController@index')->name('email.forgot');
|
Route::get('auth/forgot/email', 'UserEmailForgotController@index')->name('email.forgot');
|
||||||
Route::post('auth/forgot/email', 'UserEmailForgotController@store')->middleware('throttle:10,900,forgotEmail');
|
Route::post('auth/forgot/email', 'UserEmailForgotController@store')->middleware('throttle:10,900,forgotEmail');
|
||||||
|
|
||||||
|
Route::group([
|
||||||
|
'as' => 'passport.',
|
||||||
|
'prefix' => config('passport.path', 'oauth'),
|
||||||
|
], function () {
|
||||||
|
Route::post('/token', [
|
||||||
|
'uses' => '\Laravel\Passport\Http\Controllers\AccessTokenController@issueToken',
|
||||||
|
'as' => 'token',
|
||||||
|
'middleware' => 'throttle',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Route::get('/authorize', [
|
||||||
|
'uses' => '\Laravel\Passport\Http\Controllers\AuthorizationController@authorize',
|
||||||
|
'as' => 'authorizations.authorize',
|
||||||
|
'middleware' => 'web',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$guard = config('passport.guard', null);
|
||||||
|
|
||||||
|
Route::middleware(['web', $guard ? 'auth:'.$guard : 'auth'])->group(function () {
|
||||||
|
Route::post('/token/refresh', [
|
||||||
|
'uses' => '\Laravel\Passport\Http\Controllers\TransientTokenController@refresh',
|
||||||
|
'as' => 'token.refresh',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Route::post('/authorize', [
|
||||||
|
'uses' => '\App\Http\Controllers\OAuth\OobAuthorizationController@approve',
|
||||||
|
'as' => 'authorizations.approve',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Route::delete('/authorize', [
|
||||||
|
'uses' => '\Laravel\Passport\Http\Controllers\DenyAuthorizationController@deny',
|
||||||
|
'as' => 'authorizations.deny',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Route::get('/tokens', [
|
||||||
|
'uses' => '\Laravel\Passport\Http\Controllers\AuthorizedAccessTokenController@forUser',
|
||||||
|
'as' => 'tokens.index',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Route::delete('/tokens/{token_id}', [
|
||||||
|
'uses' => '\Laravel\Passport\Http\Controllers\AuthorizedAccessTokenController@destroy',
|
||||||
|
'as' => 'tokens.destroy',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Route::get('/clients', [
|
||||||
|
'uses' => '\Laravel\Passport\Http\Controllers\ClientController@forUser',
|
||||||
|
'as' => 'clients.index',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Route::post('/clients', [
|
||||||
|
'uses' => '\Laravel\Passport\Http\Controllers\ClientController@store',
|
||||||
|
'as' => 'clients.store',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Route::put('/clients/{client_id}', [
|
||||||
|
'uses' => '\Laravel\Passport\Http\Controllers\ClientController@update',
|
||||||
|
'as' => 'clients.update',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Route::delete('/clients/{client_id}', [
|
||||||
|
'uses' => '\Laravel\Passport\Http\Controllers\ClientController@destroy',
|
||||||
|
'as' => 'clients.destroy',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Route::get('/scopes', [
|
||||||
|
'uses' => '\Laravel\Passport\Http\Controllers\ScopeController@all',
|
||||||
|
'as' => 'scopes.index',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Route::get('/personal-access-tokens', [
|
||||||
|
'uses' => '\Laravel\Passport\Http\Controllers\PersonalAccessTokenController@forUser',
|
||||||
|
'as' => 'personal.tokens.index',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Route::post('/personal-access-tokens', [
|
||||||
|
'uses' => '\Laravel\Passport\Http\Controllers\PersonalAccessTokenController@store',
|
||||||
|
'as' => 'personal.tokens.store',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Route::delete('/personal-access-tokens/{token_id}', [
|
||||||
|
'uses' => '\Laravel\Passport\Http\Controllers\PersonalAccessTokenController@destroy',
|
||||||
|
'as' => 'personal.tokens.destroy',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
Route::get('discover', 'DiscoverController@home')->name('discover');
|
Route::get('discover', 'DiscoverController@home')->name('discover');
|
||||||
|
|
||||||
Route::get('discover/tags/{hashtag}', 'DiscoverController@showTags');
|
Route::get('discover/tags/{hashtag}', 'DiscoverController@showTags');
|
||||||
|
|
Loading…
Reference in a new issue