OAuth flow in Electron Apps
December 03, 2022 - Tech
The purpose of OAuth is to obtain a token that allows your app to make requests to a third-party service on behalf of a user. This let’s you do things like access their GitHub repositories for code analysis, access their Slack messages to create a bot, or access their Google Sheets to import them into your tools.
Typical OAuth flow
When obtaining an OAuth token, the flow is typically something like this:
-
The user starts the OAuth flow. The user enters your app, and you request permission to access their data stored in a third-party service. If they accept, the OAuth flow begins.
-
Your app opens the third-party login page. Your app either in this browser tab or a separate one, opens the login URL for the third-party. In the URL that you open, you typically also add a redirect URL parameter that the third-party service will use later on.
-
The user enters their credentials. The user puts in their username and password in this screen to authenticate with the third-party service, indicating that they are willing to allow your app to access their data.
-
The login page passes the credentials onto the third-party service. This allows the third-party service to verify the user’s credentials.
-
The third-party service provides an authorization code. This code represents that the user has authenticated with the service.
-
The login page sends the authorization code to the redirect URL. The redirect URL from step 1 receives the authorization code. Typically, this URL points to an endpoint on your web server. Along with the URL, the login page will add the code as a URL parameter, something like:
http://example.com/api/oauthcallback?code=xxxx
. -
Your web server requests an OAuth token from the third-party service. Using the authorization code, the web server is able to obtain an OAuth token (as well as a refresh token in some cases). The token allows your app to make requests to the third-party service on behalf of the user.
-
The third-party service responds with a token.
-
The web server redirects back to the web app. After storing the OAuth token for future use, your web server should typically send a (302) redirect to have the browser display your web app to the user, indicating that the OAuth flow has successfully completed.
This flow is already complicated when you have a web server and web app. But, how do you do it in an Electron app without a web server? What kind of redirect URL do you use? It’s simple. You can use any URL, because you can intercept any URL from a browser window opened by Electron.
OAuth flow in Electron apps
First, you can show the login screen to the user by opening a new BrowserWindow
. When you provide the redirect URL to the third-party service, you can really choose anything you like. I usually use something like http://127.0.0.1:9999/oauthcallback
. There’s usually nothing running on that URL (even if there was, this isn’t a problem, I’ll explain why).
const authWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: false,
}
});
const url = new URL(THIRD_PARTY_LOGIN_URL);
url.searchParams.set(
"redirect_uri",
"http://127.0.0.1:9999/oauthcallback/");
authWindow.loadURL(url.toString());
When the third-party login screen tries to redirect to the URL we provided, we simply intercept the request before the BrowserWindow
can send the request.
const {
session: { webRequest },
} = authWindow.webContents;
const filter = { urls: ["http://127.0.0.1:9999/oauthcallback/*"] };
webRequest.onBeforeRequest(filter, async ({ url }) => {
const parsedUrl = new URL(url);
authWindow.close();
const code = parsedUrl.searchParams.get("code");
// Do the rest of the authorization flow with the code.
});
After receiving the code, the rest of the steps happen as usual. With this method, you can fetch an OAuth token without a server inside of your Electron app.
Let me know what you think about this article by leaving a comment below, reaching out to me on Twitter or sending me an email at pkukkapalli@gmail.com