OAuth2 in Moodle 5.3: How to Migrate Your LMS Integrations
Static token stuck in your ERP for years? Moodle 5.3 introduces OAuth 2. See what's changing, what's not, and where to begin.
by Cleverson Gouvêa

OAuth2 in Moodle truly arrived with Moodle 5.3 LTS, released on October 5, 2026, changing how you authenticate ERPs, student information systems, CRMs, and apps that communicate with your LMS. Instead of a static token that lives for years hardcoded in a configuration file, you now have tokens that expire in one hour, secrets with validity periods, and immediate revocation. This guide shows what has changed, what hasn't, and how to plan your migration without breaking any integrations.
TL;DR
- Moodle 5.3 introduced its own OAuth 2 server, client manager, personal access tokens, and revocation endpoints (official release notes).
- These tokens are valid only for the new REST API (
/api/rest/v2). Classic web services continue to use the same static token. They are separate systems.- The new REST API still covers only a few parts of Moodle. Enrollment, user registration, and grades still rely on classic web services in 2026.
- The correct approach now is not to "migrate everything," but rather to inventory, isolate authentication, and migrate by function as the REST API grows.
- New pitfall: by default, every authenticated user can create a personal token. Review this permission on upgrade day.
What OAuth2 in Moodle 5.3 Is (and Isn't)
Until 5.2, anyone integrating an external system with Moodle essentially had one path: classic web services. You enable web services, activate the REST protocol, create an external service with the enabled functions, and generate a token for a technical user. This token goes in the URL (wstoken=...) of each call to webservice/rest/server.php. It does not expire automatically unless someone fills in the "valid until" field.
OAuth 2 is a standard authorization protocol (RFC 6749, from the IETF). Instead of a fixed password, the client system exchanges credentials for a short-lived access token and requests another when it expires. What the token can do is governed by scopes, a list of explicit permissions.
In Moodle 5.3, this appears in a list of development tickets worth knowing about, because each one results in a new screen or behavior on your site:
- MDL-89251: OAuth 2 server implementation in the backend
- MDL-89181: OAuth 2 client manager
- MDL-88473: token revocation endpoints and logic
- MDL-88468 and MDL-88472: screens for client management and OAuth 2 login flows
- MDL-87706: personal access token interface
Now, the point almost every release announcement skips: OAuth2 in Moodle 5.3 does not replace classic web service tokens. The official REST API tokens documentation is explicit: the new tokens only work with the new REST API, have their own creation and management pages, and the "Enable web services" option doesn't even affect them. The classic token remains, managed under Site administration > Server > Web services > Manage tokens.
If you want a general integration overview before diving into authentication details, start with our guide on how to integrate Moodle with other systems. This post is a deep dive into the OAuth 2 aspect.
Static Token vs. OAuth2 in Moodle: The Comparison That Matters
Before comparing, a practical definition: adopting OAuth2 in Moodle means exchanging permanent credentials for temporary, scoped credentials. The static token has a real advantage: it's simple. One line of configuration and the ERP communicates with Moodle. The problem is what happens next. In audits of environments we've taken over, it's common to find tokens created years ago, linked to an administrator account, without IP restrictions and no expiration date. If it leaked in a repository, log, or email, it remains valid until someone remembers to revoke it.
The table summarizes the three ways to authenticate an integration in Moodle 5.3:
| Criterion | Web service token (classic) | Personal access token (new) | OAuth 2 client (new) |
|---|---|---|---|
| Where it works | Classic web service functions | New REST API only | New REST API only |
| Who creates it | Administrator or user with permission | The user themselves, in Preferences | Administrator registers the app |
| Validity | Indefinite, if "valid until" is not set | 7 days to 1 year (default: 1 month) | 1-hour access token |
| Renewal | Manual | Create another token | Refresh token (1 month) or new request |
| Permission limit | Service functions + user permissions | Scopes + user permissions | Scopes (+ user, in login flow) |
| Revocation | Delete the token | Immediate, via user screen | Immediate; deactivating the client cuts everything |
| Best use today | ERP, enrollment, grades, catalog | Scripts and specific automations | Apps and new integrations on the REST API |
The numbers in the last two columns come from the official documentation for OAuth 2 clients and personal access tokens.
Why OAuth 2 Reduces Data Breach Damage
With OAuth2 in Moodle, a stolen access token is valid for a maximum of one hour. The client secret expires in one year. And, if something seems wrong, deactivating the client immediately invalidates issued tokens and prevents the use of secrets. For those who need to respond to a security questionnaire or address US privacy laws in Moodle, this replaces "we have an eternal key somewhere" with "we have credentials with a lifespan, scope, and audit trail."
Where the Static Token Still Prevails
Operational simplicity. Implementing OAuth2 in Moodle assumes that the system on the other side knows how to request and renew tokens. A legacy ERP that only knows how to send a fixed parameter in the URL won't learn to renew tokens on its own. In this case, migration requires an intermediary component (I'll discuss it later), and that comes with a cost.
The Two OAuth 2 Flows in Moodle 5.3: Which One for Each Integration
Anyone configuring OAuth2 in Moodle needs to decide two things right at the start. When registering a client under Site administration > Server > OAuth 2 clients, you choose the client type and the main flow. Both choices cannot be changed later. If you make a mistake, create another client.
Authorization Code: When a User Is Involved
This is the "Sign in with Moodle" flow. The user logs into Moodle, sees the scopes the app requests, and approves or cancels them. The app receives a 1-hour access token and a 1-month refresh token. If the user has already approved all scopes before, Moodle doesn't ask again.
Suitable for:
- Institution's own mobile app. Since the app runs on the student's phone, it's a public client: it cannot keep secrets. In this case, Moodle requires PKCE (RFC 7636), a protection that prevents the use of an intercepted authorization code.
- Student portal or dashboard displaying the user's own data.
- Instructor tools that act on behalf of the logged-in user.
The redirect URI (callback) must be HTTPS, with the exception of localhost for development.
Client Credentials: Machine-to-Machine Communication
No logged-in user. The server system exchanges the client ID and secret for an access token. There is no refresh token: when the token expires, the integration requests another. Only confidential clients (which run on a server you control) can use this flow.
This is the natural candidate for ERPs, student information systems, and CRMs when the operation already exists in the REST API. It's also where OAuth2 in Moodle demands the most discipline. But read the documentation's own warning carefully: with Client Credentials, the app acts as the main site administrator, limited only by the scopes. Anyone with the ID and a valid secret can use it. A broad scope here is a master key with an expiration date.
The Real Limit of OAuth2 in Moodle in 2026: The REST API Is Still Partial
The new REST API is built on Moodle's routing subsystem (based on the Slim Framework), available since 4.5. Routes in the api group are under the /api/rest/v2 prefix, according to the routing documentation for developers. Administrators navigate through the endpoints and required scopes in Site administration > Development > Moodle REST API UI, a Swagger interface.
The problem is coverage. Moodle 5.3 documentation states that only some parts of Moodle are available via the REST API and that more will come in future versions. In practice, for those integrating ERPs and student information systems, this means:
- Creating users, enrolling, unenrolling, and returning grades still depend on classic functions, such as
core_user_create_usersandenrol_manual_enrol_users. - An OAuth 2 token does not call these functions. There is no bridge between the two worlds.
- Available scopes vary by site, because plugins can add their own. Don't rely on a generic list: check your Moodle's Swagger interface.
In other words: today, OAuth2 in Moodle effectively handles apps and read operations already covered by the REST API. Heavy academic registrar integrations still run on the classic token. Anyone selling "complete migration to OAuth 2" right now is selling something Moodle itself doesn't yet deliver.
How to Plan Your Integration Migration to OAuth2 in Moodle
A successful migration is gradual and begins before changing any tokens. Planning OAuth2 in Moodle is, first and foremost, an inventory task. This is the roadmap we use.
1. Inventory All Existing Tokens
Open Manage tokens and list each token: user, service, enabled functions, IP restriction, expiration date, and who uses it. In almost every inventory, at least one token appears whose owner is unknown. That's the first one to investigate.
2. Classify Each Integration
For each system, answer three questions:
- Is there a human user in the flow? If yes, the target is Authorization Code. If no, Client Credentials.
- Do the operations it performs already exist in the REST API? Check in Swagger. If not, it remains on the classic token for now.
- Can the system on the other side renew tokens? A closed-source ERP that doesn't support renewal logic will need an intermediary.
3. Isolate Authentication in an Intermediary Layer
This is the decision that saves the most money in the long run. The ERP's business logic shouldn't call Moodle directly. It calls a small integration service that knows how to authenticate, renew tokens, log, and safely retry calls. When the enrollment function migrates to the REST API, you swap out a module, not rewrite the integration. We describe this design in the technical guide for SGA connected to Moodle.
4. Harden What Remains on the Classic Token
While the function doesn't migrate, reduce the risk of the static token: use a dedicated technical user (never the administrator), a service with only the necessary functions, IP restriction, and an expiration date. All of this already exists in classic web services, and almost no one uses it.
5. Pilot with a Small, Read-Only Use Case
The first OAuth2 test in Moodle production should be something that only reads data and whose error doesn't lock students out: a dashboard, a report, an app screen. Test token renewal, secret expiration, and revocation before putting write operations into production.
6. Run in Parallel, Then Revoke
Keep the old integration active until the new one completes a full cycle (e.g., an end-of-term process). Then revoke the classic token. Not before.
Pitfalls to Expect During the Moodle 5.3 Upgrade
Every User Can Create a Personal Token by Default
The moodle/api:createtoken capability is granted to the "Authenticated user" role. In practice, any student can generate a token for the REST API, within their own permissions and scopes. For most institutions, this doesn't make sense. Decide consciously: remove the capability from the default role and grant it only to those who need it.
The OAuth 2 Clients Screen Disappears Without Composer Dependencies
OAuth 2 clients only appear if the site's Composer dependencies are installed. Installations done by "unzipping" on shared hosting often lack this, and the screen simply doesn't exist. It's not a bug. It's a requirement.
Secrets Expiring in One Year Can Break Integrations
Confidential client secrets expire in one year and appear only once, upon creation. Moodle allows up to two active secrets at the same time precisely so you can rotate them without downtime: generate the new one, swap it in the client system, then revoke the old one. Add the expiration date to your operational calendar on the day you create the client.
Old Web Service Plugins Will Break
Moodle 5.3 deprecated the old \external_* classes (MDL-81225). First-party or third-party plugins that still use these classes currently work with a warning and are likely to break in a subsequent version. Include this in your inventory.
The Upgrade Itself Has Significant Prerequisites
Moodle 5.3 requires PHP 8.3 or higher (64-bit, with the sodium extension and max_input_vars of at least 5000), PostgreSQL 17, MySQL 8.4 or MariaDB 11.4, and only upgrades from Moodle 4.4. If your LMS is on 4.1 or 4.3, there's an intermediate step. I detailed the path in the checklist for upgrading Moodle 4.5 to 5.
When NOT to Migrate to OAuth2 in Moodle Right Now
There are scenarios where postponing OAuth2 in Moodle is the right decision:
- Your LMS is not yet on 5.3. First, complete the upgrade, with testing and validation. Mixing the two changes multiplies the risk.
- The integration only performs operations that the REST API doesn't yet cover. There's nowhere to migrate to. Harden the classic token and wait.
- The system on the other side doesn't support token renewal, and there's no budget for the intermediary layer in this cycle.
- Low volume and stable manual process. If the registrar's office imports one CSV per week without error, the priority is probably elsewhere.
And there's the opposite scenario, where it's worth starting now: a new mobile app, a student portal under development, or any project starting today. Building on the classic token today is creating technical debt you'll pay off two versions from now. For those evaluating their own app, OAuth 2 with PKCE changes the security equation, and I wrote about the investment in your own Moodle app.
Regarding timing: 5.3 is an LTS release, with general support until October 4, 2027, and security fixes until October 1, 2029, according to the official release calendar. There's time to carry out the migration in stages, without rush or improvisation.
Cost and Timeline Considerations
There's no standard price for migrating integrations to OAuth2 in Moodle, because the cost depends on the number of integrations and what each system on the other side accepts. But you can identify where the money goes:
- Inventory and classification: This is the cheapest step and the one that prevents the most waste. Generally, a few days.
- Intermediary layer: This is the real investment. Once built, it serves all integrations.
- Migration by function: Each migrated flow requires renewal, expiration, and revocation testing, in addition to validation with a Moodle copy.
- Ongoing support: Moodle releases versions in April and October. With each one, the REST API may gain new endpoints and scopes, and it's worth re-evaluating what can move away from the classic token.
If the budget you received doesn't include a testing environment or review with each version, it's not cheaper. It's incomplete.
How Agathas Web Can Help
Agathas Web has worked with Moodle for over 15 years. Our team holds Moodle Developer Certification from the Moodle Academy and operates production LMSs, from server to app. We are an independent company, not a Moodle Partner. Planning and executing OAuth2 adoption in Moodle is part of our Moodle development and support service.
What's included in the project:
- Inventory of tokens and integrations, with classification of what migrates now, what waits, and what needs hardening
- Upgrade to 5.3 LTS with validation, including the PHP, database, and Composer requirements that enable the OAuth 2 clients screen
- Integration layer with token renewal, logging, queuing, and idempotence, for ERPs, student information systems (including our SGA), CRMs, and payment gateways
- OAuth 2 client configuration with minimum scopes, scheduled secret rotation, and review of personal token permission
- Mobile app and WhatsApp via Official API, triggered by Moodle events and authenticated correctly
- Managed hosting dedicated to Moodle, with monitoring and verified backup
How it works: We start with a diagnostic conversation to understand your systems, volume, and pain points. Then comes a technical proposal with architecture, timeline, and investment. Execution is carried out in a separate environment, validated with your team, and only then goes to production. The integration code remains with you.
To engage us, contact us via the Agathas Web Moodle services page or the WhatsApp number listed there.
Conclusion: OAuth2 in Moodle Is a Journey, Not a Switch
OAuth2 in Moodle 5.3 is the best security news for integrations in years: one-hour tokens, time-bound secrets, explicit scopes, and immediate revocation. But it lives within the new REST API, which still covers only part of Moodle. Anyone who tries to switch everything at once will find that enrollment and grades have nowhere to go.
The path that works is to inventory, isolate authentication, harden the classic token, and migrate function by function as the REST API grows. If you want this plan executed by those who operate Moodle in production, explore Agathas Web's Moodle service and request a diagnostic of your integrations.
Related posts

Moodle VPS vs. Managed Hosting: Understanding the True Cost
A VPS might seem cheap at under $100 per month. But updating, backing up, and securing Moodle on it costs significantly more. Get the full financial picture.

Custom Moodle App: When Does the Investment Pay Off?
A custom app icon won't pay the bills. Learn the payback calculation, hidden app store costs, and when to stick with the official Moodle app.

Upgrading Moodle 4.5 to 5: A Real-World Checklist
Moodle 5.3 LTS is out, and 4.5 loses security in October 2027. Database, /public folder, plugins, and rollback: practical roadblocks to your upgrade.