Amplify Storage.put succeeds on iOS, throws axios 403 forbidden error on android (React Native)

0

We have a react-native app that allows users to import images from a network camera and upload them to an S3 bucket.

We recently migrated from Expo Kit (SDK37) to Expo Bare (SDK43), RN Version 0.64.2

On iOS, both the release build and local debug builds work as expected and images are successfully uploaded to our S3 bucket.

However, on Android, we get an error saying that the signature doesn't match, and a 403 error from axios.

Here's what my setup looks like:

System:
    OS: macOS 12.2
    CPU: (8) arm64 Apple M1
    Memory: 85.48 MB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.13.1 - /usr/local/bin/node
    Yarn: 1.22.17 - /opt/homebrew/bin/yarn
    npm: 8.1.4 - /opt/homebrew/bin/npm
    Watchman: 2021.11.29.00 - /opt/homebrew/bin/watchman
  Browsers:
    Chrome: 98.0.4758.102
    Firefox: 97.0.1
    Safari: 15.3
  npmPackages:
    @BeeCorp/react-native-volume-control:  1.0.1 
    @apollo/client: ^3.4.16 => 3.5.9 
    @babel/core: ^7.12.9 => 7.17.5 
    @babel/plugin-proposal-class-properties: ^7.14.5 => 7.16.7 
    @fortawesome/fontawesome-svg-core: ^1.2.36 => 1.3.0 
    @fortawesome/free-solid-svg-icons: ^5.15.4 => 5.15.4 
    @fortawesome/react-native-fontawesome: ^0.2.7 => 0.2.7 
    @react-native-async-storage/async-storage: ~1.15.0 => 1.15.17 
    @react-native-community/datetimepicker: 3.5.2 => 3.5.2 
    @react-native-community/masked-view: ^0.1.11 => 0.1.11 
    @react-native-community/netinfo: ^8.0.0 => 8.0.0 
    @react-native-community/slider: 4.1.12 => 4.1.12 
    @react-native-firebase/app: ^14.1.0 => 14.5.0 
    @react-native-firebase/crashlytics: ^14.1.0 => 14.5.0 
    @react-native-picker/picker: ^2.2.1 => 2.2.1 
    @unimodules/core: ~7.2.0 => 7.2.0 
    amazon-cognito-identity-js: ^5.2.6 => 5.2.6 
    aws-amplify: ^4.3.14 => 4.3.14 
    aws-amplify-react-native: ^6.0.2 => 6.0.2 
    aws-appsync: ^4.1.4 => 4.1.4 
    aws-sdk: ^2.1013.0 => 2.1077.0 
    axios: ^0.23.0 => 0.23.0 
    babel-preset-react-native: ^4.0.1 => 4.0.1 
    buffer: ^6.0.3 => 6.0.3 
    expo: ^43.0.0 => 43.0.5 
    expo-asset: ~8.4.3 => 8.4.6 
    expo-av: ~10.1.3 => 10.1.3 
    expo-background-fetch: ~10.0.3 => 10.0.3 
    expo-barcode-scanner: ~11.1.2 => 11.1.2 
    expo-constants: ~12.1.3 => 12.1.3 
    expo-location: ~13.0.4 => 13.0.4 
    expo-secure-store: ~11.0.3 => 11.0.3 
    expo-sensors: ~11.0.3 => 11.0.3 
    expo-splash-screen: ~0.13.5 => 0.13.5 
    expo-status-bar: ~1.1.0 => 1.1.0 
    expo-task-manager: ~10.0.3 => 10.0.3 
    expo-updates: ~0.10.5 => 0.10.15 
    graphql-tag: ^2.12.5 => 2.12.6 
    jest-fetch-mock: ^3.0.3 => 3.0.3 
    jest-mock-axios: ^4.4.1 => 4.5.0 
    jetifier: ^2.0.0 => 2.0.0 
    jsdom: ^18.0.0 => 18.1.1 
    lodash: ^4.17.21 => 4.17.21 
    moment: ^2.29.1 => 2.29.1 
    react: 17.0.1 => 17.0.1 
    react-apollo: ^3.1.5 => 3.1.5 
    react-dom: 17.0.1 => 17.0.1 
    react-native: ^0.64.2 => 0.64.3 
    react-native-animatable: ^1.3.3 => 1.3.3 
    react-native-background-timer: ^2.4.1 => 2.4.1 
    react-native-battery: ^0.1.18 => 0.1.18 
    react-native-collapsible: ^1.6.0 => 1.6.0 
    react-native-config: ^1.4.5 => 1.4.5 
    react-native-copilot: ^2.5.1 => 2.5.1 
    react-native-doc-viewer: https://github.com/mikemeyer30/react-native-doc-viewer => 2.7.8 
    react-native-flash-message: ^0.2.0 => 0.2.1 
    react-native-geolocation-service: ^5.3.0-beta.3 => 5.3.0-beta.4 
    react-native-gesture-handler: ~1.10.2 => 1.10.3 
    react-native-get-random-values: ^1.7.0 => 1.7.2 
    react-native-image-picker: ^4.1.2 => 4.7.3 
    react-native-keyboard-aware-scroll-view: ^0.9.4 => 0.9.5 
    react-native-keyboard-spacer: git+https://github.com/datso/react-native-keyboard-spacer.git => 0.4.1 
    react-native-material-design: ^0.3.7 => 0.3.7 
    react-native-material-dropdown-v2: ^0.11.1 => 0.11.1 
    react-native-paper: ^4.10.0 => 4.11.2 
    react-native-queue: https://github.com/mikemeyer30/react-native-queue-asyncstorage => 1.2.1 
    react-native-reanimated: ~2.2.0 => 2.2.4 
    react-native-safe-area-context: 3.3.2 => 3.3.2 
    react-native-screens: ~3.8.0 => 3.8.0 
    react-native-svg: 12.1.1 => 12.1.1 
    react-native-torch: ^1.2.0 => 1.2.0 
    react-native-vector-icons: ^9.0.0 => 9.1.0 
    react-native-web: 0.17.1 => 0.17.1 
    rn-swipe-button: ^1.3.6 => 1.3.6 
    tree-util: ^1.0.6 => 1.0.6 
    uuid: ^8.3.2 => 8.3.2 
  npmGlobalPackages:
    @aws-amplify/cli: 7.6.20
    expo-cli: 5.1.1
    n: 8.0.1
    npm: 8.1.4
    react-native-cli: 2.0.1
    yarn: 1.22.17

