blob: ba1170a8ffbd0f302320e9bcbd4de9e80cea82c0 [file] [log] [blame]
// 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:io';
import 'package:cocoon_service/src/request_handling/authentication.dart' show AuthenticatedContext;
import 'package:cocoon_service/src/request_handling/exceptions.dart';
import 'package:cocoon_service/src/request_handling/pubsub_authentication.dart';
import 'package:cocoon_service/src/service/config.dart';
import 'package:http/http.dart' as http;
import 'package:http/testing.dart';
import 'package:test/test.dart';
import '../src/datastore/fake_config.dart';
import '../src/request_handling/fake_authentication.dart';
import '../src/request_handling/fake_http.dart';
void main() {
group('PubsubAuthenticationProvider', () {
late FakeConfig config;
late FakeClientContext clientContext;
late FakeHttpRequest request;
late PubsubAuthenticationProvider auth;
late MockClient httpClient;
setUp(() {
config = FakeConfig();
clientContext = FakeClientContext();
request = FakeHttpRequest();
auth = PubsubAuthenticationProvider(
config: config,
clientContextProvider: () => clientContext,
httpClientProvider: () => httpClient,
);
});
for (String allowedAccount in Config.allowedPubsubServiceAccounts) {
test('auth succeeds for $allowedAccount', () async {
httpClient = MockClient(
(_) async => http.Response(
_generateTokenResponse(allowedAccount),
HttpStatus.ok,
headers: <String, String>{
HttpHeaders.contentTypeHeader: 'application/json',
},
),
);
auth = PubsubAuthenticationProvider(
config: config,
clientContextProvider: () => clientContext,
httpClientProvider: () => httpClient,
);
request.headers.add(HttpHeaders.authorizationHeader, 'Bearer token');
final AuthenticatedContext result = await auth.authenticate(request);
expect(result.clientContext, same(clientContext));
});
}
test('auth fails with unauthorized service account', () async {
httpClient = MockClient(
(_) async => http.Response(
_generateTokenResponse('unauthorized@gmail.com'),
HttpStatus.ok,
headers: <String, String>{
HttpHeaders.contentTypeHeader: 'application/json',
},
),
);
auth = PubsubAuthenticationProvider(
config: config,
clientContextProvider: () => clientContext,
httpClientProvider: () => httpClient,
);
request.headers.add(HttpHeaders.authorizationHeader, 'Bearer token');
expect(auth.authenticate(request), throwsA(isA<Unauthenticated>()));
});
test('auth fails with invalid token', () async {
httpClient = MockClient(
(_) async => http.Response(
'Invalid token',
HttpStatus.unauthorized,
headers: <String, String>{
HttpHeaders.contentTypeHeader: 'application/json',
},
),
);
auth = PubsubAuthenticationProvider(
config: config,
clientContextProvider: () => clientContext,
httpClientProvider: () => httpClient,
);
request.headers.add(HttpHeaders.authorizationHeader, 'Bearer token');
expect(auth.authenticate(request), throwsA(isA<FormatException>()));
});
test('auth fails with expired token', () async {
httpClient = MockClient(
(_) async => http.Response(
_generateTokenResponse(
Config.allowedPubsubServiceAccounts.first,
expiresIn: -1,
),
HttpStatus.ok,
headers: <String, String>{
HttpHeaders.contentTypeHeader: 'application/json',
},
),
);
auth = PubsubAuthenticationProvider(
config: config,
clientContextProvider: () => clientContext,
httpClientProvider: () => httpClient,
);
request.headers.add(HttpHeaders.authorizationHeader, 'Bearer token');
expect(auth.authenticate(request), throwsA(isA<Unauthenticated>()));
});
});
}
/// Return Google's OAuth response.
String _generateTokenResponse(
String email, {
int expiresIn = 123,
}) {
return '''{
"issued_to": "456",
"audience": "https://flutter-dashboard.appspot.com/api/luci-status-handler",
"user_id": "789",
"expires_in": $expiresIn,
"email": "$email",
"verified_email": true,
"issuer": "https://accounts.google.com",
"issued_at": 412321
}''';
}