Frappe Mobile Control
Mobile Control - Custom Frappe Application
- Author: dhwani-ris
- Repository: https://github.com/dhwani-ris/frappe-mobile-control
- GitHub stars: 20
- Forks: 6
- License: AGPL-3.0
- Category: Integrations
- Maintenance: Actively Maintained
- Frappe versions: develop
Install Frappe Mobile Control
bench get-app https://github.com/dhwani-ris/frappe-mobile-control
Add the Frappe Gems badge to your README
Maintain Frappe Mobile Control? Paste this into your README:
[](https://frappegems.com/gems/apps/dhwani-ris/frappe-mobile-control)
About Frappe Mobile Control
### Mobile Control
Mobile Control - Custom Frappe Application
### Installation
You can install this app using the [bench](https://github.com/frappe/bench) CLI:
```bash
cd $PATH_TO_YOUR_BENCH
bench get-app $URL_OF_THIS_REPO --branch develop
bench install-app mobile_control
```
### Mobile Auth API
These endpoints are exposed as whitelisted methods and are intended for a mobile
client. All endpoints expect `POST` requests and use the `api/v2/method/` route.
Endpoints:
- `mobile_auth.login` - Login with username/password.
- `mobile_auth.logout` - Logout and revoke refresh tokens.
- `mobile_auth.send_login_otp` - Send OTP to mobile number for login.
- `mobile_auth.verify_login_otp` - Verify OTP and complete login.
- `mobile_auth.refresh_token` - Refresh access token using refresh token.
- `mobile_auth.permissions` - Get current user permissions (requires authentication).
- `mobile_auth.get_translations` - Get translation dictionary for one or more languages (requires authentication). By default returns DB translations only; use `all=1` for full (apps + DB). Use `lang=hi,en` for multiple languages.
- `mobile_auth.get_social_login_providers` - Discover enabled social providers from `Social Login Key` (guest).
- `mobile_auth.get_social_authorize_url` - Build provider-direct OAuth authorize URL for one-tap social login (guest).
Response tokens:
- `access_token` expires in 24 hours.
- `refresh_token` expires in 30 days and is rotated on every refresh.
#### Social login APIs (one-tap)
These APIs are designed for mobile SDK OAuth (PKCE) login and avoid the extra
provider selection click on Frappe login page.
- Providers are auto-discovered from Frappe `Social Login Key`.
- No extra provider config is required in `mobile_control`.
- Sensitive data such as `client_secret` is never returned.
Required mobile callback URI:
- `frappemobilesdk://oauth/callback`
Provider discovery:
```
GET /api/method/mobile_auth.get_social_login_providers
```
Example response:
```json
{
"providers": [
{ "id": "google", "label": "Google", "icon_url": "https://..." },
{ "id": "microsoft", "label": "Microsoft", "icon_url": null }
]
}
```
Provider-direct authorize URL:
```
POST /api/v2/method/mobile_auth.get_social_authorize_url
```
Body:
```json
{
"provider": "google",
"client_id": "mobile-client-id",
"redirect_uri": "frappemobilesdk://oauth/callback",
"scope": "openid all",
"state": "random-state",
"code_challenge": "pkce-code-challenge",
"code_challenge_method": "S256"
}
```
Example response:
```json
{
"authorize_url": "https://accounts.google.com/o/oauth2/v2/auth?...state="
}
```
Notes:
- Returned URL is generated by Frappe Social Login flow for the selected provider.
- `client_id` in request body is your **Frappe OAuth Client ID** (not Google client id).
- After social login succeeds, Frappe redirects to its OAuth authorize endpoint, which then redirects to `redirect_uri` (`frappemobilesdk://oauth/callback`) with authorization code.
Troubleshooting:
- Provider not showing: verify `Social Login Key` exists and social login is enabled for that key.
- Invalid provider error: ensure `provider` matches discovered provider `id` (`google`, `microsoft`, etc).
- Redirect URI mismatch: ensure app sends `frappemobilesdk://oauth/callback` (or add allowlisted URIs in site config).
- Social opens wrong provider or fails immediately: verify `Social Login Key` for that provider is enabled and configured with valid client credentials.
#### Auth response shape (login, verify OTP, refresh token)
Login, `mobile_auth.verify_login_otp`, and `mobile_auth.refresh_token` return a response like:
```json
{
"message": "Logged In",
"user": "user@example.com",
"full_name": "User Name",
"language": "en",
"access_token": "...",
"refresh_token": "...",
"offline_enabled": false,
"mobile_form_names": [
{
"mobile_workspace_item": "Mobile Refresh Token",
"group_name": "",
"doctype_meta_modifed_at": "2026-02-14 14:40:49.962439",
"doctype_icon": ""
}
],
"roles": ["Mobile User", "All", "Desk User"],
"permissions": [
{
"doctype": "Mobile Refresh Token",
"read": true,
"write": false,
"create": true,
"delete": false,
"submit": false,
"cancel": false,
"amend": false
}
]
}
```
- `language` is the user's language (default `"en"` if blank).
- `offline_enabled` is the value of the `Mobile Configuration.offline_enabled` Check field. The mobile SDK uses this to decide whether to run as an offline-first client or a thin online client. Default `false`. Only emitted when the parent `enabled` flag is on. See the SDK's `doc/OFFLINE_MODE_TOGGLE.md` for the full client-side contract.
- `roles` is an array of role names.
- `permissions` is an array of objects; each has `doctype` and the flags `read`, `write`, `create`, `delete`, `submit`, `cancel`, `amend`.
Client flow:
1. Login or OTP verify to receive `access_token` + `refresh_token`.
2. Use `access_token` as `Authorization: Bearer ` for API calls.
3. When access token expires, call `mobile_auth.refresh_token` with the
`refresh_token` to get a new pair.
User permissions:
- Permissions are automatically included in login, OTP verify, and refresh token responses.
- Permissions include user roles and doctype-level permissions (read, write, create, delete, submit, cancel, amend) for mobile-configured doctypes.
- To refresh permissions without re-authenticating, call `mobile_auth.permissions` endpoint.
Translations:
- Call `GET /api/method/mobile_auth.get_translations?lang=hi` (Bearer token required). Omit `lang` for English (`en`). By default only **DB translations** (Translation doctype) are returned. Add `&all=1` or `&all=true` to get **full translations** (apps CSV/MO + DB). For **multiple languages**, use comma-separated codes: `?lang=hi,en`. Response is always the same shape: `{ "langs": ["hi"], "translations_by_lang": { "hi": { "source text": "translated text", ... } } }` (or multiple keys in `langs` and `translations_by_lang`). Use `translations_by_lang[lang][source] ?? source` for lookup.
#### Request Examples
All requests use:
```
POST {{base_url}}/api/v2/method/
```
Login:
```json
{
"username": "your.username",
"password": "your.password"
}
```
Send OTP:
```json
{
"mobile_no": "+15551234567"
}
```
Verify OTP:
```json
{
"tmp_id": "TMP_ID_FROM_SEND_OTP",
"otp": "123456"
}
```
Refresh token:
```json
{
"refresh_token": "REFRESH_TOKEN"
}
```
Logout:
```
Authorization: Bearer
```
Get permissions:
```
GET {{base_url}}/api/method/mobile_auth.permissions
Authorization: Bearer
```
Response:
```json
{
"roles": ["Mobile User", "System Manager"],
"permissions": [
{
"doctype": "Customer",
"read": true,
"write": true,
"create": true,
"delete": false,
"submit": true,
"cancel": false,
"amend": false
}
]
}
```
#### Bruno Collection
The `API/` directory contains a Bruno collection to try the mobile auth endpoints locally.
**Collection:** `API/bruno.json`
**Requests:**
| File | Description |
|------|-------------|
| `Login with username and password.bru` | POST login with username/password; returns `access_token`, `refresh_token`, `roles`, `permissions`, `language`. |
| `Login with mobile.bru` | POST send OTP to mobile number (`mobile_auth.send_login_otp`). |
| `Login with mobile verify.bru` | POST verify OTP and login (`mobile_auth.verify_login_otp`). |
| `Get Access Token.bru` | POST refresh token to get new `access_token` and `refresh_token`. |
| `Logout.bru` | POST logout (Bearer token required); revokes refresh tokens. |
| `permissions.bru` | GET current user roles and permissions (Bearer token required). |
| `get_translations.bru` | GET translation dictionary; optional `?lang=hi` (Bearer token required). |
| `App Status.bru` | GET app status (enabled, package_name, app_title, version). Guest. |
| `App Configuration.bru` | GET mobile configuration list. Guest. |
**Setup:** Set `base_url` in collection/environment variables. For auth requests, set `username`, `password`, and after login use the returned `access_token` as Bearer token in subsequent requests (or use Bruno’s response scripts to save the token).
### Contributing
This app uses `pre-commit` for code formatting and linting. Please [install pre-commit](https://pre-commit.com/#installation) and enable it for this repository:
```bash
cd apps/mobile_control
pre-commit install
```
Pre-commit is configured to use the following tools for checking and formatting your code:
- ruff
- eslint
- prettier
- pyupgrade
Related Integrations apps for Frappe & ERPNext
- Insights — Open Source Business Intelligence Tool
- Raven — Simple, open source team messaging platform
- Frappe Whatsapp — WhatsApp cloud integration for frappe
- Frappe Assistant Core — Infrastructure that connects LLMs to ERPNext. Frappe Assistant Core works with the Model Context Protocol (MCP) to expose ERPNext functionality to any compatible Language Model
- Biometric Attendance Sync Tool — A simple tool for syncing Biometric Attendance data with your ERPNext server
- Frappe React Sdk — React hooks for Frappe
- Frappe Js Sdk — TypeScript/JavaScript library for Frappe REST API
- Mcp — Frappe MCP allows Frappe apps to function as MCP servers