Access token created in Flutter is wrong and fails with Invalid Compact JWS

Hi! I am developing a mobile app and a web app for my university.

My backend is made in NodeJS and I authenticate my users with this code:

import { auth } from 'express-oauth2-jwt-bearer';

export const validateAuthorizationMiddleware = auth({
    audience: `https://${process.env.AUTH0_DOMAIN}/api/v2/`,
    issuerBaseURL: `https://${process.env.AUTH0_DOMAIN}/`,
});

My web app is made in React and it is in production, so backend and web app work right.

I started to develop my mobile app in Flutter and I have a problem with the access token when I send the token to my backend server, it says ‘Invalid Compact JWS’ (it also happened developing my react app when I use wrong credentials, but I think that it is not the case now).
I think it happen because I use “demo” scheme, but I don’t know how to use other scheme (I understand that demo is not for production)

This is my AuthProvider

class AuthProvider extends ChangeNotifier {
  late Auth0 _auth0;
  late String _scheme;

  bool _loading = true;
  Credentials? _credentials;
  UserProfile? _profile;

  AuthProvider(String domain, String clientId, String scheme) {
    _auth0 = Auth0(domain, clientId);
    _scheme = scheme;
    _checkCredentials();
  }

  bool get loading => _loading;
  Credentials? get credentials => _credentials;
  UserProfile? get profile => _profile;
  String get token => _credentials?.accessToken ?? '';
  String get userId => _profile?.sub ?? '';

  void _checkCredentials() async {
    if (await _auth0.credentialsManager.hasValidCredentials()) {
      _credentials = await _auth0.credentialsManager.credentials();
      if (_credentials != null) _retrieveProfile(_credentials!.accessToken);
    }
    _loading = false;
    notifyListeners();
  }

  void login() async {
    _credentials = await _auth0.webAuthentication(scheme: _scheme).login();
    notifyListeners();
  }

  void logout() async {
    await _auth0.webAuthentication(scheme: _scheme).logout();
    _credentials = null;
    notifyListeners();
  }

  void _retrieveProfile(String accessToken) async {
    _profile = await _auth0.api.userProfile(accessToken: accessToken);
  }
}

and this is the token that is sent to my backend (it has a different format of the token I have in my web app):

Hey there @developers.deve!

Thanks for the detailed description of the issue you’re seeing, very helpful! What do you get if you decode the access token from your flutter app at jwt.io?

Thank you for your answer!

It says that payload is not a valid JSON Object (it is an empty string). Then I have the following headers:

{
  "alg": "dir",
  "enc": "A256GCM",
  "iss": "https://dev-xxx.us.auth0.com/"
}

Of course, I’m happy to help!

It doesn’t look like you are passing an audience param in your Flutter code - If that’s the case then you’ll receive an opaque access token. Some more on the audience param and opaque tokens can be found here.

The audience used in your Flutter app should be the same as the audience specified on your backend - A note on that: It looks like you have the management API set as your audience in your backend. I assume you are protecting your own API? In that case the audience should be whatever name (API identifier) you gave your API when registering it in Auth0.

Keep us posted!

You are mi hero! :smile: I found that I can send the audience value when I do the login, now I have a payload in my access token! I was looking for this value in the library contract but I didn’t find it, thanks!

void login() async {
    _credentials = await _auth0.webAuthentication(scheme: _scheme).login(
      audience: _audience,
    );
    notifyListeners();
  }

Thank you for your advice about audience value.

About scheme, should I use demo? I don’t know if I can get another

1 Like

That’s great news, happy to hear!

Regarding the scheme - I believe you can use whatever you want, we use demo because https causes issues with Android and deep linking. See:

Hope this helps!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.