0

I'm building from scratch a flutter app for android, which is supposed to request a symfony REST API.

Using the http package, I can easily call the login route and store my JWT token using flutter secure storage.

But whenever I try and call another route using my stored token in the headers (Authentication), I get an "Invalid token" error.

What's weird is, if I paste the token stored in flutter secure store and pass it directly to my symfony app, well... It works.

Doing some digging, I found a few things about flutter/http lower-casing header names. But I don't think it's the case for header values.

I tried passing the lower-cased token value directly to my symfony API and surprise ! It fails. Well, looks like it's supposed to happen.

What am I dong wrong ?

pubsbec.yaml :

description: My super app
version: 1.0.0+1
publish_to: none

environment:
  sdk: '>=2.12.0 <3.0.0'

dependencies:
  flutter:
    sdk: flutter
  flutter_login: ^1.1.0
  cupertino_icons: ^1.0.2
  font_awesome_flutter: ^9.0.0
  intl: ^0.17.0
  # dummy package to test https://github.com/NearHuscarl/flutter_login/issues/35
  provider: ^5.0.0
  percent_indicator: ^3.0.1
  badges: ^2.0.1
  location: ^4.0.0
  geocoding: ^2.0.0
  camera:
  path_provider:
  path:
  thumbnails:
    git:
      url: https://github.com/divyanshub024/Flutter_Thumbnails.git
  video_player:
  esys_flutter_share:
  from_css_color: ^2.0.0
  http: ^0.13.3
  mapbox_gl: ^0.11.0
  firebase_storage: ^8.1.1
  cloud_firestore: ^2.2.1
  image_picker: ^0.8.0+1
  select_form_field: ^2.0.0
  dynamic_form: ^0.12.1
  test: ^1.16.5
  flutter_secure_storage: ^4.2.0

dev_dependencies:
  from_css_color: ^2.0.0  
  http: ^0.13.3

flutter:
  uses-material-design: true

  assets:
  - assets/images/maorie.png
  - assets/images/tiro.png
  - assets/images/coccinelle.jpg
  - assets/images/carotte1.png
  - assets/images/streetview.jpg
  - assets/images/streetview.png

  fonts:
    - family: Cabin
      fonts:
        - asset: assets/fonts/Cabin-Italic.ttf
          style: italic
        - asset: assets/fonts/Cabin-SemiBold.ttf
          weight: 600
        - asset: assets/fonts/Cabin-SemiBoldItalic.ttf
          weight: 600
          style: italic
        - asset: assets/fonts/Cabin-Bold.ttf
          weight: 700
        - asset: assets/fonts/Cabin-BoldItalic.ttf
          weight: 700
          style: italic

flutter_icons:
  android: "launcher_icon"
  ios: true
  image_path: "assets/icon/icon.png"

Getting my token in flutter app :

    return Future.delayed(loginTime).then((_) async {
      var url = Uri.parse('my_login_url');
      var response = await http.post(
        url,
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
        },
        body: jsonEncode(
            <String, String>{'email': data.name, 'password': data.password}),
      );
      print('Response status: ${response.statusCode}');
      print('Response body: ${response.body}');

      if (response.statusCode != 200) {
        return 'Email ou mot de passe incorrect';
      }

      await storage.write(key: "token", value: response.body);

      return null;
    });
  }

Desperately trying to use it :

  Future<String> get userToken async {
    var jwt = await _storage.read(key: "token");
    if (jwt == null) return "Votre compte n\' a pas pu être identifié.";
    return jwt;
  }

  Future<String> get campaignList async {
    String jwt = await userToken;

    print(jwt);

    var url = Uri.parse('my_api_url');
    var response = await http.get(url, headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Authorization': 'Bearer $jwt',
    });

    return response.body;
  }
......
        home: Scaffold(
          appBar: BaseAppBar(title: Text('Some Text'), appBar: AppBar()),
          body: Container(
            padding: EdgeInsets.fromLTRB(10, 10, 10, 0),
            height: 1000,
            width: double.maxFinite,
            child: FutureBuilder<String>(
                future: campaignList,
                builder:
                    (BuildContext context, AsyncSnapshot<String> snapshot) {
                  List<Widget> children;
                  if (snapshot.hasData) {
                    children = <Widget>[Text('${snapshot.data}')];
                  } else {
                    if (snapshot.hasError) {
                      children = <Widget>[Text('${snapshot.error}')];
                    } else {
                      children = <Widget>[Text('Loading')];
                    }
                  }
                  return Center(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: children,
                    ),
                  );
                }),
          ),
        ));
......

What I get :

JWT Invalid token

Symfony version : 4.4.23 Symfony http client config :

    http_client:
        default_options:
            max_redirects: 7
            http_version: '1.0'

The Symfony app is running behind nginx on a kubernetes cluster.

Brice Le Roux
  • 83
  • 1
  • 8

1 Answers1

0

Eventually this was quite dumb.

I was justing missing a jsonDecode on my api response... Works perfectly now.

I will keep this post in place just in case it can help somebody out.

Brice Le Roux
  • 83
  • 1
  • 8