feat: gate oauth2 authorization on per-client roles
This commit is contained in:
1 parent
79709e3a3e
commit
cc3d32fcbb
6 files changed
+436
-11
No files matched your search
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use League\Bundle\OAuth2ServerBundle\Model\AbstractClient;
|
||||
|
||||
/**
|
||||
* An OAuth2 client, extended with the roles an account must hold to authorize it.
|
||||
*
|
||||
* The bundle ships its own Client model and maps it for us. Replacing it (via
|
||||
* league_oauth2_server.client.classname) is the supported way to add a column: the bundle
|
||||
* maps AbstractClient as a mapped superclass and carries name, secret, redirectUris,
|
||||
* grants, scopes, active and allowPlainTextPkce, then stops mapping its own Client, so
|
||||
* this class only has to declare the table, the primary key and what it adds.
|
||||
*
|
||||
* Why the requirement lives here rather than in configuration: the alternative was a map
|
||||
* in services.yaml keyed on the client identifier, and identifiers differ per environment,
|
||||
* so that map would have needed an env var per client and would have drifted from the
|
||||
* client table it describes. A column cannot drift from its own row.
|
||||
*
|
||||
* Nothing validates the contents. A misspelled role is not an error, it is a client that
|
||||
* authorizes nobody, so AuthorizationCodeListener logs the requirement whenever it
|
||||
* refuses — that is what makes the mistake visible without a database query.
|
||||
*/
|
||||
#[ORM\Entity]
|
||||
#[ORM\Table(name: 'oauth2_client')]
|
||||
class OAuth2Client extends AbstractClient
|
||||
{
|
||||
/**
|
||||
* Declared protected on AbstractClient and mapped by the bundle only for its own
|
||||
* Client, so the custom class has to map it itself. The type restates the parent's
|
||||
* contract, which redeclaring the property would otherwise widen.
|
||||
*
|
||||
* @var non-empty-string
|
||||
*/
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: 'string', length: 32)]
|
||||
protected string $identifier;
|
||||
|
||||
/**
|
||||
* The roles that entitle an account to authorize this client. An empty list denies
|
||||
* everyone: a row nobody has configured and a client that needs no roles are the same
|
||||
* stored value, and of the two readings only "deny" is safe.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
#[ORM\Column(type: 'json')]
|
||||
private array $requiredRoles = [];
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getRequiredRoles(): array
|
||||
{
|
||||
return $this->requiredRoles;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<string> $requiredRoles
|
||||
*/
|
||||
public function setRequiredRoles(array $requiredRoles): self
|
||||
{
|
||||
$this->requiredRoles = $requiredRoles;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user