Skip to content

Commit

Permalink
feat(auth,api): cognito user pools auth provider & auth mode for API …
Browse files Browse the repository at this point in the history
…HTTP requests (#1913)
  • Loading branch information
Travis Sheppard committed Oct 19, 2022
1 parent 9fb8431 commit 3e9f921
Show file tree
Hide file tree
Showing 6 changed files with 255 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,15 @@ Future<http.BaseRequest> authorizeHttpRequest(http.BaseRequest request,
return authorizedRequest.httpRequest;
case APIAuthorizationType.function:
case APIAuthorizationType.oidc:
case APIAuthorizationType.userPools:
throw UnimplementedError('${authType.name} not implemented.');
case APIAuthorizationType.userPools:
final authProvider = _validateAuthProvider(
authProviderRepo.getAuthProvider(authType.authProviderToken),
authType,
);
final authorizedRequest =
await authProvider.authorizeRequest(_httpToAWSRequest(request));
return authorizedRequest.httpRequest;
case APIAuthorizationType.none:
return request;
}
Expand Down
34 changes: 29 additions & 5 deletions packages/api/amplify_api/test/authorize_http_request_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,19 @@ void main() {
final authProviderRepo = AmplifyAuthProviderRepository();

setUpAll(() {
authProviderRepo.registerAuthProvider(
authProviderRepo
..registerAuthProvider(
APIAuthorizationType.apiKey.authProviderToken,
AppSyncApiKeyAuthProvider());
authProviderRepo.registerAuthProvider(
APIAuthorizationType.iam.authProviderToken, TestIamAuthProvider());
AppSyncApiKeyAuthProvider(),
)
..registerAuthProvider(
APIAuthorizationType.iam.authProviderToken,
TestIamAuthProvider(),
)
..registerAuthProvider(
APIAuthorizationType.userPools.authProviderToken,
TestTokenAuthProvider(),
);
});

group('authorizeHttpRequest', () {
Expand Down Expand Up @@ -132,7 +140,23 @@ void main() {
throwsA(isA<ApiException>()));
});

test('authorizes with Cognito User Pools auth mode', () {}, skip: true);
test('authorizes with Cognito User Pools auth mode', () async {
const endpointConfig = AWSApiConfig(
authorizationType: APIAuthorizationType.userPools,
endpoint: _gqlEndpoint,
endpointType: EndpointType.graphQL,
region: _region);
final inputRequest = _generateTestRequest(endpointConfig.endpoint);
final authorizedRequest = await authorizeHttpRequest(
inputRequest,
endpointConfig: endpointConfig,
authProviderRepo: authProviderRepo,
);
expect(
authorizedRequest.headers[AWSHeaders.authorization],
testAccessToken,
);
});

test('authorizes with OIDC auth mode', () {}, skip: true);

Expand Down
9 changes: 9 additions & 0 deletions packages/api/amplify_api/test/util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import 'package:aws_signature_v4/aws_signature_v4.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:http/http.dart' as http;

const testAccessToken = 'test-access-token-123';

class TestIamAuthProvider extends AWSIamAmplifyAuthProvider {
@override
Future<AWSCredentials> retrieve() async {
Expand All @@ -43,6 +45,13 @@ class TestIamAuthProvider extends AWSIamAmplifyAuthProvider {
}
}

class TestTokenAuthProvider extends TokenAmplifyAuthProvider {
@override
Future<String> getLatestAuthToken() async {
return testAccessToken;
}
}

void validateSignedRequest(http.BaseRequest request) {
const userAgentHeader =
zIsWeb ? AWSHeaders.amzUserAgent : AWSHeaders.userAgent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import 'package:amplify_auth_cognito_dart/src/sdk/cognito_identity_provider.dart
import 'package:amplify_auth_cognito_dart/src/sdk/sdk_bridge.dart';
import 'package:amplify_auth_cognito_dart/src/state/state.dart';
import 'package:amplify_auth_cognito_dart/src/util/cognito_iam_auth_provider.dart';
import 'package:amplify_auth_cognito_dart/src/util/cognito_user_pools_auth_provider.dart';
import 'package:amplify_core/amplify_core.dart';
import 'package:amplify_secure_storage_dart/amplify_secure_storage_dart.dart';
import 'package:collection/collection.dart';
Expand Down Expand Up @@ -261,10 +262,15 @@ class AmplifyAuthCognitoDart extends AuthPluginInterface<

// Register auth providers to provide auth functionality to other plugins
// without requiring other plugins to call `Amplify.Auth...` directly.
authProviderRepo.registerAuthProvider(
APIAuthorizationType.iam.authProviderToken,
CognitoIamAuthProvider(),
);
authProviderRepo
..registerAuthProvider(
APIAuthorizationType.iam.authProviderToken,
CognitoIamAuthProvider(),
)
..registerAuthProvider(
APIAuthorizationType.userPools.authProviderToken,
CognitoUserPoolsAuthProvider(),
);

if (_stateMachine.getOrCreate(AuthStateMachine.type).currentState.type !=
AuthStateType.notConfigured) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import 'dart:async';

import 'package:amplify_auth_cognito_dart/amplify_auth_cognito_dart.dart';
import 'package:amplify_core/amplify_core.dart';
import 'package:meta/meta.dart';

/// [AmplifyAuthProvider] implementation that adds access token to request headers.
@internal
class CognitoUserPoolsAuthProvider extends TokenAmplifyAuthProvider {
/// Get access token from `Amplify.Auth.fetchAuthSession()`.
@override
Future<String> getLatestAuthToken() async {
final authSession =
await Amplify.Auth.fetchAuthSession() as CognitoAuthSession;
final token = authSession.userPoolTokens?.accessToken.raw;
if (token == null) {
throw const AuthException(
'Unable to fetch access token while authorizing with Cognito User Pools.',
);
}
return token;
}
}
Loading

0 comments on commit 3e9f921

Please sign in to comment.