// Copyright 2019 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:appengine/appengine.dart';
import 'package:http/http.dart';
import 'package:meta/meta.dart';

import '../../cocoon_service.dart';
import '../foundation/providers.dart';
import '../model/google/token_info.dart';
import '../service/logging.dart';
import 'exceptions.dart';

/// Class capable of authenticating [HttpRequest]s for infra endpoints.
///
/// This class implements an ACL on a [RequestHandler] to ensure only automated
/// systems can access the endpoints.
///
/// If the request has the `Service-Account-Token` HTTP header, the token
/// will be authenticated as a LUCI bot. This token is validated against
/// Google Auth APIs.
///
/// If none of the above authentication methods yield an authenticated
/// request, then the request is unauthenticated, and any call to
/// [authenticate] will throw an [Unauthenticated] exception.
@immutable
class SwarmingAuthenticationProvider extends AuthenticationProvider {
  const SwarmingAuthenticationProvider({
    required super.config,
    super.clientContextProvider = Providers.serviceScopeContext,
    super.httpClientProvider = Providers.freshHttpClient,
  });

  /// Name of the header that LUCI requests will put their service account token.
  static const String kSwarmingTokenHeader = 'Service-Account-Token';

  /// Authenticates the specified [request] and returns the associated
  /// [AuthenticatedContext].
  ///
  /// See the class documentation on [AuthenticationProvider] for a discussion
  /// of the different types of authentication that are accepted.
  ///
  /// This will throw an [Unauthenticated] exception if the request is
  /// unauthenticated.
  @override
  Future<AuthenticatedContext> authenticate(HttpRequest request) async {
    final String? swarmingToken = request.headers.value(kSwarmingTokenHeader);

    final ClientContext clientContext = clientContextProvider();

    if (swarmingToken != null) {
      log.fine('Authenticating as swarming task');
      return await authenticateAccessToken(swarmingToken, clientContext: clientContext);
    }

    throw const Unauthenticated('Request rejected due to not from LUCI');
  }

  /// Authenticate [accessToken] against Google OAuth 2 API.
  ///
  /// Access tokens are the legacy authentication strategy for Google OAuth, where ID tokens
  /// are the new technique to use. LUCI auth only generates access tokens, and must be
  /// validated against a different endpoint. We only authenticate access tokens
  /// if they belong to a LUCI prod service account.
  ///
  /// If LUCI auth adds id tokens, we can switch to that and remove this.
  Future<AuthenticatedContext> authenticateAccessToken(
    String accessToken, {
    required ClientContext clientContext,
  }) async {
    // Authenticate as a signed-in Google account via OAuth id token.
    final Client client = httpClientProvider();
    try {
      log.fine('Sending token request to Google OAuth');
      final Response verifyTokenResponse = await client.get(
        Uri.https(
          'oauth2.googleapis.com',
          '/tokeninfo',
          <String, String>{
            'access_token': accessToken,
          },
        ),
      );

      if (verifyTokenResponse.statusCode != HttpStatus.ok) {
        /// Google Auth API returns a message in the response body explaining why
        /// the request failed. Such as "Invalid Token".
        final String body = verifyTokenResponse.body;
        log.warning('Token verification failed: ${verifyTokenResponse.statusCode}; $body');
        throw const Unauthenticated('Invalid access token');
      }

      TokenInfo token;
      try {
        token = TokenInfo.fromJson(json.decode(verifyTokenResponse.body) as Map<String, dynamic>);
      } on FormatException {
        log.warning('Failed to decode token JSON: ${verifyTokenResponse.body}');
        throw InternalServerError('Invalid JSON: "${verifyTokenResponse.body}"');
      }

      // Update is from Flutter LUCI builds
      if (token.email == Config.luciProdAccount) {
        return AuthenticatedContext(clientContext: clientContext);
      }

      if (token.email == Config.frobAccount) {
        log.fine('Authenticating as FRoB request');
        return AuthenticatedContext(clientContext: clientContext);
      }

      log.fine(verifyTokenResponse.body);
      log.warning('${token.email} is not allowed');
      throw Unauthenticated('${token.email} is not allowed');
    } finally {
      client.close();
    }
  }
}
