eLabSDK2.OAuth
Hierarchy
-
default↳
OAuth
Methods
getAccessToken
Static getAccessToken(sdkPluginID, scope?): Promise<string>
Fetch a valid access token for the given installed add-on.
Returns the current access token stored server-side, refreshing it transparently if it has
expired. Returns undefined when no token exists yet (the user has not completed the OAuth
flow); call getAuthUri and open the resulting URL to start authentication.
Parameters
| Name | Type | Description |
|---|---|---|
sdkPluginID | number | Installed add-on identifier from getInstalledAddonID. |
scope? | string | Optional OAuth scope to filter by (matches the scope used at auth time). |
Returns
Promise<string>
The bearer access token, or undefined if not authenticated.
Example
const token = await eLabSDK2.OAuth.getAccessToken(addonID);
if (!token) {
const authUri = await eLabSDK2.OAuth.getAuthUri(addonID);
window.open(authUri, 'oauth', 'width=500,height=450');
}getAuthUri
Static getAuthUri(sdkPluginID): Promise<string>
Build the authorisation URI to start the OAuth 2.0 flow for the add-on.
Open the returned URL in a popup window — the third-party provider authenticates the user and
redirects back to eLab's redirect URI with a code query parameter. Capture that code on the
callback page and pass it to setAccessAndRefreshToken to exchange it for tokens.
Parameters
| Name | Type | Description |
|---|---|---|
sdkPluginID | number | Installed add-on identifier from getInstalledAddonID. |
Returns
Promise<string>
The provider authorisation URL with client id, scope, and state encoded.
Example
const uri = await eLabSDK2.OAuth.getAuthUri(addonID);
const popup = window.open(uri, 'oauth', 'width=500,height=450');getInstalledAddonID
Static getInstalledAddonID(rootVar): Promise<number>
Look up the installed add-on identifier (sdkPluginID) by its rootVar.
Marketplace add-ons are identified internally by a numeric sdkPluginID per install,
but author code references the add-on by its symbolic rootVar. Reads from the
__eLABSDKCustomPlugin global the host injects at page load — no network call.
Returns undefined when the add-on is not installed (or the global is missing because
the SDK is loaded on a page that does not list installed add-ons).
Parameters
| Name | Type | Description |
|---|---|---|
rootVar | string | The rootVar identifier the add-on declares (e.g. 'NL_BIOITECH_BOXCOM'). |
Returns
Promise<number>
The installed add-on's sdkPluginID, or undefined if not installed.
Example
const addonID = await eLabSDK2.OAuth.getInstalledAddonID('NL_BIOITECH_BOXCOM');
if (!addonID) {
throw new Error('Box add-on is not installed');
}handleHostCallback
Static handleHostCallback(): Promise<boolean>
Host-side OAuth callback handler.
Runs in the popup's main window (the host page), reads code / sdkPluginID from the
current URL, exchanges the code for tokens, then closes the popup. The opener (the addon
iframe) detects the popup closing and re-fetches the access token via
getAccessToken.
Three guards before exchanging anything:
- Path: only fires on the dedicated server-redirected callback page (exact match).
Stops a malicious cross-origin opener from feeding a crafted
?code=to an arbitrary SDK page that happens to share the suffix. - Same-origin opener: cross-origin
window.opener.sessionStorageaccess throws and we bail. The opener-was-malicious case lands here. - Flow record presence: the opener must have a
sessionStorageflow record keyed to the samesdkPluginID(set by runAuthFlow). Catches the path-spoof case where an attacker somehow lands the popup on the callback URL without an in-flight flow. The record is single-use (cleared on read).
If the provider redirects back with ?error=... (e.g. user clicked Deny), the popup
closes itself so the opener's polling loop resolves promptly instead of waiting for
the auth-wait timeout.
setupOAuthNS invokes this automatically on page load; addons do not call it.
Returns
Promise<boolean>
True when a callback was detected and handled.
runAuthFlow
Static runAuthFlow(sdkPluginID, scope?): Promise<string>
Run the full OAuth authorisation flow for the given add-on.
Opens the provider authorisation URL in a popup, waits for the popup to close (the host
callback handler closes it once the code is exchanged), then resolves with the freshly-
issued access token. Resolves with undefined when the user closes the popup without
authenticating, or when the wait times out.
Runs entirely in the host context — when an addon (in its sandbox iframe) calls this
method through the SDK facade, the call is RPC-routed to the host so window.open can
succeed under the host's CSP and the popup opens at the host origin. The addon iframe's
sandbox stays at allow-scripts only.
Parameters
| Name | Type | Description |
|---|---|---|
sdkPluginID | number | Installed add-on identifier from getInstalledAddonID. |
scope? | string | Optional OAuth scope. |
Returns
Promise<string>
Access token, or undefined if the user cancelled.
Example
const token = await eLabSDK2.OAuth.runAuthFlow(addonID);
if (!token) return; // user cancelledsetAccessAndRefreshToken
Static setAccessAndRefreshToken(sdkPluginID, code, scope?): Promise<void>
Exchange a short-lived authorisation code for access and refresh tokens.
Call this from the OAuth callback page after the provider has redirected back with a code.
The tokens are stored server-side; future getAccessToken calls will return
them and refresh automatically when needed. The returned promise rejects on transport
errors and on non-2xx responses.
Parameters
| Name | Type | Description |
|---|---|---|
sdkPluginID | number | Installed add-on identifier — usually read from the callback URL's sdkPluginID parameter. |
code | string | The authorisation code received from the provider. |
scope? | string | Optional OAuth scope (must match the scope used at auth time). |
Returns
Promise<void>
Resolves when the tokens are persisted.
Example
// OAuth callback page
const params = new URLSearchParams(window.location.search);
await eLabSDK2.OAuth.setAccessAndRefreshToken(
Number(params.get('sdkPluginID')),
params.get('code') ?? ''
);
window.close();© 2026 eLabNext
Updated about 3 hours ago