We've been troubleshooting for a little over a week now with no success, so any pointers are greatly appreciated. If there's any additional information I can provide, I'd be happy to do so. Thanks in advance

1 Answer
0

Hello,

since the requests go through on iOS but fail on Android I recommend to investigate and rule out potential reasons why the "signature doesn't match" error is thrown.

One of the more common potential reasons for this error is clock skew / system clock offset.

Making requests to AWS services requires that you use a timestamp, which represents the time at which you make the request. For security purposes, AWS requires a valid timestamp in the request in order to mitigate the risk of third-party request interception and unauthorized replay. AWS allows a five minute variance on the timestamp — in other words, the timestamp doesn’t need to be exact. However, on mobile devices, it is possible for the time to be significantly out of sync. In these situations, calls to AWS will fail due to the timestamp being outside the allowable range.

Can you please double check the system time on your Android device for potential offset? To fix potential offset you can use the setClockOffset function:

import { DateUtils } from "@aws-amplify/core"

DateUtils.setClockOffset(CLOCK_OFFSET);

see https://aws-amplify.github.io/amplify-js/api/globals.html#dateutils

AWS
answered 2 years ago
  • Hello Alexander, thanks for the suggestion;

    So first, I used DateUtils.getDateWithClockOffset() to see what date time it would log, and it seems that it is correct; it logged:

    2022-02-28T22:29:20.234Z
    

    And I'm on EST, so on my device it was:

    2022-02-28 17:29:20
    

    at the time of invocation.

    From the error log that dumps out, I pull the timestamp from the 'StringToSign' attribute, and it reads: 2022-02-28 22:29:21Z

    And when I log DateUtils.getClockOffset(), it shows 0 milli offset, so it would appear the offset isn't the issue, unless I'm missing something...

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions