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

feat(auth): enables custom auth flows #1444

Merged
merged 32 commits into from
May 11, 2022
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
0b521ee
feat(auth): enables custom auth flows
Mar 8, 2022
61c301c
updated code documentation
Mar 8, 2022
fc99080
removed validate call
Mar 8, 2022
1af2e20
removed validate call
Mar 8, 2022
c7a9ede
updated ios unit tests
Mar 8, 2022
3f29fa9
feat(authenticator): custom auth
Mar 18, 2022
d233794
fixes additionalInfo
Mar 18, 2022
27101a8
recovered stash changes
Mar 18, 2022
3f72d87
cleanup
Mar 21, 2022
0068faf
generated l10n
Mar 21, 2022
3be7a48
adds input resolver to example app
Mar 21, 2022
36c89c8
adds input resolver to example app
Mar 21, 2022
31d2864
fix unit test failure
Mar 21, 2022
e1243d9
corrected analystics pubspec conflict
Mar 22, 2022
22b30fc
cleanup
Mar 22, 2022
b412a53
correct doc error
Mar 22, 2022
d165f21
fixing analysis issues
Mar 22, 2022
2cd8616
removed extraneous dep
Mar 22, 2022
ea5367f
PR feedback and rebase
May 8, 2022
cb0ae66
updated FlutterSignInRequest.kt comments
May 8, 2022
1744fa9
pr suggestions and integ tests
May 8, 2022
6edf761
revert bad changes and fix test
May 8, 2022
72bccea
updated method channel
May 8, 2022
73fd0d1
sending additionalInfo as map
May 8, 2022
8a3d1c6
refined provision script and included in original script
May 9, 2022
1c79de2
cleaned up lambda dirs
May 9, 2022
29ede26
changed num back to in for passwordrequirement localizations
May 9, 2022
4a057f9
PR suggestions
May 9, 2022
51fb8b6
remove dupe flutter dependency key
May 9, 2022
cf3c35f
more PR suggestions
May 9, 2022
24d989a
removes dupe from authenticator_state
May 9, 2022
e0d98a8
changes additionalInfo to Map<String, String>?
May 10, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class AuthCategory {

Future<SignInResult> signIn({
required String username,
required String password,
String? password,
SignInOptions? options,
}) {
var request =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
/*
* 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.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 'package:amplify_authenticator/amplify_authenticator.dart';
haverchuck marked this conversation as resolved.
Show resolved Hide resolved
import 'package:flutter/material.dart';

import '../main.dart';

// A custom authenticator widget which enables the Custom Auth Flow for Amazon Cognito
// More information can be found (here)[https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-challenge.html]
//
// This authenticator provides custom views for Sign In and Confirm Sign In,
// but falls back on the standard views for all other states
//
// The custom confirmSignIn form assumes that the CreateAuthChallenge Lambda returns two values
// as part of the publicChallengeParameters object in the event.response:
//
// event.response.publicChallengeParameters = {};
// event.response.publicChallengeParameters.fieldTitle = 'Enter the secret code.'
// event.response.publicChallengeParameters.fieldHint = 'Check your email for the code we sent you.'
//
// [fieldTitle] is displayed in the input field's title.
// [fieldHint] is displayed in the input field's hint.

class AuthenticatorWithCustomAuthFlow extends StatelessWidget {
const AuthenticatorWithCustomAuthFlow({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Authenticator(
// If a builder method is provided the authenticator will
// use this to build the authenticator based on the current state.
//
// state is the current state of the authenticator. It contains the
// current auth step (sign in, sign out, etc.), the form data, and
// methods for updating this state.
//
// child is widget that would be displayed without the use of a custom
// builder. If currentStep is AuthenticatorStep.authenticated, this will
// be the material app. Otherwise this will be a prebuilt widget from
// amplify_authenticator to handle the current AuthenticatorStep
authenticatorBuilder: (context, state) {
switch (state.currentStep) {
case AuthenticatorStep.signIn:
return CustomSignInView(state: state);
case AuthenticatorStep.confirmSignInCustomAuth:
return CustomConfirmSignInView(state: state);
default:
// returning null will default to the prebuilt authenticator for
// all steps other than signIn and signUp
return null;
}
},
child: MaterialApp(
theme: ThemeData.from(
colorScheme: ColorScheme.fromSwatch(
primarySwatch: Colors.deepPurple,
backgroundColor: Colors.white,
brightness: Brightness.light,
),
),
darkTheme: ThemeData.from(
colorScheme: ColorScheme.fromSwatch(
primarySwatch: Colors.deepPurple,
backgroundColor: Colors.black,
brightness: Brightness.dark,
),
),
themeMode: ThemeMode.system,
debugShowCheckedModeBanner: false,
builder: Authenticator.builder(),
initialRoute: '/routeA',
routes: {
'/routeA': (BuildContext context) => const RouteA(),
'/routeB': (BuildContext context) => const RouteB(),
},
),
);
}
}

class CustomConfirmSignInView extends StatelessWidget {
const CustomConfirmSignInView({
Key? key,
required this.state,
}) : super(key: key);

final AuthenticatorState state;

@override
Widget build(BuildContext context) {
return SafeArea(
child: SingleChildScrollView(
child: AuthenticatorForm(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
children: [
// app logo (flutter logo used for example)
const Center(child: FlutterLogo(size: 100)),

// custom challenge field
// Field Title and Field Hint can be set within the Lambda Code.
ConfirmSignInFormField.customChallenge(
title: state.publicChallengeParams['fieldTitle'],
hintText: state.publicChallengeParams['fieldHint']),

// prebuilt sign up button from amplify_authenticator package
const ConfirmSignInCustomButton(),
const SizedBox(height: 16),
const Divider(),

// custom button to take the user to sign in
NavigateToSignInButton(state: state),
],
),
),
),
),
);
}
}

class CustomSignInView extends StatelessWidget {
const CustomSignInView({
Key? key,
required this.state,
}) : super(key: key);

final AuthenticatorState state;

@override
Widget build(BuildContext context) {
return SafeArea(
child: SingleChildScrollView(
child: AuthenticatorForm(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
children: [
// app logo (flutter logo used for example)
const Center(child: FlutterLogo(size: 100)),

// custom challenge field
SignInFormField.username(),

// custom challenge field
// SignInFormField.password(),

// prebuilt sign up button from amplify_authenticator package
const SignInButton(),

const SizedBox(height: 16),
const Divider(),

// custom button to take the user to sign in
NavigateToSignUpButton(state: state),
],
),
),
),
),
);
}
}

class NavigateToSignInButton extends StatelessWidget {
const NavigateToSignInButton({
Key? key,
required this.state,
}) : super(key: key);

final AuthenticatorState state;

@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
// abort sign in is called to make sure that the current auth flow is cancelled.
onPressed: state.abortSignIn,
child: const Text('Cancel Sign In'),
),
],
);
}
}

class NavigateToSignUpButton extends StatelessWidget {
const NavigateToSignUpButton({
Key? key,
required this.state,
}) : super(key: key);

final AuthenticatorState state;

@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Don\'t have an account?'),
TextButton(
onPressed: () => state.changeStep(
AuthenticatorStep.signUp,
),
child: const Text('Sign Up'),
),
],
);
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/*
* 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.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_authenticator/amplify_authenticator.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -225,7 +240,6 @@ class TermsAndConditionsCheckBox extends FormField<bool> {
if (value != true) {
return 'You must agree to the terms and conditions';
}
return null;
haverchuck marked this conversation as resolved.
Show resolved Hide resolved
},
initialValue: false,
builder: (FormFieldState<bool> state) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/*
* 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.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 'package:amplify_authenticator/amplify_authenticator.dart';
import 'package:amplify_authenticator_example/main.dart';
import 'package:flutter/material.dart';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,9 @@
"selectDialCode": "Select country",
"@selectDialCode": {
"description": "Label of the dial code selector modal"
},
"confirmSignInCustomAuth": "Custom Login Challenge",
"@confirmSignInCustomAuth": {
"description": "Label of the custom auth confirm sign in form"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
"backTo": "Regresar al {previousStep, select, signUp{registro}, signIn{inicio de sesión}, confirmSignUp{Confirmar registro}, confirmSignInMfa{Confirmar inicio de sesión} confirmSignInNewPassword{Confirmar inicio de sesión} sendCode{Enviar código} resetPassword{Restablecer contraseña} verifyUser{Verificar usuario} confirmVerifyUser{Confirmar verificación de usuario}}",
"signInWith": "Iniciar Sesión con {provider, select, google{Google} facebook{Facebook} amazon{Amazon} apple{Apple}}",
"us": "Estados Unidos",
"selectDialCode": "seleccionar país"
"selectDialCode": "seleccionar país",
"confirmSignInCustomAuth": "Título de formulario personalizado"
}
13 changes: 13 additions & 0 deletions packages/amplify_authenticator/example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_authenticator/amplify_authenticator.dart';
import 'package:amplify_authenticator_example/customization/authenticator_with_custom_auth_flow.dart';
import 'package:amplify_authenticator_example/customization/authenticator_with_custom_layout.dart';
import 'package:amplify_authenticator_example/customization/authenticator_with_onboarding.dart';
import 'package:amplify_authenticator_example/resolvers/localized_button_resolver.dart';
import 'package:amplify_authenticator_example/resolvers/localized_country_resolver.dart';
import 'package:amplify_authenticator_example/resolvers/localized_input_resolver.dart';
import 'package:amplify_authenticator_example/resolvers/localized_title_resolver.dart';
import 'package:amplify_flutter/amplify_flutter.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
Expand Down Expand Up @@ -69,6 +74,8 @@ class _MyAppState extends State<MyApp> {
const stringResolver = AuthStringResolver(
buttons: LocalizedButtonResolver(),
countries: LocalizedCountryResolver(),
titles: LocalizedTitleResolver(),
inputs: LocalizedInputResolver(),
);

// We wrap our MaterialApp in an Authenticator component. This component
Expand Down Expand Up @@ -190,6 +197,12 @@ class _MyAppState extends State<MyApp> {
// Widget build(BuildContext context) {
// return const AuthenticatorWithOnboarding();
// }

// Below is yet another example of a custom authenticator, with a widget to support Cognito's Custom Auth flow
// @override
// Widget build(BuildContext context) {
// return const AuthenticatorWithCustomAuthFlow();
// }
}

/// The screen which is shown once the user is logged in. We can use [SignOutButton]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/*
* 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.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 'package:amplify_authenticator/amplify_authenticator.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/*
* 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.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 'package:amplify_authenticator/amplify_authenticator.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
Expand Down
Loading