Почему мое приложение Flutter не может получить доступ к развернутому сервису Django в Google Cloud Run?

Я разрабатываю приложение flutter и бэкенд Django. У меня есть бэкенд с докером и двойная настройка: Локально я использую docker-compose с google cloud proxy. Для развертывания я использую DockerFile и действия на github. При локальном развертывании к сервису можно получить доступ через браузер и приложение flutter. Однако когда сервис находится на Cloud Run, доступ к нему возможен через браузер, но не через приложение Flutter. В настройках Cloud Run сервису разрешен неавторизованный доступ. В настройках Django разрешено взаимодействие без csrf:

CSRF_TRUSTED_ORIGINS = ["https://xxxxxx"]
CORS_ALLOW_ALL_ORIGINS = True

представление, которое возвращает неавторизованное, - это google login, который получает запрос на вход с Firebase idToken:


@api_view(["POST"])
@authentication_classes([])
@permission_classes([AllowAny])
@csrf_exempt
def google_login(request) -> Response:

Мой бэкенд django оставляет эти журналы в Cloud Run

:textPayload: "Unauthorized: /api/v1/google-login/"

Я реализовал JWT-аутентификацию, которую еще нужно протестировать, но она работает, когда я запускаю сервер на своей машине. Значит, что-то не так с запросом, но я не понимаю, что именно. Браузер может получить доступ к развернутой облачной службе запуска, как я уже говорил. При сканировании журналов Network я вижу, что он отправляет запрос с csrftoken и не вижу больше никаких вещей, которые мне, возможно, нужно добавить в Flutter

request.accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
accept-encoding:
gzip, deflate, br, zstd
accept-language:
en-GB,en-US;q=0.9,en;q=0.8
cookie:
csrftoken=xxxxxx
priority:
u=0, i
referer:
https://xxxxxxx
sec-ch-ua:
"Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"
sec-ch-ua-arch:
"arm"
sec-ch-ua-bitness:
"64"
sec-ch-ua-full-version-list:
"Chromium";v="130.0.6723.117", "Google Chrome";v="130.0.6723.117", "Not?A_Brand";v="99.0.0.0"
sec-ch-ua-mobile:
?0
sec-ch-ua-model:
""
sec-ch-ua-platform:
"macOS"
sec-ch-ua-platform-version:
"15.1.0"

Код флаттера:
Страница входа

BlocListener<FirebaseAuthCubit, FirebaseAuthState>(
        listener: (context, firebaseAuthState) async {
          if (firebaseAuthState is FirebaseAuthSuccess) {
            context
                .read<UserSessionCubit>()
                .googleLogin(firebaseAuthState.idToken, _deviceLocale!);
          }
        },

Метод кубита:

Future<void> googleLogin(String googleIdToken, String languageCode) async {
    emit(UserSessionInLoading());

    try {
      final UserSessionModel loginResponse = await _loginApiClient.googleLogin(googleIdToken, languageCode);
      emit(UserSessionSuccess(loginResponse.accessToken, loginResponse.refreshToken, loginResponse.userId, loginResponse.languageCode));
    } catch (e) {
      emit(UserSessionFailure(e.toString()));
    }
  }

Метод клиента:

Future<UserSessionModel> googleLogin(String googleIdToken, String languageCode) async {
        final Uri loginRequest = debug ? Uri.http(baseUrl, '/api/v1/google-login/') : Uri.https(baseUrl, '/api/v1/google-login/');
    
        final response = await _dioClient.post(
            loginRequest.toString(),
            data: jsonEncode({'googleIdToken': googleIdToken, 'languageCode': languageCode}),
            options: Options(headers: {'Content-Type': 'application/json'}),
            // headers: {'Content-Type': 'application/json'},
          );
    
        if (response.statusCode == 200) {
          log(response.data.toString());
          final jsonResponse = response.data;
          return UserSessionModel.fromJson(jsonResponse);
        } else {
          log(response.data.toString());
          throw LoginRequestFailure();
        }
      }
    
      void log(String message) {
        if (debug) {
          print(message);
        }
      }
Вернуться на верх