Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(googleapis_auth): rename AuthProvider to AuthEndpoints #1755

Merged
merged 4 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 22 additions & 22 deletions packages/shorebird_cli/lib/src/auth/auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import 'package:http/http.dart' as http;
import 'package:jwt/jwt.dart';
import 'package:path/path.dart' as p;
import 'package:scoped/scoped.dart';
import 'package:shorebird_cli/src/auth/providers/providers.dart';
import 'package:shorebird_cli/src/auth/endpoints/endpoints.dart';
import 'package:shorebird_cli/src/command.dart';
import 'package:shorebird_cli/src/command_runner.dart';
import 'package:shorebird_cli/src/http_client/http_client.dart';
Expand All @@ -30,15 +30,15 @@ const googleJwtIssuer = 'https://accounts.google.com';
const microsoftJwtIssuerPrefix = 'https://login.microsoftonline.com/';

typedef ObtainAccessCredentials = Future<oauth2.AccessCredentials> Function(
oauth2.AuthProvider authProvider,
oauth2.AuthEndpoints authEndpoints,
oauth2.ClientId clientId,
List<String> scopes,
http.Client client,
void Function(String) userPrompt,
);

typedef RefreshCredentials = Future<oauth2.AccessCredentials> Function(
oauth2.AuthProvider authProvider,
oauth2.AuthEndpoints authEndpoints,
oauth2.ClientId clientId,
oauth2.AccessCredentials credentials,
http.Client client,
Expand Down Expand Up @@ -98,7 +98,7 @@ class AuthenticatedClient extends http.BaseClient {
if (credentials == null) {
final token = _token!;
final jwt = Jwt.parse(token);
final authProvider = jwt.authProvider;
final authProvider = jwt.authEndpoints;
credentials = _credentials = await _refreshCredentials(
authProvider,
authProvider.clientId,
Expand All @@ -115,7 +115,7 @@ class AuthenticatedClient extends http.BaseClient {

if (credentials.accessToken.hasExpired && credentials.idToken != null) {
final jwt = Jwt.parse(credentials.idToken!);
final authProvider = jwt.authProvider;
final authProvider = jwt.authEndpoints;

credentials = _credentials = await _refreshCredentials(
authProvider,
Expand Down Expand Up @@ -176,15 +176,15 @@ class Auth {
}

Future<AccessCredentials> loginCI(
oauth2.AuthProvider authProvider, {
oauth2.AuthEndpoints authEndpoints, {
required void Function(String) prompt,
}) async {
final client = http.Client();
try {
final credentials = await _obtainAccessCredentials(
authProvider,
authProvider.clientId,
authProvider.scopes,
authEndpoints,
authEndpoints.clientId,
authEndpoints.scopes,
client,
prompt,
);
Expand All @@ -206,7 +206,7 @@ class Auth {
}

Future<void> login(
oauth2.AuthProvider authProvider, {
oauth2.AuthEndpoints authEndpoints, {
required void Function(String) prompt,
}) async {
if (_credentials != null) {
Expand All @@ -216,9 +216,9 @@ class Auth {
final client = http.Client();
try {
_credentials = await _obtainAccessCredentials(
authProvider,
authProvider.clientId,
authProvider.scopes,
authEndpoints,
authEndpoints.clientId,
authEndpoints.scopes,
client,
prompt,
);
Expand Down Expand Up @@ -326,22 +326,22 @@ class UserNotFoundException implements Exception {
final String email;
}

extension OauthAuthProvider on Jwt {
oauth2.AuthProvider get authProvider {
extension OauthAuthEndpoints on Jwt {
oauth2.AuthEndpoints get authEndpoints {
if (payload.iss == googleJwtIssuer) {
return oauth2.GoogleAuthProvider();
return oauth2.GoogleAuthEndpoints();
} else if (payload.iss.startsWith(microsoftJwtIssuerPrefix)) {
return MicrosoftAuthProvider();
return MicrosoftAuthEndpoints();
}

throw Exception('Unknown jwt issuer: ${payload.iss}');
}
}

extension OauthValues on oauth2.AuthProvider {
extension OauthValues on oauth2.AuthEndpoints {
oauth2.ClientId get clientId {
switch (runtimeType) {
case oauth2.GoogleAuthProvider:
case oauth2.GoogleAuthEndpoints:
return oauth2.ClientId(
/// Shorebird CLI's OAuth 2.0 identifier for GCP,
'''523302233293-eia5antm0tgvek240t46orctktiabrek.apps.googleusercontent.com''',
Expand All @@ -358,7 +358,7 @@ extension OauthValues on oauth2.AuthProvider {
/// For more info see: https://developers.google.com/identity/protocols/oauth2/native-app
'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',
);
case MicrosoftAuthProvider:
case MicrosoftAuthEndpoints:
return oauth2.ClientId(
/// Shorebird CLI's OAuth 2.0 identifier for Azure/Entra.
'0ff83897-ec85-4642-a250-48d5f595137c',
Expand All @@ -370,9 +370,9 @@ extension OauthValues on oauth2.AuthProvider {

List<String> get scopes {
switch (runtimeType) {
case oauth2.GoogleAuthProvider:
case oauth2.GoogleAuthEndpoints:
return ['openid', 'https://www.googleapis.com/auth/userinfo.email'];
case MicrosoftAuthProvider:
case MicrosoftAuthEndpoints:
return ['openid'];
}

Expand Down
2 changes: 2 additions & 0 deletions packages/shorebird_cli/lib/src/auth/endpoints/endpoints.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export 'package:googleapis_auth/auth_io.dart' show GoogleAuthEndpoints;
export 'microsoft_auth_endpoints.dart';
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:googleapis_auth/googleapis_auth.dart';

/// Endpoints for OAuth authentication with Azure/Entra/Microsoft.
class MicrosoftAuthProvider extends AuthProvider {
class MicrosoftAuthEndpoints extends AuthEndpoints {
@override
Uri get authorizationEndpoint =>
Uri.https('login.microsoftonline.com', 'common/oauth2/v2.0/authorize');
Expand Down
2 changes: 0 additions & 2 deletions packages/shorebird_cli/lib/src/auth/providers/providers.dart

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class LoginCiCommand extends ShorebirdCommand {
final AccessCredentials credentials;

try {
credentials = await auth.loginCI(GoogleAuthProvider(), prompt: prompt);
credentials = await auth.loginCI(GoogleAuthEndpoints(), prompt: prompt);
} on UserNotFoundException catch (error) {
logger
..err(
Expand Down
3 changes: 2 additions & 1 deletion packages/shorebird_cli/lib/src/commands/login_command.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:googleapis_auth/auth_io.dart';
import 'package:mason_logger/mason_logger.dart';
import 'package:shorebird_cli/src/auth/auth.dart';
import 'package:shorebird_cli/src/auth/endpoints/endpoints.dart';
import 'package:shorebird_cli/src/command.dart';
import 'package:shorebird_cli/src/logger.dart';

Expand All @@ -18,7 +19,7 @@ class LoginCommand extends ShorebirdCommand {
@override
Future<int> run() async {
try {
await auth.login(GoogleAuthProvider(), prompt: prompt);
await auth.login(GoogleAuthEndpoints(), prompt: prompt);
} on UserAlreadyLoggedInException catch (error) {
logger
..info('You are already logged in as <${error.email}>.')
Expand Down
60 changes: 30 additions & 30 deletions packages/shorebird_cli/test/src/auth/auth_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import 'package:path/path.dart' as p;
import 'package:platform/platform.dart';
import 'package:scoped/scoped.dart';
import 'package:shorebird_cli/src/auth/auth.dart';
import 'package:shorebird_cli/src/auth/providers/providers.dart';
import 'package:shorebird_cli/src/auth/endpoints/endpoints.dart';
import 'package:shorebird_cli/src/command_runner.dart';
import 'package:shorebird_cli/src/http_client/http_client.dart';
import 'package:shorebird_cli/src/logger.dart';
Expand All @@ -22,7 +22,7 @@ import 'package:test/test.dart';
import '../fakes.dart';
import '../mocks.dart';

class FakeProvider extends oauth2.AuthProvider {
class FakeAuthEndpoints extends oauth2.AuthEndpoints {
@override
Uri get authorizationEndpoint => Uri.https('example.com');

Expand Down Expand Up @@ -52,17 +52,17 @@ void main() {
});

group('OauthValues', () {
final fakeAuthProvider = FakeProvider();
final fakeAuthEndpoints = FakeAuthEndpoints();

group('clientId', () {
test('throws UnsupportedError when provider is not a known type', () {
expect(() => fakeAuthProvider.clientId, throwsUnsupportedError);
test('throws UnsupportedError when endpoints is not a known type', () {
expect(() => fakeAuthEndpoints.clientId, throwsUnsupportedError);
});
});

group('scopes', () {
test('throws UnsupportedError when provider is not a known type', () {
expect(() => fakeAuthProvider.scopes, throwsUnsupportedError);
test('throws UnsupportedError when endpoints is not a known type', () {
expect(() => fakeAuthEndpoints.scopes, throwsUnsupportedError);
});
});
});
Expand All @@ -86,7 +86,7 @@ void main() {
});
});

group('OauthAuthProvider', () {
group('OauthAuthEndpoints', () {
late Jwt jwt;
late JwtPayload payload;

Expand All @@ -99,14 +99,14 @@ void main() {
);
});

group('authProvider', () {
group('authEndpoints', () {
group('when issuer is login.microsoft.online', () {
setUp(() {
when(() => payload.iss).thenReturn(microsoftJwtIssuer);
});

test('returns AuthProvider.microsoft', () {
expect(jwt.authProvider, isA<MicrosoftAuthProvider>());
test('returns MicrosoftAuthEndpoints', () {
expect(jwt.authEndpoints, isA<MicrosoftAuthEndpoints>());
});
});

Expand All @@ -115,8 +115,8 @@ void main() {
when(() => payload.iss).thenReturn(googleJwtIssuer);
});

test('returns AuthProvider.google', () {
expect(jwt.authProvider, isA<GoogleAuthProvider>());
test('returns GoogleAuthEndpoints', () {
expect(jwt.authEndpoints, isA<GoogleAuthEndpoints>());
});
});

Expand All @@ -127,7 +127,7 @@ void main() {

test('throws exception', () {
expect(
() => jwt.authProvider,
() => jwt.authEndpoints,
throwsA(
isA<Exception>().having(
(e) => e.toString(),
Expand All @@ -152,8 +152,8 @@ void main() {
);
const refreshToken = '';
const scopes = <String>[];
final googleAuthProvider = GoogleAuthProvider();
final microsoftAuthProvider = MicrosoftAuthProvider();
final googleAuthEndpoints = GoogleAuthEndpoints();
final microsoftAuthEndpoints = MicrosoftAuthEndpoints();
final accessToken = oauth2.AccessToken(
'Bearer',
'accessToken',
Expand Down Expand Up @@ -198,7 +198,7 @@ void main() {
return codePushClient;
},
obtainAccessCredentials:
(authProvider, clientId, scopes, client, userPrompt) async {
(authEndpoints, clientId, scopes, client, userPrompt) async {
return accessCredentials;
},
),
Expand Down Expand Up @@ -235,7 +235,7 @@ void main() {
token: token,
httpClient: httpClient,
refreshCredentials:
(authProvider, clientId, credentials, client) async =>
(authEndpoints, clientId, credentials, client) async =>
accessCredentials,
),
returnsNormally,
Expand All @@ -258,7 +258,7 @@ void main() {
httpClient: httpClient,
onRefreshCredentials: onRefreshCredentialsCalls.add,
refreshCredentials:
(authProvider, clientId, credentials, client) async =>
(authEndpoints, clientId, credentials, client) async =>
accessCredentials,
);

Expand Down Expand Up @@ -292,7 +292,7 @@ void main() {
httpClient: httpClient,
onRefreshCredentials: onRefreshCredentialsCalls.add,
refreshCredentials:
(authProvider, clientId, credentials, client) async =>
(authEndpoints, clientId, credentials, client) async =>
accessCredentials,
);

Expand Down Expand Up @@ -342,7 +342,7 @@ void main() {
httpClient: httpClient,
onRefreshCredentials: onRefreshCredentialsCalls.add,
refreshCredentials:
(authProvider, clientId, credentials, client) async =>
(authEndpoints, clientId, credentials, client) async =>
accessCredentials,
);

Expand Down Expand Up @@ -400,7 +400,7 @@ void main() {
HttpStatus.ok,
),
);
await auth.login(googleAuthProvider, prompt: (_) {});
await auth.login(googleAuthEndpoints, prompt: (_) {});
final client = auth.client;
expect(client, isA<http.Client>());
expect(client, isA<AuthenticatedClient>());
Expand Down Expand Up @@ -445,18 +445,18 @@ void main() {
group('login', () {
test('should set the email when claims are valid and current user exists',
() async {
await auth.login(googleAuthProvider, prompt: (_) {});
await auth.login(googleAuthEndpoints, prompt: (_) {});
expect(auth.email, email);
expect(auth.isAuthenticated, isTrue);
expect(buildAuth().email, email);
expect(buildAuth().isAuthenticated, isTrue);
});

group('with a custom auth provider', () {
group('with custom auth endpoints', () {
test(
'''should set the email when claims are valid and current user exists''',
() async {
await auth.login(microsoftAuthProvider, prompt: (_) {});
await auth.login(microsoftAuthEndpoints, prompt: (_) {});
expect(auth.email, email);
expect(auth.isAuthenticated, isTrue);
expect(buildAuth().email, email);
Expand All @@ -470,7 +470,7 @@ void main() {
auth = buildAuth();

await expectLater(
auth.login(googleAuthProvider, prompt: (_) {}),
auth.login(googleAuthEndpoints, prompt: (_) {}),
throwsA(isA<UserAlreadyLoggedInException>()),
);

Expand All @@ -483,7 +483,7 @@ void main() {
.thenAnswer((_) async => null);

await expectLater(
auth.login(googleAuthProvider, prompt: (_) {}),
auth.login(googleAuthEndpoints, prompt: (_) {}),
throwsA(isA<UserNotFoundException>()),
);

Expand All @@ -505,7 +505,7 @@ void main() {
'returns credentials and does not set the email or cache credentials',
() async {
await expectLater(
auth.loginCI(googleAuthProvider, prompt: (_) {}),
auth.loginCI(googleAuthEndpoints, prompt: (_) {}),
completion(equals(accessCredentials)),
);
expect(auth.email, isNull);
Expand All @@ -522,7 +522,7 @@ void main() {
).thenAnswer((_) async => null);

await expectLater(
auth.loginCI(googleAuthProvider, prompt: (_) {}),
auth.loginCI(googleAuthEndpoints, prompt: (_) {}),
throwsA(isA<UserNotFoundException>()),
);

Expand All @@ -532,7 +532,7 @@ void main() {

group('logout', () {
test('clears session and wipes state', () async {
await auth.login(googleAuthProvider, prompt: (_) {});
await auth.login(googleAuthEndpoints, prompt: (_) {});
expect(auth.email, email);
expect(auth.isAuthenticated, isTrue);

Expand Down
Loading
Loading