Skip to content

Commit 2256175

Browse files
authored
feat(auth): enables custom auth flows (#1444)
* feat(auth): enables custom auth flows
1 parent a5be8de commit 2256175

File tree

79 files changed

+1595
-195
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+1595
-195
lines changed

packages/amplify/amplify_flutter/lib/src/categories/amplify_auth_category.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ class AuthCategory {
9494

9595
Future<SignInResult> signIn({
9696
required String username,
97-
required String password,
97+
String? password,
9898
SignInOptions? options,
9999
}) {
100100
var request =
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
/*
2+
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
import 'package:amplify_authenticator/amplify_authenticator.dart';
17+
import 'package:flutter/material.dart';
18+
19+
import '../main.dart';
20+
21+
// A custom authenticator widget which enables the Custom Auth Flow for Amazon Cognito
22+
// More information can be found (here)[https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-challenge.html]
23+
//
24+
// This authenticator provides custom views for Sign In and Confirm Sign In,
25+
// but falls back on the standard views for all other states
26+
//
27+
// The custom confirmSignIn form assumes that the CreateAuthChallenge Lambda returns two values
28+
// as part of the publicChallengeParameters object in the event.response:
29+
//
30+
// event.response.publicChallengeParameters = {};
31+
// event.response.publicChallengeParameters.fieldTitle = 'Enter the secret code.'
32+
// event.response.publicChallengeParameters.fieldHint = 'Check your email for the code we sent you.'
33+
//
34+
// [fieldTitle] is displayed in the input field's title.
35+
// [fieldHint] is displayed in the input field's hint.
36+
37+
class AuthenticatorWithCustomAuthFlow extends StatelessWidget {
38+
const AuthenticatorWithCustomAuthFlow({Key? key}) : super(key: key);
39+
40+
@override
41+
Widget build(BuildContext context) {
42+
return Authenticator(
43+
// If a builder method is provided the authenticator will
44+
// use this to build the authenticator based on the current state.
45+
//
46+
// state is the current state of the authenticator. It contains the
47+
// current auth step (sign in, sign out, etc.), the form data, and
48+
// methods for updating this state.
49+
//
50+
// child is widget that would be displayed without the use of a custom
51+
// builder. If currentStep is AuthenticatorStep.authenticated, this will
52+
// be the material app. Otherwise this will be a prebuilt widget from
53+
// amplify_authenticator to handle the current AuthenticatorStep
54+
authenticatorBuilder: (context, state) {
55+
switch (state.currentStep) {
56+
case AuthenticatorStep.signIn:
57+
return CustomSignInView(state: state);
58+
case AuthenticatorStep.confirmSignInCustomAuth:
59+
return CustomConfirmSignInView(state: state);
60+
default:
61+
// returning null will default to the prebuilt authenticator for
62+
// all steps other than signIn and signUp
63+
return null;
64+
}
65+
},
66+
child: MaterialApp(
67+
theme: ThemeData.from(
68+
colorScheme: ColorScheme.fromSwatch(
69+
primarySwatch: Colors.deepPurple,
70+
backgroundColor: Colors.white,
71+
brightness: Brightness.light,
72+
),
73+
),
74+
darkTheme: ThemeData.from(
75+
colorScheme: ColorScheme.fromSwatch(
76+
primarySwatch: Colors.deepPurple,
77+
backgroundColor: Colors.black,
78+
brightness: Brightness.dark,
79+
),
80+
),
81+
themeMode: ThemeMode.system,
82+
debugShowCheckedModeBanner: false,
83+
builder: Authenticator.builder(),
84+
initialRoute: '/routeA',
85+
routes: {
86+
'/routeA': (BuildContext context) => const RouteA(),
87+
'/routeB': (BuildContext context) => const RouteB(),
88+
},
89+
),
90+
);
91+
}
92+
}
93+
94+
class CustomConfirmSignInView extends StatelessWidget {
95+
const CustomConfirmSignInView({
96+
Key? key,
97+
required this.state,
98+
}) : super(key: key);
99+
100+
final AuthenticatorState state;
101+
102+
@override
103+
Widget build(BuildContext context) {
104+
return SafeArea(
105+
child: SingleChildScrollView(
106+
child: AuthenticatorForm(
107+
child: Padding(
108+
padding: const EdgeInsets.symmetric(horizontal: 16),
109+
child: Column(
110+
children: [
111+
// app logo (flutter logo used for example)
112+
const Center(child: FlutterLogo(size: 100)),
113+
114+
// custom challenge field
115+
// Field Title and Field Hint can be set within the Lambda Code.
116+
ConfirmSignInFormField.customChallenge(
117+
title: state.publicChallengeParams['fieldTitle'],
118+
hintText: state.publicChallengeParams['fieldHint']),
119+
120+
// prebuilt sign up button from amplify_authenticator package
121+
const ConfirmSignInCustomButton(),
122+
const SizedBox(height: 16),
123+
const Divider(),
124+
125+
// custom button to take the user to sign in
126+
NavigateToSignInButton(state: state),
127+
],
128+
),
129+
),
130+
),
131+
),
132+
);
133+
}
134+
}
135+
136+
class CustomSignInView extends StatelessWidget {
137+
const CustomSignInView({
138+
Key? key,
139+
required this.state,
140+
}) : super(key: key);
141+
142+
final AuthenticatorState state;
143+
144+
@override
145+
Widget build(BuildContext context) {
146+
return SafeArea(
147+
child: SingleChildScrollView(
148+
child: AuthenticatorForm(
149+
child: Padding(
150+
padding: const EdgeInsets.symmetric(horizontal: 16),
151+
child: Column(
152+
children: [
153+
// app logo (flutter logo used for example)
154+
const Center(child: FlutterLogo(size: 100)),
155+
156+
// custom challenge field
157+
SignInFormField.username(),
158+
159+
// custom challenge field
160+
// SignInFormField.password(),
161+
162+
// prebuilt sign up button from amplify_authenticator package
163+
const SignInButton(),
164+
165+
const SizedBox(height: 16),
166+
const Divider(),
167+
168+
// custom button to take the user to sign in
169+
NavigateToSignUpButton(state: state),
170+
],
171+
),
172+
),
173+
),
174+
),
175+
);
176+
}
177+
}
178+
179+
class NavigateToSignInButton extends StatelessWidget {
180+
const NavigateToSignInButton({
181+
Key? key,
182+
required this.state,
183+
}) : super(key: key);
184+
185+
final AuthenticatorState state;
186+
187+
@override
188+
Widget build(BuildContext context) {
189+
return Row(
190+
mainAxisAlignment: MainAxisAlignment.center,
191+
children: [
192+
TextButton(
193+
// abort sign in is called to make sure that the current auth flow is cancelled.
194+
onPressed: state.abortSignIn,
195+
child: const Text('Cancel Sign In'),
196+
),
197+
],
198+
);
199+
}
200+
}
201+
202+
class NavigateToSignUpButton extends StatelessWidget {
203+
const NavigateToSignUpButton({
204+
Key? key,
205+
required this.state,
206+
}) : super(key: key);
207+
208+
final AuthenticatorState state;
209+
210+
@override
211+
Widget build(BuildContext context) {
212+
return Row(
213+
mainAxisAlignment: MainAxisAlignment.center,
214+
children: [
215+
const Text('Don\'t have an account?'),
216+
TextButton(
217+
onPressed: () => state.changeStep(
218+
AuthenticatorStep.signUp,
219+
),
220+
child: const Text('Sign Up'),
221+
),
222+
],
223+
);
224+
}
225+
}

packages/amplify_authenticator/example/lib/customization/authenticator_with_custom_layout.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
/*
2+
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
116
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
217
import 'package:amplify_authenticator/amplify_authenticator.dart';
318
import 'package:flutter/material.dart';

packages/amplify_authenticator/example/lib/customization/authenticator_with_onboarding.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
/*
2+
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
116
import 'package:amplify_authenticator/amplify_authenticator.dart';
217
import 'package:amplify_authenticator_example/main.dart';
318
import 'package:flutter/material.dart';

packages/amplify_authenticator/example/lib/l10n/amplify_en.arb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,5 +86,9 @@
8686
"selectDialCode": "Select country",
8787
"@selectDialCode": {
8888
"description": "Label of the dial code selector modal"
89+
},
90+
"confirmSignInCustomAuth": "Custom Login Challenge",
91+
"@confirmSignInCustomAuth": {
92+
"description": "Label of the custom auth confirm sign in form"
8993
}
9094
}

packages/amplify_authenticator/example/lib/l10n/amplify_es.arb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@
1616
"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}}",
1717
"signInWith": "Iniciar Sesión con {provider, select, google{Google} facebook{Facebook} amazon{Amazon} apple{Apple}}",
1818
"us": "Estados Unidos",
19-
"selectDialCode": "seleccionar país"
19+
"selectDialCode": "seleccionar país",
20+
"confirmSignInCustomAuth": "Título de formulario personalizado"
2021
}

packages/amplify_authenticator/example/lib/main.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
22
import 'package:amplify_authenticator/amplify_authenticator.dart';
3+
import 'package:amplify_authenticator_example/customization/authenticator_with_custom_auth_flow.dart';
4+
import 'package:amplify_authenticator_example/customization/authenticator_with_custom_layout.dart';
5+
import 'package:amplify_authenticator_example/customization/authenticator_with_onboarding.dart';
36
import 'package:amplify_authenticator_example/resolvers/localized_button_resolver.dart';
47
import 'package:amplify_authenticator_example/resolvers/localized_country_resolver.dart';
8+
import 'package:amplify_authenticator_example/resolvers/localized_input_resolver.dart';
9+
import 'package:amplify_authenticator_example/resolvers/localized_title_resolver.dart';
510
import 'package:amplify_flutter/amplify_flutter.dart';
611
import 'package:flutter/material.dart';
712
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@@ -69,6 +74,8 @@ class _MyAppState extends State<MyApp> {
6974
const stringResolver = AuthStringResolver(
7075
buttons: LocalizedButtonResolver(),
7176
countries: LocalizedCountryResolver(),
77+
titles: LocalizedTitleResolver(),
78+
inputs: LocalizedInputResolver(),
7279
);
7380

7481
// We wrap our MaterialApp in an Authenticator component. This component
@@ -190,6 +197,12 @@ class _MyAppState extends State<MyApp> {
190197
// Widget build(BuildContext context) {
191198
// return const AuthenticatorWithOnboarding();
192199
// }
200+
201+
// Below is yet another example of a custom authenticator, with a widget to support Cognito's Custom Auth flow
202+
// @override
203+
// Widget build(BuildContext context) {
204+
// return const AuthenticatorWithCustomAuthFlow();
205+
// }
193206
}
194207

195208
/// The screen which is shown once the user is logged in. We can use [SignOutButton]

packages/amplify_authenticator/example/lib/resolvers/localized_button_resolver.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
/*
2+
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
116
import 'package:amplify_authenticator/amplify_authenticator.dart';
217
import 'package:flutter/material.dart';
318
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

packages/amplify_authenticator/example/lib/resolvers/localized_country_resolver.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
/*
2+
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
116
import 'package:amplify_authenticator/amplify_authenticator.dart';
217
import 'package:flutter/material.dart';
318
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

0 commit comments

Comments
 (0)