OAuth

SKILL

  • mmo.oauth
  • agent skill
  • mmoframework-skill://mmo.oauth/mmo-agent-login/SKILL.md
--- name: mmo-agent-login description: Log into a local MMOFramework deployment (an application using mmo.oauth) without a password and test its pages in a browser. Use when asked to try, click through, smoke-test, screenshot or check the pages of an MMO application running on localhost, to see a page as a given user or role, or to call its json api as a logged-in user. --- # Logging into a local MMOFramework site An application using mmo.oauth answers every page with its login form until a session holds a token. Never type a password into that form, ask for one, or keep one in a skill or a note: the application's command line hands out a login link instead. It only needs a username: the project's own skill names the one to use (my.oviepro's `oviepro-local-demo` does); otherwise ask the user which account to test with. ## 1. Get a link From the application's folder (the one with `admin.php` and `bootstrap.php`): ```bash php admin.php agent-login --user=<username> --url=<site url> [--redirect=<page>] [--as=<username>] [--ttl=PT8H] -m ``` - `--url` is the url Apache serves the site at (`http://localhost/my.oviepro`). The command line can't work it out by itself, so always pass it. - `-m` prints json: `data.url` is the link, `data.header` is an `Authorization: Bearer ...` header for the api, `data.user` and `data.expires` describe the session. Without `-m`, the same is printed as text. - `--as=<username>` logs in as someone else to see the site with that user's rights. The `--user` account needs the `sudo.switchAccount` scope for that. - The command is `AdminController::route_agentLogin` (mmo.core). It works only when the application is in dev mode (`MMO_MODE` is `dev`) and gives a 403 otherwise. Each call stores a new access token, which lives for `--ttl`. - If the command opens the interactive menu instead of answering, or the project has no `admin.php`, see [No command line](#no-command-line). Keep the link and the header out of your replies: anyone holding them is logged in until they expire. ## 2. Open it in the browser Navigate the browser to `data.url`. The `login` route stores the token in the session and redirects to `--redirect` (the site's root by default). From there the browser stays logged in like a user who typed the password. `/logout` ends the session. For the json api, send `data.header` with each request instead (`curl -H "$header" .../user/scopes.json`). ## 3. Visit every page `GET <site url>/pages.json` (mmo.client's `PageController::routePages`), fetched from the logged-in browser or with the header, lists every page the current user can open: ```json {"data": [{"path": "incidents", "url": "http://localhost/my.oviepro/incidents", "title": "Incidents", "menu": true, "templated": false}, ...]} ``` - Pages the user's rights hide are not in the list. Compare two `--as` users to check a role's access. - A `templated` page needs parameters (`?uid={uid}`), so it can't be opened from the list. Reach it from its parent page, through a link the parent renders. - An entity's own page is `entity?uid=<uid>`. Take a uid from a list page or the data api. For each page, record: 1. the HTTP status and the page title (a login form means the session expired: get a new link); 2. console errors (`read_console_messages` with `onlyErrors`); 3. failed requests: status 400 or more (`read_network_requests`); 4. a PHP error printed into the page (in dev mode the framework prints the exception in a `<pre>`); 5. a screenshot when something is wrong. Then report the failing pages: url, what failed, and the error text. ## No command line The command needs a script that boots the application (its root `bootstrap.php`, so its configuration and keys) and routes to `MMO\core\controllers\AdminController` or a subclass of it. my.oviepro's `admin.php` does. A project made by `php tools/mmo.php project` doesn't: its `scripts/admin.php` is mmo.admin's deployment tool, which loads neither. Add this one to the project's root, as `admin.php`, and say so to the user: ```php <?php require(__DIR__ . '/bootstrap.php'); $app = \MMO\app([\MMO\core\Application::class => ['=routes' => [\MMO\core\controllers\AdminController::class]]]); $app->runInteractive(); ``` An `admin.php` that already exists but doesn't route to `AdminController` gets it added to its routes. Several shell controllers can share a script: the one with the command answers.