drupal-react-oauth-provider v1.1.0
drupal-react-oauth-provider
React Context provider and hooks for Drupal, with support for Oauth2 authentication.
Simplify headless Drupal REST and authentication.
- Written in Typescript
- Zero dependencies
- Drupal 8+
- Drupal 7 - (Planned)
- Collaboration, feedback, and feature requests welcome
Features
- Context Provider stores Oauth across app
- Abstract away all token management
Supports proxies to hide oauth client ID, secret etc. on frontend
- Hooks such as
useAPI
,useLazyAPI
,useLazyLogin
, anduseLazyLoginProxy
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
Lazy?
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/',
};
ReactDOM.render(
<React.StrictMode>
<DrupalProvider config={config}>
<App />
</DrupalProvider>
</React.StrictMode>,
document.getElementById('root'),
);
Log in users with useLazyLogin
or useLazyLoginProxy
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
})
}
Create a proxy server that stores oauth settings.
Any stack can be used as long as it return the JSON from Drupal. Proxy server should listen for username
and password
for login, and refresh_token
for refreshing the access token. The proxy should have the fields in the example above.
Example: https://github.com/niallmurphy-ie/drupal-react-oauth-provider-proxy-example/blob/master/index.js
const [login, { loading, error, data }] = useLazyLoginProxy();
...
onClick={() =>
login({
username, // 'user1',
password, // '123456',
proxyURL: 'https://myproxy.mysite.com/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={() =>
lazyAPI({
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
Requirements
- Oauth2 (Tested with Simple OAuth (OAuth2) & OpenID Connect)
- An oauth client created in Drupal with ID / scope etc.
- Drupal 8+
Recommended
- 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 withuseAPI
oruseLazyAPI
Note
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