Skip to content
Open
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
62 changes: 56 additions & 6 deletions flutter_appauth/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ class MyApp extends StatefulWidget {
State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
bool _isBusy = false;
bool _isAuthFlowInProgress = false;
final FlutterAppAuth _appAuth = const FlutterAppAuth();

String? _codeVerifier;
Expand Down Expand Up @@ -62,6 +63,30 @@ class _MyAppState extends State<MyApp> {
endSessionEndpoint: 'https://demo.duendesoftware.com/connect/endsession',
);

@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}

@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
if (_isAuthFlowInProgress) {
setState(() {
_isAuthFlowInProgress = false;
_clearBusyState();
});
}
}
}

@override
Widget build(BuildContext context) {
return MaterialApp(
Expand Down Expand Up @@ -126,6 +151,19 @@ class _MyAppState extends State<MyApp> {
ExternalUserAgent.sfSafariViewController),
),
),
if (Platform.isIOS)
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
child: const Text(
'Auto code exchange using system browser (iOS only)',
textAlign: TextAlign.center,
),
onPressed: () => _signInWithAutoCodeExchange(
externalUserAgent:
ExternalUserAgent.customBrowser),
),
),
ElevatedButton(
onPressed: _refreshToken != null ? _refresh : null,
child: const Text('Refresh token'),
Expand Down Expand Up @@ -335,21 +373,30 @@ class _MyAppState extends State<MyApp> {
{ExternalUserAgent externalUserAgent =
ExternalUserAgent.asWebAuthenticationSession}) async {
try {
_setBusyState();
_setBusyState(
isAuthFlow: externalUserAgent == ExternalUserAgent.customBrowser
);

/*
This shows that we can also explicitly specify the endpoints rather than
getting from the details from the discovery document.
*/
final AuthorizationTokenResponse result =
await _appAuth.authorizeAndExchangeCode(
final Future<AuthorizationTokenResponse> authRequest =
_appAuth.authorizeAndExchangeCode(
AuthorizationTokenRequest(_clientId, _redirectUrl,
serviceConfiguration: _serviceConfiguration,
scopes: _scopes,
externalUserAgent: externalUserAgent),
);

/*
// Apply timeout only when using an external browser user agent.
final AuthorizationTokenResponse result =
externalUserAgent == ExternalUserAgent.customBrowser
? await authRequest.timeout(const Duration(minutes: 2))
: await authRequest;


/*
This code block demonstrates passing in values for the prompt
parameter. In this case it prompts the user login even if they have
already signed in. the list of supported values depends on the
Expand Down Expand Up @@ -402,10 +449,13 @@ class _MyAppState extends State<MyApp> {
});
}

void _setBusyState() {
void _setBusyState({bool? isAuthFlow}) {
setState(() {
_error = '';
_isBusy = true;
if (isAuthFlow != null) {
_isAuthFlowInProgress = isAuthFlow;
}
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ @implementation AppAuthIOSAuthorization
return [[OIDExternalUserAgentIOSSafariViewController alloc]
initWithPresentingViewController:rootViewController];
}
if ([externalUserAgent integerValue] == CustomBrowser) {
return [OIDExternalUserAgentIOSCustomBrowser CustomBrowserSafari];
}
return [[OIDExternalUserAgentIOS alloc]
initWithPresentingViewController:rootViewController];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ static NSString *const END_SESSION_ERROR_MESSAGE_FORMAT =
typedef NS_ENUM(NSInteger, ExternalUserAgent) {
ASWebAuthenticationSession,
EphemeralASWebAuthenticationSession,
SafariViewController
SafariViewController,
CustomBrowser
};

@interface AppAuthAuthorization : NSObject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,12 @@ enum ExternalUserAgent {
/// Note that as this does not follow the best practices on using the
/// appropriate native APIs based on the OS version, developers should use
/// this at their own discretion.
sfSafariViewController
sfSafariViewController,


/// Indicates a preference for using an external user-agent,
/// suitable for e.g. the secure browser of a MDM solution,
/// SSO flows and using the cookies/context of the system main browser.
/// This is only applicable to iOS (fallback is [asWebAuthenticationSession]).
customBrowser
}