React Context provider and hooks for Drupal, with support for Oauth2 authentication.
Simplify headless Drupal REST and authentication.
  • [x] Written in Typescript
  • [x] Zero dependencies
  • [x] Drupal 8+
  • [ ] Drupal 7 - (Planned)
  • [x] Collaboration, feedback, and feature requests welcome


  • Context Provider stores Oauth across app
  • Abstract away all token management
  • Hooks such as useAPI, useLazyAPI, and useLazyLogin access REST / JSON:API / Views REST etc. with user credentials in the header
  • GET, POST, PATCH, and DELETE supported
  • _format=json added by default. _format=hal_json can be added manually


Taking inspiration from Apollo GraphQL's useLazyQuery, the hooks provided can be triggered at any time, instead of when the React component is rendered.

How does it work?

Wrap your React app with DrupalProvider.

import { DrupalProvider } from 'drupal-react-oauth-provider';
const config = {
	url: 'https://d9-testing.niallmurphy.dev/',
		<DrupalProvider config={config}>
			<App />

Log in users with useLazyLogin

import { useLazyLogin } from 'drupal-react-oauth-provider';
const [login, { loading, error, data }] = useLazyLogin();
    onClick={() =>
    	login({ // examples below
    		username, // 'user1',
    		password, // '123456',
    		client_id, // '5e6c8415-9a1f-4d8b-9249-72b9dc6f7494',
    		client_secret, // 'client_secret_simple_oauth',
    		grant_type, // 'password',
    		scope, // 'consumer' < Some Drupal role that's set in oauth

Check authentication status with authenticated

import { useAuthenticated } from 'drupal-react-oauth-provider';
const isAuthenticated = useAuthenticated();
{isAuthenticated ? 'You are authenticated': 'You are not authenticated'}

Make queries with useAPI or useLazyAPI

Get, post, patch, or delete any data you need. eg. Views.

import { useLazyAPI } from 'drupal-react-oauth-provider';
const [lazyAPI, { loading, error, data }] = useLazyAPI();
onClick={() =>
		endpoint: 'node/3',
		method: 'PATCH',
		body: {
			nid: [{ value: '3' }],
			type: [{ target_id: 'article' }],
			title: [{ value: 'This is hardcoded to show how body works.' }],

Log out with useLazyLogout

import { useLazyLogout } from 'drupal-react-oauth-provider';
const [logout] = useLazyLogout();
<button onClick={() => logout()}>Logout</button>

Drupal Installation


  • Enable REST / RESTUI / JSON:API / Views etc.
  • Create a "me" user View with Contextual Filter: User ID: User ID from logged in user to get user roles etc. Access it with useAPI or useLazyAPI


There is a problem with Jest tests. They require react and react-dom as devDependencies, but this breaks production. And help writing more comprehensive tests would be welcome. Unit testing the lazy functions is difficult so I think E2E testing with Cyrpus would work better. I've seen some people say that testing Apollo's lazy queries is difficult.

I hope the Drupal community can share ideas on how to make this better.

Enjoy your headless Drupal.

License: MIT


View Github