Skip to content

Commit

Permalink
Cache by user->sub, update to auth0 8
Browse files Browse the repository at this point in the history
  • Loading branch information
tomhelmer committed Mar 22, 2024
1 parent 3c3d3dd commit 54f8698
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 89 deletions.
4 changes: 0 additions & 4 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,4 @@

// The base URL for the user service
'user_api_base_url' => env('AUTH0_USER_API'),

// The URI for the JWKS file (fallback to https://gsv.eu.auth0.com/.well-known/jwks.json)
'jwks_uri' => null,

];
101 changes: 33 additions & 68 deletions src/GsvAuth0Provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,57 +9,44 @@
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Cache;

use Auth0\SDK\Token;
use Auth0\SDK\Configuration\SdkConfiguration;

class GsvAuth0Provider
{
protected $auth0_domain;

protected $api_identifier;

protected $jwks_uri;
protected $configuration;

protected $cache;

public function __construct(?string $auth0_domain, ?string $api_identifier, ?string $jwks_uri = null)
public function __construct(?string $domain, ?string $audience)
{
$this->auth0_domain = $auth0_domain;
$this->api_identifier = $api_identifier;

$this->jwks_uri = $jwks_uri ?: sprintf('https://%s/.well-known/jwks.json', $this->auth0_domain);

$this->cache = app()->make('cache.store');

// Add a neat little custom method that only caches if a condition is met
$this->cache->macro('rememberWhen', function ($condition, $key, $ttl, $callback) {
if ($condition) {
return $this->remember($key, $ttl, $callback);
} else {
return $callback();
}
});
$this->configuration = new SdkConfiguration(
domain: $domain,
audience: [$audience],
clientId: 'dummy', // Don't need a real value as we only validate jwt's
clientSecret: 'dummy', // Don't need a real value as we only validate jwt's
cookieSecret: 'dummy', // Don't need a real value as we only validate jwt's
);
}

/**
* Authenticate the token
* Authenticate the jwt
*
* @param string $token
* @return self
*/
public function authenticate(string $token): self
public function authenticate(string $jwt): self
{
if ($this->auth0_domain === null) {
throw new Exception('Auth0 domain not set');
}

if ($this->api_identifier === null) {
throw new Exception('API identifier not set');
if ($this->configuration === null) {
throw new Exception('Auth0 configuration not set');
}

try {
$info = $this->decodeJWT($token);

$this->setUser($info, $token);
} catch (InvalidTokenException $e) {
$token = new Token($this->configuration, $jwt, \Auth0\SDK\Token::TYPE_ACCESS_TOKEN);
$token->verify();
$token->validate();
$this->setUser($token->toArray(), $jwt);
} catch (\Exception $e) {
// Re-throw into a 401
throw new InvalidTokenException($e->getMessage(), 401);
}
Expand All @@ -78,14 +65,17 @@ public function loadUserData(Auth0User $user = null): self

$client = app()->make('gsv-auth0-user-service');

$userData = $this->cache->rememberWhen(
$user->expires->isAfter(Carbon::now()), // Only cache if this condition is met
md5($user->token), // The cache key
$user->expires->diffInSeconds(Carbon::now()), // Cache expires when the auth expires
function () use ($client, $user) {
return $client->setToken($user->token)->fetch($user->auth0_id);
}
);
if ($user->expires->isAfter(Carbon::now())) {
$userData = Cache::remember(
md5($user->sub),
$user->expires->diffInSeconds(Carbon::now()),
function () use ($client, $user) {
return $client->setToken($user->token)->fetch($user->auth0_id);
}
);
} else {
$userData = $client->setToken($user->token)->fetch($user->auth0_id);
}

if ((isset($userData['status']) && $userData['status'] === 'Error') || empty($userData['data'])) {
throw new UserNotFoundException($userData['message'], 401);
Expand Down Expand Up @@ -158,29 +148,4 @@ protected function setUser(array $info, string $token): self

return $this;
}

/**
* Verify a JWT from Auth0
*
* @see https://github.com/auth0/laravel-auth0/blob/8377bd09644de60d5a8688653589ea299ccd2969/src/Auth0/Login/Auth0Service.php#L206
* @param string $encUser
* @param array $verifierOptions
* @throws InvalidTokenException
* @return array
*/
protected function decodeJWT(string $encUser, array $verifierOptions = []): array
{
$jwks_fetcher = app()->make('gsv-auth0-jwks-fetcher', [
'cache' => $this->cache,
]);
$jwks = $jwks_fetcher->getKeys($this->jwks_uri);

$token_verifier = app()->make('gsv-auth0-token-verifier', [
'domain' => $this->auth0_domain,
'apiIdentifier' => $this->api_identifier,
'jwks' => $jwks,
]);

return $token_verifier->verify($encUser, $verifierOptions);
}
}
18 changes: 1 addition & 17 deletions src/GsvAuth0ProviderServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@

namespace Adaptdk\GsvAuth0Provider;

use Auth0\SDK\Helpers\JWKFetcher;
use Auth0\SDK\Helpers\Tokens\AsymmetricVerifier;
use Auth0\SDK\Helpers\Tokens\TokenVerifier;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\ServiceProvider;
Expand All @@ -29,8 +26,7 @@ public function register()
$this->app->singleton('gsv-auth0-provider', function () {
return new GsvAuth0Provider(
config('gsv-auth0-provider.domain'),
config('gsv-auth0-provider.api_identifier'),
config('gsv-auth0-provider.jwks_uri')
config('gsv-auth0-provider.api_identifier')
);
});

Expand All @@ -39,18 +35,6 @@ public function register()
return new UserService(config('gsv-auth0-provider.user_api_base_url'));
});

$this->app->bind('gsv-auth0-jwks-fetcher', function ($app, $params) {
return new JWKFetcher($params['cache']);
});

$this->app->bind('gsv-auth0-token-verifier', function ($app, $params) {
return new TokenVerifier(
sprintf('https://%s/', $params['domain']),
$params['apiIdentifier'],
new AsymmetricVerifier($params['jwks']),
);
});

// Open the gates
Auth::viaRequest('gsv-auth0-provider', function (Request $request) {
$token = $request->bearerToken() ?: $request->query('authToken');
Expand Down

0 comments on commit 54f8698

Please sign in to comment.