0.19.6 • Published 8 months ago

@itwin/electron-authorization v0.19.6

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

@itwin/electron-authorization

Copyright © Bentley Systems, Incorporated. All rights reserved. See LICENSE.md for license terms and full copyright notice.

Description

The @itwin/electron-authorization package contains an Electron based client for authorization with the iTwin Platform by default and is configurable to work with any OAuth2.0 based provider.

How it works

The OAuth2.0 workflow used in this package is Authorization Code + PKCE, for more information about the flow please visit the Authorization Overview Page.

The package is broken into two main classes ElectronMainAuthorization and ElectronRendererAuthorization that communicate via Electron's IPC between the main and renderer process, respectively. The IPC channel is used to pass the login and access token information and handle refreshing the token when necessary.

During initialization, this package will start an express.js loopback server. The port is 3000 by default and can be adjusted by setting the _redirectUris with url and port

Usage

  1. Setup Main Process (Skip if using @itwin/core-electron`)
  • Add the @itwin/electron-authorization/renderer/ElectronPreload script as a preload to your renderer window.
const win = new BrowserWindow({
  webPreferences: {
    preload: require.resolve(
      "@itwin/electron-authorization/renderer/ElectronPreload"
    ),
  },
});
  • When your browser window is ready, create a new client.
const client = new ElectronMainAuthorization({
  clientId: process.env.clientId,
  scope: process.env.scope,
});

await client.signIn(); // sign in from the main process
new ElectronMainAuthorization({
  ...
  tokenStorePath: yourOwnDirectoryAbsolutePath
})
  • Import the ElectronRendererAuthorization class and create a new instance
  • Register a listener to the ElectronRendererAuthorization.onAccessTokenChanged which is a BeEvent and wait for a token.
import { ElectronRendererAuthorization } from "@itwin/electron-authorization/Renderer";

const client = new ElectronRendererAuthorization();

client.onAccessTokenChanged.addListener((token: string) => {
  console.log("Token received");
  console.log(token);
});

await client.signIn(); // sign in from the renderer process

You probably only want to trigger an initial sign in from one of the processes; both are listed above for sake of completeness.

Note: If you're using moduleResolution: node16/nodenext, you can import using the pattern above.

If not, you can import it like this instead: import { ElectronRendererAuthorization } from "@itwin/electron-authorization/lib/esm/ElectronRenderer";

Linux Compatibility

ElectronMainAuthorization uses Electron's safeStorage to securely encrypt and decrypt refresh tokens on disk. This allows the client to automatically sign-in and receive a new access token between sessions. In order to use safeStorage on linux, specifically Debian/Ubuntu, libsecret-1-dev must be installed.

If keytar is being used in a headless environment additional steps need to be taken. The following packages will need to be installed:

  • libsecret-1-dev
  • dbus-x11
  • gnome-keyring

Users will then need to start a dbus session and create a keyring password by running dbus-run-session -- sh and then creating a keyring with echo 'keyringPassword' | gnome-keyring-daemon -r -d --unlock. Then simply start up the application like normal while in the dbus session: npm run start. If running within a Docker container, make sure to add the --privileged argument when running the container.

API

ElectronMainAuthorization

MethodDescriptionTypeReturns
signInStarts the sign in flowFunctionPromise<void>
silentSignInAttempts a silent sign in with the authorization providerFunctionPromise<void>
signOutSigns a user outFunctionPromise<void>
onUserStateChangedFired when a user's token changesBeEventvoid
refreshTokenForces a refresh of the user's access tokenFunctionPromise<AccessToken>
getAccessTokenreturns a token if available, otherwise calls refreshTokenFunctionPromise<AccessToken>
tokenStorereturns the ElectronTokenStoregetterElectronTokenStore

ElectronBrowserAuthorization

MethodDescriptionTypeReturns
signInStarts the sign in flow from the rendererFunctionPromise<void>
signOutSigns a user outFunctionPromise<void>
onAccessTokenChangedFired when a user's token changesBeEventvoid
getAccessTokenreturns a token if available, otherwise calls refreshTokenFunctionPromise<AccessToken>
hasSignedInWhether or not the user has ever signed ingetterboolean
isAuthorizedWhether the user is signed in and not expiredgetterboolean

new ElectronMainAuthorization(options) - options

PropertyTypeDescription
issuerUrlstring (optional)The OAuth token issuer URL. Defaults to Bentley's auth production URL if undefined.
redirectUrisstring[]List of redirect URIs available for use in the OAuth authorization flow. See note below:
clientIdstringClient application's identifier as registered with the OIDC/OAuth2 provider.
scopesstringList of space separated scopes to request access to various resources.
expiryBuffernumber (optional)Time in seconds that's used as a buffer to check the token for validity/expiry.
ipcSocketIpcSocketBackend (optional)Optional custom implementation of IpcSocketBackend to use for IPC communication with the Frontend counterpart of authorization client.
authenticationOptionsAuthenticationOptions (optional)Additional options to use for every OIDC authentication request made by ElectronMainAuthorization.
tokenStorePathstring (optional)Directory path that overrides where the refresh token is stored.

RedirectUris

The redirectUris property is an array of strings that represent the URIs that the authorization server can redirect to after the user has authenticated. The URIs must be in the format http(s)://localhost:port where port is the port number that the ElectronMainAuthorization instance will listen on. The default port is 3000.

  • In the case of a port collision, it is recommended to use multiple (e.g. three) redirect URIs with different ports.
  • A decent strategy for choosing ports for your application is: 3|4|5{GPR_ID}. For example (GPR_ID used here is 1234):
  • http://localhost:31234/signin-callback
  • http://localhost:41234/signin-callback
  • http://localhost:51234/signin-callback
0.19.6

8 months ago

0.19.3

1 year ago

0.19.4

12 months ago

0.19.5

12 months ago

0.19.2

1 year ago

0.19.0

1 year ago

0.19.1

1 year ago

0.18.5

1 year ago

0.18.4

1 year ago

0.18.3

1 year ago

0.18.2

1 year ago

0.18.1

2 years ago

0.18.0

2 years ago

0.15.0

2 years ago

0.14.1

2 years ago

0.16.0

2 years ago

0.17.0

2 years ago

0.14.0

2 years ago

0.11.0

2 years ago

0.12.0

2 years ago

0.13.0

2 years ago

0.10.0

2 years ago

0.10.1

2 years ago

0.9.0

2 years ago

0.8.5

3 years ago

0.8.4

3 years ago

0.8.1

3 years ago

0.8.0

3 years ago

0.8.3

3 years ago

0.8.2

3 years ago

0.7.0

4 years ago

0.6.0

4 years ago

0.5.1

4 years ago

0.5.0

4 years ago

0.4.0

4 years ago

0.3.2

4 years ago

0.3.1

4 years ago

0.3.0

4 years ago