dart-eventsource icon indicating copy to clipboard operation
dart-eventsource copied to clipboard

Can't authenticate request

Open VittorioParagallo opened this issue 5 years ago • 5 comments

Is it possible to add the possibility to add authorization header? without it becomes useless in a secured environment :( i've been looking all around last two days and it looks like this feature is missing in the original eventsource api, but there are some implementations with polyfill

VittorioParagallo avatar Aug 25 '20 14:08 VittorioParagallo

What makes you think that it's not supported? The connect method accepts a header argument: https://github.com/stevenroose/dart-eventsource/blob/master/lib/eventsource.dart#L61

Though I'm not sure how well / if it works on the Web.

jonasbark avatar Oct 09 '20 11:10 jonasbark

Oh.. It has passed a bit of time, i don t really Remember what the point was. I m developing an app for both mobile and web. I ended up using Dio for mobile and wrote a js wrapper around polyfill to solve It. But it would be nice to use only 1 external library like eventsource. As i ll have some free time in november i ll test again eventsource package to see what was the situation with the features. (As i Remember It didn t work on web)

Il ven 9 ott 2020, 13:36 jonasbark [email protected] ha scritto:

What makes you think that it's not supported? The connect method accepts a header argument:

https://github.com/stevenroose/dart-eventsource/blob/master/lib/eventsource.dart#L61

Though I'm not sure how well / if it works on the Web.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/stevenroose/dart-eventsource/issues/16#issuecomment-706129870, or unsubscribe https://github.com/notifications/unsubscribe-auth/AN3UJSDIVGIWU4TXY5WGWDLSJ3YSZANCNFSM4QKWDENA .

--

Indirizzo istituzionale di posta elettronica degli studenti e dei laureati dell'Università degli Studi di TorinoOfficial  University of Turin email address for students and graduates 

VittorioParagallo avatar Oct 09 '20 17:10 VittorioParagallo

@VittorioParagallo Could you share your solution for Web? Having the same issue with Web implementation

tnovoselec avatar Oct 13 '21 07:10 tnovoselec

@VittorioParagallo can you please share how you managed to use Dio for SSE with authorization headers? - I am trying the same and it connects but doesn't stream the data

alexbvw avatar Feb 23 '22 02:02 alexbvw

I uploaded the code in my repo.

I guess that taking my code and following these steps can you easily to the solution. (my repo is a fully working app)

At first add this js file to the web folder of your flutter project(it's the polyfill): https://github.com/VittorioParagallo/swingcriminals_secretary/blob/master/web/eventsource.js It's the javascript code that does the work done.

Then we need to call that javascript object from dart. so i wrote all the needed code in the folder http_sse_tool

You can download the whole folder, it contains 5 files:

  • eventsource_commons.dart : groups the object needed by the other files
  • js_eventsource_polyfill.dart: it's a bridge class javascript<-> dart. It allows to instantiate the js object and call it's method.
  • eventsource_html.dart: wraps js_eventsource_polyfill.dart and exposes the sse functions so it is the class used for the web
  • eventsource_io.dart: wraps the package:restio/restio.dart file
  • eventsource_stub.dart: is the class with exactly the same methods of eventsource_html.dart and eventsource_io.dart. It is used as a stub to dinamically import the right class in case of web or app, here below i show you how.

Now that everything is set, is possible to develop the api, the one i did is rest_api_service.dart. In that file you can see the import:

`import 'package:swingcriminals_secretary/http_sse_tool/eventsource_stub.dart'
    // ignore: uri_does_not_exist
       if (dart.library.html) 'package:swingcriminals_secretary/http_sse_tool/eventsource_html.dart'
    // ignore: uri_does_not_exist
       if (dart.library.io) 'package:swingcriminals_secretary/http_sse_tool/eventsource_io.dart';`

So the import dinamically loads the right file wether is a web app or not. That's why a stub with all unimplemented closures was needed.

In the same file you can see the normal get (baseUrl is the webserver and url is the right part endpoint):

`

 Future<dynamic> get(String url) async {
 print("Called RestApiService:get($url)");
var responseJson;
try {
        final response = await http.get(baseUrl + url,
        headers: await AuthService().getRestHeaderWithToken());
        responseJson = _returnResponse(response);
     } on SocketException {
     throw FetchDataException('No Internet connection');
     }
return responseJson; 
 }

`

(_returnResponse check if it has data or error status, check at the end of the file).

This uses the conventional 'package:http/http.dart' and returns just one result. While the method sseGet:

  Future<EventSource> sseGet(String url) async {
     print("Called RestApiService:sseGet($url)");
    try {
      EventSource eventSource = await EventSource.connect(baseUrl + url,
          headers: await AuthService().getSseHeaderWithToken());
      return eventSource;
    } on SocketException {
      throw FetchDataException('No Internet connection');
    }
  }

Works the same way, but returns the EventSource object which is a stream, and continues to stream data till it's closed. You can check th method .getSseHeaderWithToken()) in the file auth_service.dart.

  Future<Map<String, String>> getSseHeaderWithToken() async {
    FirebaseUser user = await firebase.currentUser();
    var token = (await user.getIdToken()).token;
    return {
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive',
      'Accept': 'text/event-stream',
      'Authorization': 'Bearer $token',
    };
  }

It just prepares the header with the bearer token.

I hope it helps. I just tested again the code and it works great! Let me know your feedbacks.

VittorioParagallo avatar Aug 27 '22 03:08 VittorioParagallo