How a Drupal OAuth 2.0 server with Simple OAuth issues tokens
When a mobile app, a decoupled front end or a partner system needs to call Drupal's APIs, the goal is to avoid sharing user passwords with that client. Simple OAuth is the contributed module that makes Drupal the token issuer: the client requests an access token from Drupal, presents it on each API call, and Drupal checks it against the permissions of the user or client it represents. It is commonly paired with JSON:API, so the tokens guard the same resources that JSON:API exposes. This is the opposite direction from the OpenID Connect client module, which lets an external provider sign Drupal users in. In a Simple OAuth design, Drupal is the authority that other systems trust, and the two modules can coexist on one site when you need both directions.
Before you commit to a design, confirm the details that change the build on the Simple OAuth project page on Drupal.org: which grant types are supported in the release you plan to run, whether OpenID Connect issuance is available and how it is enabled, the default and configurable token lifetimes, and which Drupal core branches each release supports. Ask your team to record these answers in the design document, because they decide whether a mobile app can use an authorization code flow with PKCE, whether a server-to-server partner can use a client credentials flow, and how often clients must refresh. Treat grant support as a hard requirement to verify, not an assumption to carry from older Simple OAuth releases.
Plan the signing keys, the consumer records and the refresh behavior as decisions, not defaults. Each API client needs a consumer entry with its allowed grants and scopes, and each token is signed with a key pair that must be generated, stored outside the web root, rotated and backed up. Token lifetimes control how long a stolen token remains useful, so set them against the sensitivity of the data behind JSON:API. Test revocation and expiry with a real client before launch, and confirm with your security team how logouts from the mobile app or front end invalidate existing tokens.
What a Drupal OAuth server needs before installation
Simple OAuth turns a Drupal site into a token issuer for apps and partner systems, so every later decision depends on a stable platform underneath it. The checks below cover the Drupal and PHP baseline, the module release that matches core, the transport and key storage rules, and the people who must own the work.
Drupal 11 and PHP 8.3 baseline
Drupal 11 is the current major version, and it requires PHP 8.3 or later. Confirm the PHP runtime, web server and database against the system requirements before you plan anything else, because a token server on an unsupported PHP version is a patching problem from day one. Drupal runs on Apache, Nginx and other web servers, with MariaDB, MySQL, PostgreSQL or SQLite as the database, so record which combination your hosting team will support.
Simple OAuth release matched to core
Choose the Simple OAuth release that supports the Drupal core version in use, and pin it in Composer rather than accepting whatever resolves on update. Check the module's compatibility notes on its Drupal.org project page before each core upgrade, since the OAuth server and its dependencies are part of the upgrade scope. Ask your partner to confirm the grant types you need are available in that release line.
JSON:API configuration and exposed resources
Simple OAuth protects requests to JSON:API, so the JSON:API module must be enabled and its resource exposure reviewed before clients connect. Decide which entity types, fields and bundles are readable by token holders, and which need no access at all. Record the list in the design document, because each exposed field becomes a data-exposure decision that auditors and security reviewers will ask about.
TLS on every endpoint
Authorization, token and userinfo endpoints must only be reached over HTTPS, including internal load balancer hops that terminate TLS. Confirm the certificate chain, the redirect rules that block plain HTTP, and how the reverse proxy passes the original scheme to Drupal so generated URLs and redirect URIs are correct. Mixed scheme configuration is a common cause of token exchange failures and insecure callbacks.
Key pair stored outside the web root
Simple OAuth signs access tokens with a private key and a public key used for verification. Store both files outside the document root, with permissions limited to the web service account, and keep them out of the Git repository and build artifacts. Document where the keys live in each environment, and plan how they are rotated, since rotating keys invalidates tokens and must be scheduled with client owners.
Composer access, staging and client owners
Your team needs Composer access to the build repository, a staging site that matches production in PHP version, HTTPS and JSON:API settings, and a named owner for every OAuth client. Without a staging site, key rotation and grant changes are tested in production. Without an owner per client, nobody can approve redirect URI changes or revoke a compromised application, so agree that responsibility in writing before installation.
Why Drupal as the token issuer differs from Drupal as an OIDC client
Drupal can sit on either side of a login, and the two roles are configured with different modules. When Drupal is the token issuer, the Simple OAuth module makes Drupal hand out access tokens to other applications such as a mobile app, a single-page front end or a partner system. Drupal then owns the user database, the password check and the consent screen that asks a user to approve an app. When Drupal is an OpenID Connect client, the contributed OpenID Connect module makes Drupal trust an external provider such as Keycloak or Okta. The provider authenticates the person, and Drupal creates or updates a local account on first sign-in. Drupal does not verify the password itself in that case.
The choice follows from where you want the login screen and the password store to live. If Drupal already holds your editors and customers and only needs to serve API clients, Simple OAuth alone may be enough, and you accept that Drupal's login becomes the single point of authentication for those clients. If your workforce or customer identities already live in an identity provider, a single provider in front of Drupal is usually the cleaner design, and Drupal becomes a client that trusts it. Many organizations need both: the identity provider signs people in, and Drupal issues tokens to the apps those people use. Confirm which of these you need before the content model or user roles are built, because account linking, role mapping and logout behavior depend on it.
Before you commit, check three things with your team. First, decide which system is the source of truth for each account, including who can disable a user and how quickly that change reaches Drupal. Second, confirm that the identity provider's tokens and Drupal's tokens will not be confused by your API clients, since each issuer has its own keys and claims. Third, test sign-out in both directions, because ending a session in one system does not automatically end it in the other. Confirm the exact module versions and supported grant types against the current project pages on Drupal.org before you write the design, since these change between releases.
How to configure Drupal OAuth 2.0 server steps in order
This sequence takes a Drupal site from a bare install to a tested OAuth 2.0 server that issues tokens for JSON:API clients. Each step closes with a check, so the team knows the previous step works before the next one depends on it.
Install Simple OAuth and its dependencies
The Drupal developer adds the Simple OAuth module with Composer from the project's Composer root, so that dependencies resolve in the same build as the rest of the site. They then enable the module and JSON:API through the admin interface or Drush, on a non-production site first. Done means the module appears as enabled, the OAuth settings page loads for an administrator, and the build passes on the same Composer lock file that will be promoted later.
Generate signing keys outside the web root
The platform engineer generates a private and public key pair with a standard tool such as OpenSSL, then places both files in a directory outside the document root. Permissions should let only the web server user read the private key. The key paths are then entered in the Simple OAuth settings. Done means PHP can read the keys, the settings page reports them as valid, and a direct browser request for the key file path returns a denial or a not-found response.
Set access and refresh token lifetimes
The security lead and the application owner agree on how long access tokens and refresh tokens stay valid, then enter those values in the Simple OAuth settings. Shorter access token lifetimes limit the damage from a leaked token, while refresh token lifetimes determine how often users must sign in again. Record the agreed values in the change log. Done means a test token issued after the change carries an expiry that matches the configured lifetime.
Create OAuth client entries for each application
The Drupal developer creates one consumer entry per mobile app, front end or partner system, rather than sharing a single client across them. Each entry records the grant types the application needs, its allowed scopes, its exact redirect URIs and, for confidential clients, a secret that is stored in the application's secret manager. Done means each client appears in the consumer list with its own identifier, and an authorization request using a redirect URI that does not match the registered value is refused.
Assign roles and permissions to users and clients
The Drupal administrator creates dedicated roles for API access and grants only the JSON:API resource permissions each client needs. Machine clients that use the client credentials grant need a user account with that role, and that account should not be an administrator. Scopes should be reviewed against the same role model. Done means a permission audit for each API role lists only the expected content types and operations, and a test account can read exactly those resources.
Request tokens for each grant on a test site
The QA engineer requests a token for each grant type the clients use, against a non-production copy of the site with the same configuration. For the authorization code flow, they complete a sign-in in a test browser and exchange the code at the token endpoint. Confirm the supported grants with the Simple OAuth project page for the installed release before testing. Done means each grant returns an access token, the refresh grant returns a new one, and a valid token reads an allowed JSON:API resource with a success response.
Confirm denied requests before promotion
The QA engineer repeats the test with requests that should fail: no token, a malformed token, an expired token, a token with a scope the client lacks, and a read against a resource outside the API role. The site should refuse each one with an authentication or authorization error and write it to the logs. Done means every negative case returns the expected refusal, the results are saved with the release record, and the same configuration is ready to move to production.
Which OAuth grant fits each kind of client
A native mobile app is a public client. Anyone can download the app package and inspect it, so a client secret embedded in the binary cannot stay secret. For this reason, mobile apps are normally designed to sign users in with the authorization code flow combined with PKCE (Proof Key for Code Exchange), which binds the code exchange to a value that only the app instance holds. Confirm with the Simple OAuth project page whether PKCE is supported in the release you plan to run, because support for this and other grants depends on the module version.
- Authorization code with PKCE: the app opens the system browser or a secure web view, receives a one-time code and exchanges it with a per-login verifier.
- No shared secret in the binary: treat any client secret shipped in the app as public information and rely on user consent and short-lived tokens instead.
- Refresh token storage: keep refresh tokens in the platform's secure storage, such as the iOS Keychain or Android Keystore, and never in plain preferences.
- Rotation and revocation: plan how a lost or stolen device gets its refresh token revoked, and how the app signs out cleanly.
- Short access token lifetimes: keep access tokens short so a leaked token has limited value.
Before build, confirm the exact grants and PKCE behavior in the Simple OAuth release you will run, and check the project page for any grant that depends on a later version.
A single-page application or a decoupled front end that runs entirely in the browser is also a public client. Its JavaScript source and every token it receives can be read by the user and by any script that runs in the page. The usual pattern is the authorization code flow with PKCE, so the browser never needs a client secret. Where the front end is rendered by a server you control, a confidential client with its own server-side session can hold the secret instead, which changes the risk profile. The choice depends on the architecture, so record it as a design decision.
- Authorization code with PKCE in the browser: the client generates the verifier in memory for each sign-in and discards it after the exchange.
- Backend-for-frontend option: a server component holds the client secret and the tokens, and the browser holds only a session cookie.
- Refresh token exposure: avoid long-lived refresh tokens in browser storage. Use rotation, short lifetimes and silent renewal where the design allows.
- Token audience and scope: limit each token to the JSON:API resources the front end actually calls.
- Logout and session end: define how the front end revokes tokens when a user signs out or the session expires.
Check which token storage pattern and refresh behavior the chosen Simple OAuth release supports, and confirm the JSON:API access configuration against the project documentation before design sign-off.
A partner system that calls Drupal from a back-end service has no user present at the time of the call, so the usual choice is the client credentials grant. The partner's service holds a client ID and secret in its own protected configuration, authenticates as itself and receives an access token scoped to the permissions granted to that client. Because the secret stays on infrastructure the partner controls, this is a confidential client. The risk moves from the code to the secret itself, so the secret handling becomes the main control.
- Client credentials grant: the partner service requests a token directly from Drupal with no user interaction.
- Secret storage: keep the client secret in a secrets manager or the partner's vault, with rotation and access logging.
- Dedicated Drupal user and roles: map the OAuth client to a restricted Drupal account so the token cannot reach beyond the required content and fields.
- Token lifetime and renewal: request a new token when the old one expires instead of storing long-lived tokens on disk.
- Per-partner clients: create one client per partner so access can be revoked without affecting other integrations.
Confirm whether the Simple OAuth release in use supports the client credentials grant and how it maps to Drupal users, and check the project page for any grant or setting that depends on a later module version.
Refresh tokens let a client obtain new access tokens without asking the user to sign in again. They are valuable to an attacker because they extend access over time, so their handling matters more than their existence. Whether a given client needs a refresh token at all depends on the grant and the client type, and this should be decided per client, not applied to every integration by default.
- Issue only where needed: skip refresh tokens for server-to-server clients that can request a new token directly.
- Rotation: where the release supports it, issue a new refresh token on each use and invalidate the old one.
- Revocation path: provide a documented way to revoke a token when a device is lost, a user leaves or a partner contract ends.
- Lifetime settings: set access and refresh lifetimes separately, and record the chosen values in the design document.
- Logging: log token issuance, refresh and revocation events so the security team can investigate misuse.
Confirm the refresh token options, lifetimes and rotation behavior in the Simple OAuth configuration for your release before setting policy, since these settings vary between versions.
Mapping users, roles and scopes to token claims and JSON:API permissions
This table traces each identity on the Drupal side, from a human user to a partner system account, to the permissions it receives, the JSON:API resources it can reach and the owner who approves changes. Read each row as a rule to write down before configuration starts, then confirm the exact claim names and scope settings in the Simple OAuth documentation for your release. The main takeaway is that a token only grants what the underlying Drupal user can already do, so access design belongs in roles and entity permissions.
| Identity or control | Drupal permission it receives | JSON:API resources it controls | Owner who approves changes |
|---|---|---|---|
| Mobile app end user | Authenticated role with only the entity access their account needs | Content and user resources they can view under entity access rules | Product owner with the security lead |
| Front-end editor or reviewer | Editor or reviewer role limited to assigned content types and workflow states | Create, update and review operations on named content types | Content owner for the site |
| Partner system account | Dedicated non-human user with one narrow custom role and no shared login | Only the resources the partner integration needs, read-only where possible | Integration owner, with the security team approving scope |
| OAuth client (confidential) | Client linked to the dedicated account it acts for, with scopes the client needs | Limited to the scopes and resources listed in the approved client record | Platform owner for client registration |
| OAuth client (public, such as a mobile app) | No client secret; access comes from the signed-in end user's permissions | Mirrors what the signed-in user may see, not a wider set | Product owner with the security lead |
| Unpublished or private content | Access controlled by entity access and node grants, not by the token alone | Hidden from JSON:API responses unless the user holds view rights for that state | Content owner, reviewed when workflows change |
| Revoked user or client | Account blocked or client disabled in Drupal, which blocks new token issuance | Existing access tokens remain valid until expiry unless your configuration revokes them; confirm this behavior | Identity administrator, with an incident runbook |
| Claim and scope mapping | Claim names and scope definitions set in configuration and exported to code | Scope names drive which resource permissions apply; confirm the mapping in the module documentation | Platform owner, reviewed on each module upgrade |
Hardening token issuance, keys and client secrets
Token issuance is where a Drupal OAuth 2.0 and OpenID Connect server carries the most risk, because every mobile app, front end and partner system depends on it. The cards below cover the transport, key, secret, token lifetime, browser, abuse, logging and patching decisions that a team should settle before the first client goes live.
TLS-only authorization and token endpoints
Serve the authorization, token, revocation and JWKS endpoints only over TLS, and redirect or reject plain HTTP at the reverse proxy or load balancer. Confirm that the web server and any ingress set HSTS and that redirect URIs registered for clients accept only HTTPS, except for loopback addresses that native apps may use. Check the setting in staging with a scanner before partners are onboarded. Decide who owns certificate renewal and how expiry alerts reach the team.
Signing key storage and rotation
Simple OAuth signs access tokens with an RSA key pair stored on the Drupal server, so the private key must be readable only by the web process and excluded from version control and shared backups. Decide where the key lives (file system outside the web root, a secrets manager or a mounted volume), how a new key is published alongside the old one, and how long tokens signed by the old key remain valid. Write the rotation runbook before go-live.
Client secret handling for confidential and public clients
Confidential clients such as partner back ends hold a client secret, which should be generated randomly, stored hashed in Drupal and rotated on a set schedule or after staff changes. Public clients such as single-page apps and mobile apps have no secret and must use Authorization Code with PKCE. Decide which client type each integration uses, and remove any client that was created with a shared secret for a browser or device app.
Short token lifetimes and refresh controls
Set access token lifetimes short enough that a stolen token has limited use, and make refresh tokens rotate on each use so reuse can be detected. Decide how long a refresh token stays valid, which clients may receive one, and how a user or administrator revokes a session. Test expiry behavior with each front end, because mobile and single-page clients often fail silently when refresh is misconfigured.
CORS settings for browser clients
Browser-based front ends call the token and JSON:API endpoints from their own origins, so the CORS allow-list must name only the front-end origins that are approved for each client, never a wildcard on endpoints that accept credentials. Review the CORS settings in the Drupal services configuration and at any CDN or proxy in front of Drupal, because a proxy can add or strip headers. Keep the list under change control so a new origin needs a documented request.
Rate limiting on the token endpoint
The token endpoint accepts password-guessing and client authentication attempts, so limit requests per client and per source address at the reverse proxy, WAF or API gateway in front of Drupal. Decide thresholds with the partners that call the endpoint, since a batch integration can look like an attack. Confirm how Drupal's own flood protection and login throttling interact with the proxy limits so legitimate users are not locked out.
Audit logging of grants and revocations
Record token issuance, refresh, revocation and failed client authentication with the client identifier, grant type, user and timestamp, and send these records to a log store that the Drupal administrators cannot silently edit. Decide retention with your compliance owner, and confirm which events the installed Simple OAuth version writes to the Drupal log. Without this trail, a compromised client cannot be traced after the fact.
Security advisories for core and contributed modules
Simple OAuth, its dependencies and Drupal core all receive advisories from the Drupal Security Team, which publishes CVE identifiers and risk scores and uses a fixed Wednesday window for security releases. Subscribe your team to these advisories, name an owner who can apply a patch within a set period, and test token issuance after each update. Ask any implementation partner how they will track advisories during the retainer period.
Why JSON:API calls fail even with a valid OAuth token
This table lists the failures we see most often when a client presents a valid bearer token to Drupal's JSON:API and still gets a denial or an unexpected result. Each row gives the likely cause, the fix and the first log or configuration check to run. Work through the rows in order, because the first two checks (role permissions and key matching) account for most cases.
| Failure | Likely cause | Fix and first check |
|---|---|---|
| Token accepted but JSON:API returns 403 | The user tied to the token lacks view permission on the resource type or field | Grant the role view access to the entity type in JSON:API permissions. First check: the Drupal log for access denied entries and the roles of the token's user |
| Token rejected after moving between environments | Signing keys on the target differ from the keys that issued the token | Copy the private and public key pair to the environment and confirm the key paths in Simple OAuth settings. First check: signature verification errors in the watchdog or application log |
| Authorization request fails at the redirect step | The client redirect URI or allowed origin is not registered exactly as the client sends it | Register the full redirect URI, including scheme, host, port and path, and add the front-end origin to CORS settings. First check: the redirect URI in the authorization request against the client record |
| Tokens expire before the client refreshes them | Clock skew between servers or access token lifetime set shorter than the client's refresh logic expects | Sync time with NTP on all web nodes and align lifetimes with the client's refresh behavior. First check: the token issued-at and expiry timestamps against server time |
| Authorization header missing on Drupal | A reverse proxy, load balancer or CDN strips the Authorization header before it reaches PHP | Pass the header through in the proxy configuration, for example with an explicit rule for the Authorization header on the JSON:API path. First check: request headers logged at the proxy and at the Drupal web server |
| Mobile or single-page client fails token exchange | A public client was configured with a client secret, or the client sends a secret it does not hold | Set the client to public without a secret and use the authorization code flow with PKCE. First check: the client type on the Simple OAuth client record and the grant type in the token request |
| Resource returns empty results or not found | The JSON:API resource is not exposed to the role, or the entity type is disabled for JSON:API | Confirm the entity type is enabled for JSON:API and that the role has access to the bundle and fields. First check: the JSON:API resource list at the collection endpoint for the user's role |
Planning Simple OAuth through Drupal upgrades and branch end of life
The Simple OAuth release line has to match the Drupal core line in use, so any move to a newer Drupal version or a newer Simple OAuth branch is a planned upgrade, not an in-place swap of tokens. Start by mapping your current Drupal core version, the Simple OAuth branch you run and the PHP version on each server. Confirm the end of life date for the 5.2 branch on the Simple OAuth project page before you quote it to stakeholders, because that date decides how long the current build can stay in production without a supported path. Treat that date as a fixed input to the plan, not an estimate.
Core timing matters as much as the module branch. According to the Drupal core release schedule, Drupal 10 reaches end of life on December 9, 2026, and Drupal 12 is scheduled for the week of December 7, 2026. Each major version also raises the PHP floor: Drupal 10 requires PHP 8.1 or later, Drupal 11 requires PHP 8.3 or later and Drupal 12 requires PHP 8.5 or later, according to the Drupal.org PHP requirements page. A token service that works on today's PHP runtime may need a runtime upgrade before the Drupal upgrade can start, so put PHP and the web server images into the same change window as the core work.
Test the OAuth behavior on a staging copy built from a current production database before any cutover. Confirm that access tokens and refresh tokens are issued for each grant your clients use, that existing client registrations still authenticate with their stored secrets or redirect URIs, and that the signing keys load correctly after the upgrade. Rehearse key rotation as its own step, with a documented way to publish the new public key, a window where old and new keys are both valid, and a rollback that restores the previous key pair. Mobile apps and partner systems cannot be fixed by a quick server deploy, so plan their client updates and their token expiry before the cutover date.
What buyers ask before hiring help with a Drupal OAuth server
How do the number of clients and grants change the cost of a Drupal OAuth server?
Cost rises mainly with the number of client applications, the grant types each one uses and the number of distinct token audiences, because each combination needs its own configuration, testing and access rules. A single authorization code flow for one front end is a small job. Mobile apps, a single-page front end and partner machine-to-machine clients, each with different scopes and token lifetimes, multiply the test matrix. Ask for the written scope to list every client, its grant type, the scopes it requests, how tokens are stored, and which JSON:API resources each scope can reach. Those lines are what a quote should price, and they are also the first place to find work that was left out.
How long does a first Drupal OAuth integration take, and what sets that duration?
The duration depends on how many clients and grants are in scope, how much of the role model already exists in Drupal, and how quickly the internal team answers decisions. A first integration usually includes key generation, consumer setup, scope design, token lifetime choices, testing with each client and a handover. Confirm the timeline with the partner against your written scope rather than against a general figure, and ask which parts depend on your identity provider, your API owners or your release calendar. Drupal core and contributed module release timing also matters, since security releases are published on Wednesdays and can interrupt planned work.
What must our internal team provide before an OAuth server build starts?
Three inputs decide most of the early work: named API owners who approve which content and fields each client may read or write, a role model that maps Drupal roles to the permissions a token carries, and test clients that represent each real consumer. Without test clients, the integration can only be checked against assumptions. Ask the partner to list these inputs as dependencies in the scope, with an owner and a date for each, so that a delay in one of them is visible to the steering group rather than discovered during testing.
Can a competent internal Drupal developer set up an OAuth server alone?
A developer who knows Drupal configuration, Composer and the JSON:API module can install the Simple OAuth package and configure a first client, and many teams do this successfully. The harder parts are judgement calls: which grants to enable, how long tokens should live, how refresh tokens are revoked, how scopes map to content access, and how key files are protected. Those decisions also need security review and a test plan. A practical approach is to have the internal developer build the first client while an experienced partner reviews the configuration, writes the test cases and documents the operating procedure.
How do we handle an existing Drupal 7 or older site that needs an OAuth server?
Drupal 7 security support ended on January 5, 2025, and Drupal 6 and 7 sites cannot be updated in place to Drupal 10 or later. They are migrated into a new site with the core Migrate, Migrate Drupal and Migrate Drupal UI modules or with Drush, and themes must be rebuilt. The OAuth server should be designed on the new Drupal site, not added to the old one. If the legacy site must stay online for a period, the Drupal 7 end of life partner program lists certified providers for extended security support. Ask the partner to scope the migration and the OAuth work separately so each can be estimated and tested on its own terms.
How are ongoing support, upgrades and security fixes arranged after launch?
Support is best defined in the written scope before launch, not after. Ask who monitors Drupal core and Simple OAuth security advisories, who applies patches, how often test clients are rerun and who approves token policy changes. Drupal core and contributed projects follow a published release calendar, and each major version has its own PHP requirement, so the upgrade path must include runtime changes. DeployOpen offers ongoing support, upgrades and continuous testing as retainers, which can be set against the same written scope. Ask for the response expectations, the upgrade cycle and the testing cadence in writing.
What should a written scope for a Drupal OAuth server include?
A useful scope lists each client with its grant type, scopes, token lifetimes and resources, along with the identity source, the role-to-permission map, the test cases and the documents to be handed over. It should also name the Drupal and PHP versions in use, state the hosting environment and say who holds the signing keys. Items left out of scope, such as user provisioning from an external identity provider or custom token claims, should be named explicitly. Fixed-scope engagements are agreed in writing before work starts, so this list is the document to compare quotes against.
How DeployOpen scopes, builds and supports a Drupal OAuth server
DeployOpen plans, builds, documents and supports self-hosted Drupal inside your own infrastructure, including Simple OAuth configuration for mobile apps, front ends and partner systems. Each engagement starts from a written scope that names the grants, clients, token rules and verification steps before any build work begins.
How we scope
- Inventory every client type that will request tokens, such as mobile apps, single-page front ends and partner back ends.
- Agree in writing which OAuth 2.0 grants and OpenID Connect flows each client type may use on your Drupal version.
- Confirm the Drupal branch, PHP version and Simple OAuth release that your hosting and upgrade plan will support.
How we build
- Configure Simple OAuth consumers, scopes and key pairs in a non-production environment that mirrors your production hosting.
- Test token issuance, expiry, refresh and revocation against JSON:API routes with the access rules your content model requires.
- Review cross-site request and redirect URI handling for each front end, and record the decisions in the project repository.
How we hand over
- Deliver a configuration record covering clients, scopes, grant types, token lifetimes and the owners of each setting.
- Provide runbooks for rotating signing keys, revoking clients and responding to a suspected token leak.
- Document the upgrade path for Simple OAuth and Drupal core, including the 5.2 branch end of life, so your team can plan releases.
How we support
- Ongoing support, upgrades and continuous security testing are available as retainers after handover.
- Monitor Drupal security advisories that affect the modules in your OAuth stack and agree a patch window with your team.
- Ask any partner to confirm response times, coverage hours and escalation paths in the written support agreement before signing.

