B A C K
Understanding Simple OAuth in Drupal: Authentication for Decoupled Applications

Understanding Simple OAuth in Drupal: Authentication for Decoupled Applications

Knowledge

What is Simple OAuth?

Simple OAuth is a Drupal module that provides authentication capabilities for decoupled applications. It implements token-based authentication, allowing users to securely access your application through access tokens rather than traditional login credentials.

Token-Based Authentication Flow

The authentication process follows a hierarchical token system:

  • Access Token — The primary authentication credential, generated as a unique SHA-256 hash.
  • Refresh Token — Used to generate new access tokens when they expire.
  • Base Authentication — Required when both access and refresh tokens expire.

Understanding Access Tokens

Access tokens are JWT (JSON Web Tokens) that contain two key components:

Claims

Claims store essential user identity information needed by the client application. By default, Simple OAuth includes two claims:

  • mail — User's email address.
  • username — User's account name.

Scopes

Scopes represent user roles within your application. They determine what actions a user can perform. Some important points about scopes:

  • Multiple roles should be specified with space separation.
  • If no scope is defined, the authenticated role becomes the default.
  • The final token includes both requested scopes and any additional roles defined in the client ID.

Extending Access Token Claims

To add custom claims beyond the default mail and username, you need to extend the AccessTokenEntity class. Here's how:

class MyAccessTokenEntity extends AccessTokenEntity {
  public function convertToJWT(CryptKey $privateKey) {
    $private_claims = [];
    \Drupal::moduleHandler()
      ->alter('simple_oauth_private_claims', $private_claims, $this);

    if (!is_array($private_claims)) {
      $message = 'An implementation of hook_simple_oauth_private_claims_alter '
        . 'returns an invalid $private_claims value. $private_claims '
        . 'must be an array.';
      throw new \InvalidArgumentException($message);
    }

    $builder = (new Builder())
      ->setAudience($this->getClient()->getIdentifier())
      ->setId($this->getIdentifier(), TRUE)
      ->setIssuedAt(time())
      ->setNotBefore(time())
      ->setExpiration($this->getExpiryDateTime()->getTimestamp())
      ->setSubject($this->getUserIdentifier())
      ->set('scopes', $this->getScopes());

    // Add custom claims here
    // Example: $builder->set('user_picture', ...);
    foreach ($private_claims as $claim_name => $value) {
      $builder->set($claim_name, $value);
    }

    $key   = new Key($privateKey->getKeyPath(), $privateKey->getPassPhrase());
    $token = $builder->sign(new Sha256(), $key)->getToken();
    return $token;
  }
}

Implementing the Custom Token Entity

To use your custom token entity, you'll need to register it with Drupal's service container:

class MyServiceProvider extends ServiceProviderBase implements ServiceProviderInterface {
  public function alter(ContainerBuilder $container) {
    $definition = $container->getDefinition('simple_oauth.repositories.access_token');
    $definition->setClass('Drupal\my_module\Repositories\MyAccessTokenRepository');
  }
}

Best Practices

  • Always validate private claims before processing.
  • Consider token expiration times carefully for your use case.
  • Implement proper error handling for token generation and validation.
  • Document any custom claims added to the system.
  • Monitor token usage and implement rate limiting if necessary.

Reach back to us if you need any help.