Skip to content

Commit 40c5df9

Browse files
authored
feat(auth): add support for cognito oidc parameters in managed login (#6442)
* feat(auth): add support for cognito oidc parameters in managed login * fix failing test build * fix format errors * fix test build * fix build * add formatting changes * add missing generated file * update tests * address review comments
1 parent c0d47df commit 40c5df9

File tree

13 files changed

+366
-48
lines changed

13 files changed

+366
-48
lines changed

packages/auth/amplify_auth_cognito/example/integration_test/native_auth_bridge_test.dart

Lines changed: 119 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,65 @@ void main() {
5353
dependencyManager
5454
..addInstance<NativeAuthBridge>(
5555
MockNativeAuthBridge(
56-
signInWithUrl: expectAsync4((
57-
argUrl,
58-
argCallbackurlscheme,
59-
argPreferprivatesession,
60-
argBrowserpackagename,
61-
) async {
62-
expect(argUrl, contains(mockConfig.auth?.oauth?.domain));
63-
expect(argCallbackurlscheme, testUrlScheme);
64-
expect(argPreferprivatesession, isFalse);
65-
expect(argBrowserpackagename, browserPackage);
56+
signInWithUrl: expectAsync1((argSignInOut) async {
57+
expect(
58+
argSignInOut.url,
59+
contains(mockConfig.auth?.oauth?.domain),
60+
);
61+
expect(argSignInOut.callbackurlscheme, testUrlScheme);
62+
expect(argSignInOut.preferprivatesession, isFalse);
63+
expect(argSignInOut.browserPackageName, browserPackage);
64+
return {'code': 'code', 'state': 'state'};
65+
}),
66+
),
67+
)
68+
..addInstance<Dispatcher<AuthEvent, AuthState>>(
69+
const MockDispatcher(),
70+
);
71+
await platform.signIn(options: options);
72+
});
73+
74+
asyncTest('signInWithUrl with OIDC parameters', (_) async {
75+
const options = CognitoSignInWithWebUIPluginOptions(
76+
isPreferPrivateSession: false,
77+
browserPackageName: browserPackage,
78+
nonce: 'nonce',
79+
language: 'en',
80+
loginHint: 'username',
81+
prompt: [
82+
CognitoSignInWithWebUIPrompt.login,
83+
CognitoSignInWithWebUIPrompt.consent,
84+
],
85+
resource: 'myapp://',
86+
);
87+
dependencyManager
88+
..addInstance<NativeAuthBridge>(
89+
MockNativeAuthBridge(
90+
signInWithUrl: expectAsync1((argSignInOut) async {
91+
expect(
92+
argSignInOut.url,
93+
contains(mockConfig.auth?.oauth?.domain),
94+
);
95+
expect(argSignInOut.callbackurlscheme, testUrlScheme);
96+
expect(argSignInOut.preferprivatesession, isFalse);
97+
expect(argSignInOut.browserPackageName, browserPackage);
98+
expect(argSignInOut.nonce, 'nonce');
99+
expect(argSignInOut.language, 'en');
100+
expect(argSignInOut.loginHint, 'username');
101+
expect(argSignInOut.prompt, isNotNull);
102+
expect(
103+
argSignInOut.prompt?.contains(
104+
CognitoSignInWithWebUIPrompt.login.value,
105+
),
106+
isTrue,
107+
);
108+
expect(
109+
argSignInOut.prompt?.contains(
110+
CognitoSignInWithWebUIPrompt.consent.value,
111+
),
112+
isTrue,
113+
);
114+
expect(argSignInOut.resource, 'myapp://');
66115
return {'code': 'code', 'state': 'state'};
67116
}),
68117
),
@@ -81,16 +130,14 @@ void main() {
81130
dependencyManager
82131
..addInstance<NativeAuthBridge>(
83132
MockNativeAuthBridge(
84-
signOutWithUrl: expectAsync4((
85-
argUrl,
86-
argCallbackurlscheme,
87-
argPreferprivatesession,
88-
argBrowserpackagename,
89-
) async {
90-
expect(argUrl, contains(mockConfig.auth?.oauth?.domain));
91-
expect(argCallbackurlscheme, testUrlScheme);
92-
expect(argPreferprivatesession, isFalse);
93-
expect(argBrowserpackagename, browserPackage);
133+
signOutWithUrl: expectAsync1((argSignInOut) async {
134+
expect(
135+
argSignInOut.url,
136+
contains(mockConfig.auth?.oauth?.domain),
137+
);
138+
expect(argSignInOut.callbackurlscheme, testUrlScheme);
139+
expect(argSignInOut.preferprivatesession, isFalse);
140+
expect(argSignInOut.browserPackageName, browserPackage);
94141
}),
95142
),
96143
)
@@ -103,13 +150,31 @@ void main() {
103150
);
104151
}
105152

106-
typedef SignInOutFn<T> =
107-
Future<T> Function(
108-
String argUrl,
109-
String argCallbackurlscheme,
110-
bool argPreferprivatesession,
111-
String? argBrowserpackagename,
112-
);
153+
class SignInOut {
154+
SignInOut(
155+
this.url,
156+
this.callbackurlscheme,
157+
this.preferprivatesession,
158+
this.browserPackageName,
159+
this.nonce,
160+
this.language,
161+
this.loginHint,
162+
this.prompt,
163+
this.resource,
164+
);
165+
166+
String url = '';
167+
String callbackurlscheme = '';
168+
bool preferprivatesession = false;
169+
String? browserPackageName;
170+
String? nonce;
171+
String? language;
172+
String? loginHint;
173+
List<String>? prompt;
174+
String? resource;
175+
}
176+
177+
typedef SignInOutFn<T> = Future<T> Function(SignInOut signInOut);
113178

114179
class MockNativeAuthBridge extends Fake implements NativeAuthBridge {
115180
MockNativeAuthBridge({
@@ -127,12 +192,24 @@ class MockNativeAuthBridge extends Fake implements NativeAuthBridge {
127192
String argCallbackurlscheme,
128193
bool argPreferprivatesession,
129194
String? argBrowserpackagename,
195+
String? argNonce,
196+
String? argLanguage,
197+
String? argLoginHint,
198+
List<String>? argPrompt,
199+
String? argResource,
130200
) async {
131201
return _signInWithUrl?.call(
132-
argUrl,
133-
argCallbackurlscheme,
134-
argPreferprivatesession,
135-
argBrowserpackagename,
202+
SignInOut(
203+
argUrl,
204+
argCallbackurlscheme,
205+
argPreferprivatesession,
206+
argBrowserpackagename,
207+
argNonce,
208+
argLanguage,
209+
argLoginHint,
210+
argPrompt,
211+
argResource,
212+
),
136213
) ??
137214
(throw UnimplementedError());
138215
}
@@ -145,10 +222,17 @@ class MockNativeAuthBridge extends Fake implements NativeAuthBridge {
145222
String? argBrowserpackagename,
146223
) async {
147224
return _signOutWithUrl?.call(
148-
argUrl,
149-
argCallbackurlscheme,
150-
argPreferprivatesession,
151-
argBrowserpackagename,
225+
SignInOut(
226+
argUrl,
227+
argCallbackurlscheme,
228+
argPreferprivatesession,
229+
argBrowserpackagename,
230+
null,
231+
null,
232+
null,
233+
null,
234+
null,
235+
),
152236
) ??
153237
(throw UnimplementedError());
154238
}

packages/auth/amplify_auth_cognito/lib/src/flows/hosted_ui/hosted_ui_platform_flutter.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ class HostedUiPlatformImpl extends io.HostedUiPlatformImpl {
9494
signInRedirectUri.scheme,
9595
options.isPreferPrivateSession,
9696
options.browserPackageName,
97+
options.nonce,
98+
options.language,
99+
options.loginHint,
100+
options.prompt?.map((obj) => obj.value).toList(),
101+
options.resource,
97102
);
98103
dispatcher
99104
.dispatch(

packages/auth/amplify_auth_cognito/lib/src/native_auth_plugin.g.dart

Lines changed: 17 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/auth/amplify_auth_cognito/test/hosted_ui_platform_flutter_test.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ final class ThrowingNativeBridge extends Fake implements NativeAuthBridge {
8383
String arg_callbackUrlScheme,
8484
bool arg_preferPrivateSession,
8585
String? arg_browserPackageName,
86+
String? arg_nonce,
87+
String? arg_language,
88+
String? arg_loginHint,
89+
List<String>? arg_prompt,
90+
String? arg_resource,
8691
) async {
8792
throw PlatformException(code: 'CANCELLED');
8893
}

packages/auth/amplify_auth_cognito_dart/lib/amplify_auth_cognito_dart.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export 'src/model/signin/cognito_confirm_sign_in_plugin_options.dart';
4040
export 'src/model/signin/cognito_sign_in_plugin_options.dart';
4141
export 'src/model/signin/cognito_sign_in_result.dart';
4242
export 'src/model/signin/cognito_sign_in_with_web_ui_plugin_options.dart';
43+
export 'src/model/signin/cognito_sign_in_with_web_ui_plugin_options_prompt.dart';
4344
export 'src/model/signout/cognito_sign_out_plugin_options.dart';
4445
export 'src/model/signout/cognito_sign_out_result.dart';
4546
export 'src/model/signup/cognito_confirm_sign_up_plugin_options.dart';

packages/auth/amplify_auth_cognito_dart/lib/src/flows/hosted_ui/hosted_ui_config.dart

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
import 'package:amplify_auth_cognito_dart/amplify_auth_cognito_dart.dart';
45
import 'package:amplify_core/amplify_core.dart';
56
// ignore: implementation_imports
67
import 'package:amplify_core/src/config/amplify_outputs/auth/oauth_outputs.dart';
@@ -26,7 +27,10 @@ extension HostedUiConfig on OAuthOutputs {
2627
/// References:
2728
/// - https://docs.aws.amazon.com/cognito/latest/developerguide/authorization-endpoint.html
2829
/// - https://docs.aws.amazon.com/cognito/latest/developerguide/login-endpoint.html
29-
Uri signInUri([AuthProvider? provider]) {
30+
Uri signInUri([
31+
AuthProvider? provider,
32+
CognitoSignInWithWebUIPluginOptions? options,
33+
]) {
3034
Uri baseUri;
3135
// ignore: invalid_use_of_internal_member
3236
if (this.signInUri != null) {
@@ -35,9 +39,20 @@ extension HostedUiConfig on OAuthOutputs {
3539
} else {
3640
baseUri = _webDomain.replace(path: '/oauth2/authorize');
3741
}
42+
43+
final nonce = options?.nonce;
44+
final language = options?.language;
45+
final loginHint = options?.loginHint;
46+
final prompt = options?.prompt?.map((obj) => obj.value).toList().join(' ');
47+
final resource = options?.resource;
3848
return baseUri.replace(
3949
queryParameters: <String, String>{
4050
if (provider != null) 'identity_provider': provider.uriParameter,
51+
if (nonce != null) 'nonce': nonce,
52+
if (language != null) 'lang': language,
53+
if (loginHint != null) 'login_hint': loginHint,
54+
if (prompt != null) 'prompt': prompt,
55+
if (resource != null) 'resource': resource,
4156
// ignore: invalid_use_of_internal_member
4257
...?signInUriQueryParameters,
4358
},

packages/auth/amplify_auth_cognito_dart/lib/src/flows/hosted_ui/hosted_ui_platform.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,11 @@ abstract class HostedUiPlatform implements Closeable {
102102
@protected
103103
@visibleForTesting
104104
@nonVirtual
105-
Future<Uri> getSignInUri({Uri? redirectUri, AuthProvider? provider}) async {
105+
Future<Uri> getSignInUri({
106+
Uri? redirectUri,
107+
AuthProvider? provider,
108+
CognitoSignInWithWebUIPluginOptions? options,
109+
}) async {
106110
final state = generateState();
107111
final codeVerifier = createCodeVerifier();
108112

@@ -124,6 +128,7 @@ abstract class HostedUiPlatform implements Closeable {
124128
codeVerifier: codeVerifier,
125129
httpClient: httpClient,
126130
provider: provider,
131+
options: options,
127132
);
128133
final uri = _authCodeGrant!.getAuthorizationUrl(
129134
redirectUri ?? signInRedirectUri,
@@ -162,12 +167,13 @@ abstract class HostedUiPlatform implements Closeable {
162167
String userPoolClientId, {
163168
String? appClientSecret,
164169
AuthProvider? provider,
170+
CognitoSignInWithWebUIPluginOptions? options,
165171
String? codeVerifier,
166172
http.Client? httpClient,
167173
}) {
168174
return oauth2.AuthorizationCodeGrant(
169175
userPoolClientId,
170-
HostedUiConfig(authOutputs.oauth!).signInUri(provider),
176+
HostedUiConfig(authOutputs.oauth!).signInUri(provider, options),
171177
HostedUiConfig(authOutputs.oauth!).tokenUri,
172178
secret: appClientSecret,
173179
httpClient: httpClient,

packages/auth/amplify_auth_cognito_dart/lib/src/flows/hosted_ui/hosted_ui_platform_html.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ class HostedUiPlatformImpl extends HostedUiPlatform {
5454
required CognitoSignInWithWebUIPluginOptions options,
5555
AuthProvider? provider,
5656
}) async {
57-
final signInUrl = (await getSignInUri(provider: provider)).toString();
57+
final signInUrl = (await getSignInUri(
58+
provider: provider,
59+
options: options,
60+
)).toString();
5861
await launchUrl(signInUrl);
5962
}
6063

packages/auth/amplify_auth_cognito_dart/lib/src/flows/hosted_ui/hosted_ui_platform_io.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ class HostedUiPlatformImpl extends HostedUiPlatform {
216216
try {
217217
final signInUrl = (await getSignInUri(
218218
provider: provider,
219+
options: options,
219220
redirectUri: localServer.uri,
220221
)).toString();
221222
await launchUrl(signInUrl);

0 commit comments

Comments
 (0)