Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cesium.ITwinPlatform.defaultAccessToken should be a function instead of a string #12386

Open
jason-crow opened this issue Dec 20, 2024 · 2 comments
Assignees

Comments

@jason-crow
Copy link
Contributor

Feature

Propose that Cesium.ITwinPlatform.defaultAccessToken be converted to Cesium.ITwinPlatform.getDefaultAccessToken as an async function instead of a string

The main justification of this change is to avoid dealing with that token expiring.

As a static string, unless the user resets it, the token will expire and if they set it to a variable the reference will be lost and again it will expire.

As an async function it always grabs the latest token. The consumer is forced to call it before they use it, but as tokens are always used for async requests to a service, this should not be a problem. Additionally, if they do save it on a variable the result is still a valid token. Effectively, you are free from this expiration contingency now.

References:
iModel integration

@ggetz
Copy link
Contributor

ggetz commented Jan 2, 2025

@jjspace Could you please triage?

@jjspace
Copy link
Contributor

jjspace commented Jan 10, 2025

Some initial thoughts on a plan

Our Resource class has an option to use a retryCallback automatically when a request fails. I think this can be utilized to fetch a new token only when it's needed, ie when a request just failed due to Auth issues 403.

The question would just be how best to expose this in the API. I'm currently thinking of adding a function ITwinPlatform.requestNewAuthToken that takes no arguments and returns the string of the new token.

Then in each internal Resource we use for the API requests setting a retryCallback that wraps the logic to update the defaultAccessToken for users like this:

const resource = new Resource({
  // ...
  retryCallback: async function (resource, error) {
    if (error.statusCode !== 403) {
      // we only care about Auth failures
      return false;
    }

    const newToken = await ITwinPlatform.requestNewAuthToken();
    if (!defined(newToken)) {
      return false;
    }
    resource.headers.Authorization = `Bearer ${newToken}`;
    ITwinPlatform.defaultAccessToken = newToken;
    return true;
  },
  retryAttempts: 1,
});

The resulting code for users of this API would look something like this

const authToken = await requestAuthToken();
ITwinPlatform.defaultAccessToken = authToken;
ITwinPlatform.requestNewAuthToken = requestAuthToken();

ITwinData.createTilesetFromIModelId(iModelId);

There's a larger discussion to be had about how Resource handles auth tokens and "sharing" them between Resource objects and derived routes. See #10435.

Right now the token needs to be stored "somewhere else" which is the ITwinPlatform.defaultAccessToken but I don't think users should be required to remember to update that themselves in the ITwinPlatform.requestNewAuthToken function

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants