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

setConfig not always updating Authorization header #1980

Closed
Perronef5 opened this issue Mar 28, 2024 · 16 comments
Closed

setConfig not always updating Authorization header #1980

Perronef5 opened this issue Mar 28, 2024 · 16 comments
Labels

Comments

@Perronef5
Copy link

Perronef5 commented Mar 28, 2024

Your Environment

  • Plugin version: 4.15.2
  • Platform: iOS and Android
  • React Native version (react-native -v): 0.73.6
  • Plugin config
{
  url: `${ReactNativeConfig.MAPPING_URL}/locations`,
  desiredAccuracy: BackgroundGeolocation.DESIRED_ACCURACY_HIGH,
  distanceFilter: 10,
  stopTimeout: 5,
  debug: debugMapping && isApprovedEmail,
  logLevel: BackgroundGeolocation.LOG_LEVEL_OFF,
  stopOnTerminate: false,
  startOnBoot: true,
  foregroundService: true,
  enableHeadless: true,
  backgroundPermissionRationale: {
    title: "title",
    message:"message",
  },
  notification: {
    title: "title",
    text: '',
    smallIcon: 'drawable/ic_notification',
    largeIcon: '',
    sticky: true,
    channelName: 'Channel Name',
    channelId: 'Channel ID,
  },
  locationAuthorizationAlert: {
    titleWhenNotEnabled: "enabled",
    titleWhenOff: "off",
    instructions: Platform.OS === 'ios'
      ? "ios instructions"
      : "android instructions",
    cancelButton: "cancel button",
    settingsButton: "settings button",
  },
  extras: {
    extraStuff,
  },
}

Expected Behavior

When calling setConfig to update the configuration, particularly the Authorization token in the headers, the new configuration should be applied immediately to ensure all subsequent requests use the updated Authorization token.

Here is how we are updating the auth token after we see a 401 from the server:

    const state = await BackgroundGeolocation.getState()
    await BackgroundGeolocation.setConfig({
      ...state,
      headers: {
        Authorization: `Bearer ${token.accessToken}`,
      },
    })

Actual Behavior

After calling setConfig to update the Authorization token in the headers, the old token continues to be used for subsequent requests. This indicates that the new configuration settings, particularly the updated Authorization token, are not being applied as expected.

Steps to Reproduce

  • Initialize the plugin with the initial configuration, including a specific Authorization token in the headers.
  • Use setConfig to update the headers, specifically changing the Authorization token.
  • Make a request that should utilize the updated Authorization token in the headers.
  • Observe that the old Authorization token is still being used, suggesting the new config was not applied.

Context

The goal is to dynamically update the Authorization token in the headers of the plugin configuration to ensure that all subsequent requests use the most current Authorization token for authentication. It's important to note that not all users are experiencing this issue, but a significant portion are, which suggests the possibility of intermittent caching issues with the token update process. Additionally, our application is utilizing Redux for state management, which might be relevant in diagnosing the issue. The inconsistent behavior raises the question of whether the library might sometimes have difficulties properly caching or updating the token.

@christocracy
Copy link
Member

is this issue for iOS or Android?

@Perronef5
Copy link
Author

Perronef5 commented Mar 28, 2024

is this issue for iOS or Android?

Mostly Android from what I can see but its definitely both iOS and Android.

We added a hack to reset the config if the state is not updated after setting the config. Hopefully that helps

@christocracy
Copy link
Member

Show me all your code where you're handling 401 Unauthorized and what you're doing there.

@Perronef5
Copy link
Author

Perronef5 commented Mar 29, 2024

const onHttp = useCallback(async (response: HttpEvent) => {
  if (response.status === 401) {
    /**
     * 401 is returned when the auth token has expired.
     * We need to re register and set the config again.
     */
     
     // HACK where we store the old auth token and try to force it into transistor since its not updating the token...
    const authToken = await getAsyncItem('mapping_auth_token')
    await BackgroundGeolocation.setConfig({
      headers: {
        Authorization: `Bearer ${authToken}`,
      },
    })
    Logger.breadcrumb('onHttp: 401 calling register')
    await register()
  }
}, [])
    export const register = async () => {
    const somethingWeNeed = await getAsyncItem('something_we_need')
  
    const sessionKey = await generateSessionKey()
  
    const { data: initResponse } = await axios.post(
      `/first_step_in_register`,
    )

    await axios.post(
      `/second_step_in_register`,
      {
        sessionKey
      },
    )

   const {data: token } =  await axios.post(
      `/third_step_in_register`,
      {
        sessionKey
      },
    )

    // Cache token to try to stuff in later
    await setAsyncItem('mapping_auth_token', token.accessToken)

    await BackgroundGeolocation.setConfig({
      ...state,
      headers: {
        Authorization: `Bearer ${token.accessToken}`,
      },
    })

    const newState = await BackgroundGeolocation.getState()
    const headers: TransistorHeader = newState?.headers as TransistorHeader
    if (headers?.Authorization !== `Bearer ${token.accessToken}`) {
      // Tokens did not match 
      await BackgroundGeolocation.reset({
        ...newState,
        headers: {
          Authorization: `Bearer ${token.accessToken}`,
        },
      })
    }
}

Update:

We have discovered that some how the http callbacks are multi threaded and our logic was stepping on itself. Can you confirm that the onHttp runs on a multi thread?

@Perronef5
Copy link
Author

@christocracy Any update here?

@christocracy
Copy link
Member

I don't like your use of reset() here and echoing back to the plugin its current state.

await BackgroundGeolocation.reset({
  ...newState,
  headers: {
    Authorization: `Bearer ${token.accessToken}`,
  },
})

Change it to this:

await BackgroundGeolocation.setConfig({
  headers: {
    Authorization: `Bearer ${token.accessToken}`,
  }
})

@Perronef5
Copy link
Author

@christocracy We only added that because the config was not being updated. What about the multi threaded part?

@Perronef5
Copy link
Author

@christocracy Any update?

@christocracy
Copy link
Member

I have no update

@Perronef5
Copy link
Author

Can you confirm that the onHttp callback is happening on a multi thread? It would help for that to be in the documentation if it is

@christocracy
Copy link
Member

callback is happening on a multi thread?

What do you mean by this? All event callbacks must be executed in the Main Thread (aka “UI thread”)

@Perronef5
Copy link
Author

callback is happening on a multi thread?

What do you mean by this? All event callbacks must be executed in the Main Thread (aka “UI thread”)

In our logs we see multiple instances of the http callback stepping on itself so we're thinking it was multi threaded on the native level

@christocracy
Copy link
Member

we see multiple instances of the http callback stepping on itself

what makes you think that?

this plug-in takes great care with multi-threading.

@Perronef5
Copy link
Author

we see multiple instances of the http callback stepping on itself

what makes you think that?

this plug-in takes great care with multi-threading.

Our register logic requires basic nonce / session key logic. In order to establish a session key we need the nonce and once we have a session key we can issue a JWT token. This a 3 step http request process where each http request is dependent off of the one that comes before it. You can imagine how multiple onHttp callbacks would cause this logic to invalidate itself.

It would help to make it clear to the consumers that the onHttp callbacks are being called on multiple threads.

Copy link

github-actions bot commented May 9, 2024

This issue is stale because it has been open for 30 days with no activity.

@github-actions github-actions bot added the stale label May 9, 2024
Copy link

This issue was closed because it has been inactive for 14 days since being marked as stale.

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

No branches or pull requests

2 participants