-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use passport-multiauth with CreateFreshApiToken #55
Comments
@jflatscher Sorry for the delay. Have you found a solution to your problem? Please, let me know. |
How did you solve the issue? I am still struggling to get this working. |
I'm facing the same issue and have been doing some digging in why this isn't working as well ways to solve this. Also note, though I'm used to work with Passport from multiple projects, I understand it at an implementation level but I've just dived into how the package was written. Why isn't it workingFirst, MultiAuth doesn't look for the TokenCookie that's created when the middleware So problem seems to start in $psrRequest = $this->server->validateAuthenticatedRequest($psrRequest); What will happen is that since the Authorization header is missing, a AuthenticationException is thrown and we get a 401 response. Looking at how Passport is resolving the user in /**
* Get the user for the incoming request.
*
* @param \Illuminate\Http\Request $request
* @return mixed
*/
public function user(Request $request)
{
if ($request->bearerToken()) {
return $this->authenticateViaBearerToken($request);
} elseif ($request->cookie(Passport::cookie())) {
return $this->authenticateViaCookie($request);
}
} We find a hint on where to start with the solution. Possible solutionIn try {
if ($request->bearerToken()) {
$psrRequest = $this->server->validateAuthenticatedRequest($psrRequest);
if (! ($accessToken = $this->getAccessTokenFromRequest($psrRequest))) {
throw new AuthenticationException('Unauthenticated', $guards);
}
$guard = $this->getTokenGuard($accessToken, $guards);
$this->authenticate($request, $guard);
} elseif ($request->cookie(Passport::cookie())) {
// Validate -> Authenticate CookieToken
}
} catch (OAuthServerException $e) { I've not solved how to solve this correctly and securely validate/authenticate the CookieToken yet, any hints/suggestions would be appreciated. Next, since the CookieToken isn't stored in the Currently The cookie is created when a user is authenticated, so instead of changing the Passport middleware MultiAuth can provide it's own, ie. Also the CookieFactory class used by Passport to create the CookieToken only allows for two arguments as well so MultiAuth will need to provide it's own version of that as well. <?php
namespace SMartins\PassportMultiauth\Http\Middleware;
use Closure;
use Illuminate\Http\Response;
use Laravel\Passport\Http\Middleware\CreateFreshApiToken;
use Laravel\Passport\Passport;
use Illuminate\Http\JsonResponse;
use SMartins\PassportMultiauth\Factories\MultiAuthApiTokenCookieFactory as ApiTokenCookieFactory;
use SMartins\PassportMultiauth\Config\AuthConfigHelper;
class CreateFreshMultiAuthApiToken extends CreateFreshApiToken
{
/**
* Create a new middleware instance.
*
* @param SMartins\PassportMultiauth\Factories\ApiTokenCookieFactory $cookieFactory
* @return void
*/
public function __construct(ApiTokenCookieFactory $cookieFactory)
{
$this->cookieFactory = $cookieFactory;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
*
* @return mixed
* @throws \SMartins\PassportMultiauth\Exceptions\MissingConfigException
*/
public function handle($request, Closure $next, $guard = null)
{
$this->guard = $guard;
$response = $next($request);
if ($this->shouldReceiveFreshToken($request, $response)) {
$provider = AuthConfigHelper::getUserProvider($request->user($this->guard));
$response->withCookie($this->cookieFactory->make(
$request->user($this->guard)->getKey(), $request->session()->token(), $provider
));
}
return $response;
}
} <?php
namespace SMartins\PassportMultiauth\Factories;
use Carbon\Carbon;
use Firebase\JWT\JWT;
use Laravel\Passport\Passport;
use Symfony\Component\HttpFoundation\Cookie;
use Illuminate\Contracts\Encryption\Encrypter;
use Illuminate\Contracts\Config\Repository as Config;
class MultiAuthApiTokenCookieFactory
{
/**
* The configuration repository implementation.
*
* @var \Illuminate\Contracts\Config\Repository
*/
protected $config;
/**
* The encrypter implementation.
*
* @var \Illuminate\Contracts\Encryption\Encrypter
*/
protected $encrypter;
/**
* Create an API token cookie factory instance.
*
* @param \Illuminate\Contracts\Config\Repository $config
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
* @return void
*/
public function __construct(Config $config, Encrypter $encrypter)
{
$this->config = $config;
$this->encrypter = $encrypter;
}
/**
* Create a new API token cookie.
*
* @param mixed $userId
* @param string $csrfToken
* @param $provider
* @return \Symfony\Component\HttpFoundation\Cookie
*/
public function make($userId, $csrfToken, $provider)
{
$config = $this->config->get('session');
$expiration = Carbon::now()->addMinutes($config['lifetime']);
return new Cookie(
Passport::cookie(),
$this->createToken($userId, $csrfToken, $provider, $expiration),
$expiration,
$config['path'],
$config['domain'],
$config['secure'],
true,
false,
$config['same_site'] ?? null
);
}
/**
* Create a new JWT token for the given user ID and CSRF token.
*
* @param mixed $userId
* @param string $csrfToken
* @param $provider
* @param \Carbon\Carbon $expiration
* @return string
*/
protected function createToken($userId, $csrfToken, $provider, Carbon $expiration)
{
return JWT::encode([
'sub' => $userId,
'csrf' => $csrfToken,
'provider' => $provider,
'expiry' => $expiration->getTimestamp(),
], $this->encrypter->getKey());
}
} Then it should just be the validation/authentication of the CookieToken left. @sfelix-martins would appreciate any feedback you have about this or someone else that's interested in getting this solved. |
Hi!
I would like to use passport-multiauth with CreateFreshApiToken class, so I can use my api with my javascript application.
'web' => [ ... \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class ],
When I replace the basic auth class with the multiauth class in $routeMiddleware in Kernel.php, I get 401 Unauthorized error
//'auth' => \Illuminate\Auth\Middleware\Authenticate::class, 'auth' => \SMartins\PassportMultiauth\Http\Middleware\MultiAuthenticate::class,
Is there any possibility to make it work with multiauth?
The text was updated successfully, but these errors were encountered: