arnemolland / sigv4

Dart library for signing AWS requests with Signature Version 4
MIT License
17 stars 23 forks source link

[WEB] How to use .sign extension with Dio #19

Open BartusZak opened 3 years ago

BartusZak commented 3 years ago

I'm trying to use Dio Interceptors with sigv4 library, but it calculates signature wrongly and returns: InvalidSignatureError

  final Dio _dioClient = new Dio();
  _dioClient.options.baseUrl = serverUrl;
  _dioClient.interceptors
      .add(InterceptorsWrapper(onRequest: (RequestOptions options) async {
    options.sign(_sigV4Client);
    options.headers['Content-Type'] = 'application/json; charset=utf-8';
  })); 

Doing it directly (withoute Interceptors) works. But why?

      final request = _sigV4Client.request(
        url,
        headers: {
          HttpHeaders.contentTypeHeader: 'application/json',
        },
      );

      final test2 = await Dio().get(url,
          options: Options(headers: {
            'Content-Type': 'application/json',
            ...request.headers
          }));

When itercpectors dont work I'm trying to do something like that:

      final test2 = await _dioClient.get(url,
          options: RequestOptions().sign(_sigV4Client));

But it does not work. It does not return any error even.

arnemolland commented 3 years ago

Hi @BartusZak!

In your first snippet, you're adding headers after calculating the signature. All headers to be sent with a signed request must be included in the signature, which is why it's invalid. In your second snippet, it's working because you've already specified the Content-Type header before signing, meaning it's included in the signature and therefore it doesn't matter that you specify it once more in the Options constructor.

The last snippet is bad error handling, it's not checking for null/empty paths (which is needed) so I'm opening a PR to fix that.

Thanks for the report, hope that helps!

BartusZak commented 3 years ago

Hey @arnemolland!

I have updated to sigv4 to s4.1.2 and got:

Expected a value of type 'String', but got one of type 'bool'

I have no idea where it comes from.

It appears directly after running app:

Launching lib\main.dart on Chrome in debug mode...
lib\main.dart:1
Debug service listening on ws://127.0.0.1:52609/ueauNImWsbs=/ws
Running with unsound null safety
For more information see https://dart.dev/null-safety/unsound-null-safety
Connecting to VM Service at ws://127.0.0.1:52609/ueauNImWsbs=/ws
onTransition -- bloc: ApplicationBloc, transition: Transition { currentState: InitialApplicationState(), event: ApplicationLoadEvent, nextState: ApplicationLoadingState() }
Expected a value of type 'String', but got one of type 'bool'

I will try later, one more time with .sign() and let you know.

I really do apreaciate it!

BartusZak commented 3 years ago

Hey @arnemolland,

I tried one more time and it did not work.

Added Content-Type and it was not included in request headers.

  final Dio _dioClient = new Dio();
  _dioClient.options.baseUrl = serverUrl;

    final request = _sigV4Client.request(
      url,
      headers: {
        HttpHeaders.contentTypeHeader: 'application/json',
      },
    );

    final response = await _dioClient.get(url,
        options: Options(
            headers: {'Content-Type': 'application/json', ...request.headers})); // WORKS
  final Dio _dioClient2 = new Dio();
    _dioClient2.options.baseUrl = serverUrl;
    _dioClient2.interceptors
        .add(InterceptorsWrapper(onRequest: (RequestOptions options) async {
      options.headers['Content-Type'] = 'application/json';
      options.sign(_sigV4Client);
    }));

    final response2 = await _dioClient2.get(url); // ERROR

Differences in fetch: image