I was using the magento-cloud CLI tool a bit ago, which is for interacting with their cloud hosting service, and it had an interesting login mechanism. I dug into it a bit to figure out what it was doing and thought I’d share what I learned.
Overall what happens is when running the CLI command “magento-cloud auth:browser-login” it opens up a web browser window/tab that then passes the Magento login info back to the magento-cloud command line app. Seamless with no copy/pasting keys or anything.
After looking into it a bit more I realized it’s basically the standard oauth2 flow:
OAuth2 is a method of granting applications specific tokens for authorization to web services. The apps can then interact with other services but without knowing your account password. You can also see a list of all the apps that have access to your account and individually revoke their access.
With a password or a shared auth token you’d have to update all of the separate apps whenever the password or token is changed.
The interesting thing to me is the magento-cloud app starts a local PHP server that’s operating like the more traditional “web server” in the that flow diagram, with the web browser passing info to it.
I reviewed the code a bit more and here’s roughly the process:
- CLI magento-cloud app starts a simple local PHP server on port 5000 (uses the -S argument of the php binary)
- The “document root” (location on the filesystem that serves files/script for the web server) for that local PHP server is an OAuth2 handler script. Eg, index.html, oauth2.php.
- CLI app opens the web browser pointing to that local server. Eg, http://localhost:5000/oauth2.php
- The first thing the local server script does is HTTP 302 redirect the browser to the Magento Cloud OAuth2 endpoint URL. Eg, oauth.magento.com
- The browser is free to pass any existing cookies/sessions now to the endpoint. If you’re already logged into your Magento account in the browser then it won’t prompt you to login.
- If already logged in or after the user logs in, the OAuth2 endpoint HTTP 302 redirects the browser back to the local server but adds a couple authorization parameters to the URL. Eg, http://localhost:5000/oauth2.php?code=abc123
- The local PHP server script receives a new request and reads the authorization info in the URL. The server script then contacts the Magento Cloud API directly to get an access token and saves that to a config file.
- After success it shuts down the local PHP server and continues forward. Probably using the access token to get a shorter-lived token for increased security.
Overall I was impressed because it was frictionless and fast.
Without using OAuth2, the CLI magento-cloud app could ask for the login info directly like some apps do. More generally, if it was some other desktop app or mobile app it could use an embedded WebView component.
However, after a little research the current best practice is called “AppAuth pattern” and to open a new tab in the web browser, even for mobile.
This is for both increased security, say if you need to login to the service then it helps avoid the native app intercepting the account login info. Even if the app isn’t malicious, it can still be clumsy, such as logging HTTP request & response info to a file for later debugging. Similar to Apple’s recent security bug logging filesystem encryption keys to insecure plaintext.
The other benefit to using an external browser (user agent) like with Magento is that the user might already be logged in, or might already be logged into an existing single-sign on system.
All around neat stuff and an interesting lesson. It helps us stay on top of security and usability best practices that we can incorporate into software we build.