Skip to content

Commit

Permalink
appauth: support SFSafariController
Browse files Browse the repository at this point in the history
  • Loading branch information
john-slow committed Sep 26, 2024
1 parent 33efc78 commit 1703094
Show file tree
Hide file tree
Showing 10 changed files with 326 additions and 34 deletions.
67 changes: 56 additions & 11 deletions flutter_appauth/example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:convert';
import 'dart:io' show Platform;
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_appauth/flutter_appauth.dart';
Expand Down Expand Up @@ -107,7 +108,22 @@ class _MyAppState extends State<MyApp> {
textAlign: TextAlign.center,
),
onPressed: () => _signInWithAutoCodeExchange(
preferEphemeralSession: true),
preferredExternalAgent: ExternalAgentType
.ephemeralAsWebAuthenticationSession),
),
),
if (Platform.isIOS)
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
child: const Text(
'Sign in with auto code exchange using '
'SFSafariViewController',
textAlign: TextAlign.center,
),
onPressed: () => _signInWithAutoCodeExchange(
preferredExternalAgent:
ExternalAgentType.sfSafariViewController),
),
),
ElevatedButton(
Expand All @@ -123,6 +139,34 @@ class _MyAppState extends State<MyApp> {
: null,
child: const Text('End session'),
),
if (Platform.isIOS || Platform.isMacOS)
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: _idToken != null
? () async {
await _endSession(
preferredExternalAgent: ExternalAgentType
.ephemeralAsWebAuthenticationSession);
}
: null,
child:
const Text('End session using ephemeral session'),
)),
if (Platform.isIOS)
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: _idToken != null
? () async {
await _endSession(
preferredExternalAgent: ExternalAgentType
.sfSafariViewController);
}
: null,
child: const Text(
'End session using SFSafariViewController'),
)),
const SizedBox(height: 8),
if (_error != null) Text(_error ?? ''),
const SizedBox(height: 8),
Expand Down Expand Up @@ -156,13 +200,16 @@ class _MyAppState extends State<MyApp> {
);
}

Future<void> _endSession() async {
Future<void> _endSession(
{ExternalAgentType preferredExternalAgent =
ExternalAgentType.asWebAuthenticationSession}) async {
try {
_setBusyState();
await _appAuth.endSession(EndSessionRequest(
idTokenHint: _idToken,
postLogoutRedirectUrl: _postLogoutRedirectUrl,
serviceConfiguration: _serviceConfiguration));
serviceConfiguration: _serviceConfiguration,
preferredExternalAgent: preferredExternalAgent));
_clearSessionInfo();
} catch (e) {
_handleError(e);
Expand Down Expand Up @@ -285,7 +332,8 @@ class _MyAppState extends State<MyApp> {
}

Future<void> _signInWithAutoCodeExchange(
{bool preferEphemeralSession = false}) async {
{ExternalAgentType preferredExternalAgent =
ExternalAgentType.asWebAuthenticationSession}) async {
try {
_setBusyState();

Expand All @@ -295,13 +343,10 @@ class _MyAppState extends State<MyApp> {
*/
final AuthorizationTokenResponse result =
await _appAuth.authorizeAndExchangeCode(
AuthorizationTokenRequest(
_clientId,
_redirectUrl,
serviceConfiguration: _serviceConfiguration,
scopes: _scopes,
preferEphemeralSession: preferEphemeralSession,
),
AuthorizationTokenRequest(_clientId, _redirectUrl,
serviceConfiguration: _serviceConfiguration,
scopes: _scopes,
preferredExternalAgent: preferredExternalAgent),
);

/*
Expand Down
1 change: 1 addition & 0 deletions flutter_appauth/ios/Classes/AppAuthIOSAuthorization.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import <AppAuth/AppAuth.h>
#import <Flutter/Flutter.h>
#import "OIDExternalUserAgentIOSNoSSO.h"
#import "OIDExternalUserAgentIOSSafariViewController.h"
#import "FlutterAppAuth.h"

NS_ASSUME_NONNULL_BEGIN
Expand Down
20 changes: 12 additions & 8 deletions flutter_appauth/ios/Classes/AppAuthIOSAuthorization.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

@implementation AppAuthIOSAuthorization

- (id<OIDExternalUserAgentSession>) performAuthorization:(OIDServiceConfiguration *)serviceConfiguration clientId:(NSString*)clientId clientSecret:(NSString*)clientSecret scopes:(NSArray *)scopes redirectUrl:(NSString*)redirectUrl additionalParameters:(NSDictionary *)additionalParameters preferEphemeralSession:(BOOL)preferEphemeralSession result:(FlutterResult)result exchangeCode:(BOOL)exchangeCode nonce:(NSString*)nonce{
- (id<OIDExternalUserAgentSession>) performAuthorization:(OIDServiceConfiguration *)serviceConfiguration clientId:(NSString*)clientId clientSecret:(NSString*)clientSecret scopes:(NSArray *)scopes redirectUrl:(NSString*)redirectUrl additionalParameters:(NSDictionary *)additionalParameters preferredExternalAgent:(NSString*)preferredExternalAgent result:(FlutterResult)result exchangeCode:(BOOL)exchangeCode nonce:(NSString*)nonce{
NSString *codeVerifier = [OIDAuthorizationRequest generateCodeVerifier];
NSString *codeChallenge = [OIDAuthorizationRequest codeChallengeS256ForVerifier:codeVerifier];

Expand All @@ -21,7 +21,7 @@ @implementation AppAuthIOSAuthorization
additionalParameters:additionalParameters];
UIViewController *rootViewController = [self rootViewController];
if(exchangeCode) {
id<OIDExternalUserAgent> externalUserAgent = [self userAgentWithViewController:rootViewController useEphemeralSession:preferEphemeralSession];
id<OIDExternalUserAgent> externalUserAgent = [self userAgentWithViewController:rootViewController preferredExternalAgent:preferredExternalAgent];
return [OIDAuthState authStateByPresentingAuthorizationRequest:request externalUserAgent:externalUserAgent callback:^(OIDAuthState *_Nullable authState,
NSError *_Nullable error) {
if(authState) {
Expand All @@ -32,7 +32,7 @@ @implementation AppAuthIOSAuthorization
}
}];
} else {
id<OIDExternalUserAgent> externalUserAgent = [self userAgentWithViewController:rootViewController useEphemeralSession:preferEphemeralSession];
id<OIDExternalUserAgent> externalUserAgent = [self userAgentWithViewController:rootViewController preferredExternalAgent:preferredExternalAgent];
return [OIDAuthorizationService presentAuthorizationRequest:request externalUserAgent:externalUserAgent callback:^(OIDAuthorizationResponse *_Nullable authorizationResponse, NSError *_Nullable error) {
if(authorizationResponse) {
NSMutableDictionary *processedResponse = [[NSMutableDictionary alloc] init];
Expand All @@ -56,7 +56,7 @@ @implementation AppAuthIOSAuthorization
additionalParameters:requestParameters.additionalParameters];

UIViewController *rootViewController = [self rootViewController];
id<OIDExternalUserAgent> externalUserAgent = [self userAgentWithViewController:rootViewController useEphemeralSession:requestParameters.preferEphemeralSession];
id<OIDExternalUserAgent> externalUserAgent = [self userAgentWithViewController:rootViewController preferredExternalAgent:requestParameters.preferredExternalAgent];


return [OIDAuthorizationService presentEndSessionRequest:endSessionRequest externalUserAgent:externalUserAgent callback:^(OIDEndSessionResponse * _Nullable endSessionResponse, NSError * _Nullable error) {
Expand All @@ -71,13 +71,17 @@ @implementation AppAuthIOSAuthorization
}];
}

- (id<OIDExternalUserAgent>)userAgentWithViewController:(UIViewController *)rootViewController useEphemeralSession:(BOOL)useEphemeralSession {
if (useEphemeralSession) {
- (id<OIDExternalUserAgent>)userAgentWithViewController:(UIViewController *)rootViewController preferredExternalAgent:(NSString*)preferredExternalAgent {
if ([preferredExternalAgent isEqual:@"ExternalAgentType.ephemeralAsWebAuthenticationSession"]) {
return [[OIDExternalUserAgentIOSNoSSO alloc]
initWithPresentingViewController:rootViewController];
} else if ([preferredExternalAgent isEqual:@"ExternalAgentType.sfSafariViewController"]) {
return [[OIDExternalUserAgentIOSSafariViewController alloc]
initWithPresentingViewController:rootViewController];
} else {
return [[OIDExternalUserAgentIOS alloc]
initWithPresentingViewController:rootViewController];
}
return [[OIDExternalUserAgentIOS alloc]
initWithPresentingViewController:rootViewController];
}

- (UIViewController *)rootViewController {
Expand Down
4 changes: 2 additions & 2 deletions flutter_appauth/ios/Classes/FlutterAppAuth.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ static NSString *const END_SESSION_ERROR_MESSAGE_FORMAT = @"Failed to end sessio
@property(nonatomic, strong) NSString *discoveryUrl;
@property(nonatomic, strong) NSDictionary *serviceConfigurationParameters;
@property(nonatomic, strong) NSDictionary *additionalParameters;
@property(nonatomic, readwrite) BOOL preferEphemeralSession;
@property(nonatomic, strong) NSString *preferredExternalAgent;
@end

@interface AppAuthAuthorization : NSObject

- (id<OIDExternalUserAgentSession>)performAuthorization:(OIDServiceConfiguration *)serviceConfiguration clientId:(NSString*)clientId clientSecret:(NSString*)clientSecret scopes:(NSArray *)scopes redirectUrl:(NSString*)redirectUrl additionalParameters:(NSDictionary *)additionalParameters preferEphemeralSession:(BOOL)preferEphemeralSession result:(FlutterResult)result exchangeCode:(BOOL)exchangeCode nonce:(NSString*)nonce;
- (id<OIDExternalUserAgentSession>)performAuthorization:(OIDServiceConfiguration *)serviceConfiguration clientId:(NSString*)clientId clientSecret:(NSString*)clientSecret scopes:(NSArray *)scopes redirectUrl:(NSString*)redirectUrl additionalParameters:(NSDictionary *)additionalParameters preferredExternalAgent:(NSString*)preferredExternalAgent result:(FlutterResult)result exchangeCode:(BOOL)exchangeCode nonce:(NSString*)nonce;

- (id<OIDExternalUserAgentSession>)performEndSessionRequest:(OIDServiceConfiguration *)serviceConfiguration requestParameters:(EndSessionRequestParameters *)requestParameters result:(FlutterResult)result;

Expand Down
2 changes: 1 addition & 1 deletion flutter_appauth/ios/Classes/FlutterAppAuth.m
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ + (NSString *) formatMessageWithError:(NSString *)messageFormat error:(NSError *

@implementation AppAuthAuthorization

- (id<OIDExternalUserAgentSession>)performAuthorization:(OIDServiceConfiguration *)serviceConfiguration clientId:(NSString*)clientId clientSecret:(NSString*)clientSecret scopes:(NSArray *)scopes redirectUrl:(NSString*)redirectUrl additionalParameters:(NSDictionary *)additionalParameters preferEphemeralSession:(BOOL)preferEphemeralSession result:(FlutterResult)result exchangeCode:(BOOL)exchangeCode nonce:(NSString*)nonce {
- (id<OIDExternalUserAgentSession>)performAuthorization:(OIDServiceConfiguration *)serviceConfiguration clientId:(NSString*)clientId clientSecret:(NSString*)clientSecret scopes:(NSArray *)scopes redirectUrl:(NSString*)redirectUrl additionalParameters:(NSDictionary *)additionalParameters preferredExternalAgent:(NSString*)preferredExternalAgent result:(FlutterResult)result exchangeCode:(BOOL)exchangeCode nonce:(NSString*)nonce {
return nil;
}

Expand Down
12 changes: 6 additions & 6 deletions flutter_appauth/ios/Classes/FlutterAppauthPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ @interface TokenRequestParameters : NSObject
@property(nonatomic, strong) NSArray *scopes;
@property(nonatomic, strong) NSDictionary *serviceConfigurationParameters;
@property(nonatomic, strong) NSDictionary *additionalParameters;
@property(nonatomic, readwrite) BOOL preferEphemeralSession;
@property(nonatomic, strong) NSString *preferredExternalAgent;

@end

Expand All @@ -47,7 +47,7 @@ - (void)processArguments:(NSDictionary *)arguments {
_scopes = [ArgumentProcessor processArgumentValue:arguments withKey:@"scopes"];
_serviceConfigurationParameters = [ArgumentProcessor processArgumentValue:arguments withKey:@"serviceConfiguration"];
_additionalParameters = [ArgumentProcessor processArgumentValue:arguments withKey:@"additionalParameters"];
_preferEphemeralSession = [[ArgumentProcessor processArgumentValue:arguments withKey:@"preferEphemeralSession"] isEqual:@YES];
_preferredExternalAgent = [ArgumentProcessor processArgumentValue:arguments withKey:@"preferredExternalAgent"];
}

- (id)initWithArguments:(NSDictionary *)arguments {
Expand Down Expand Up @@ -82,7 +82,7 @@ - (id)initWithArguments:(NSDictionary *)arguments {
_discoveryUrl = [ArgumentProcessor processArgumentValue:arguments withKey:@"discoveryUrl"];
_serviceConfigurationParameters = [ArgumentProcessor processArgumentValue:arguments withKey:@"serviceConfiguration"];
_additionalParameters = [ArgumentProcessor processArgumentValue:arguments withKey:@"additionalParameters"];
_preferEphemeralSession = [[ArgumentProcessor processArgumentValue:arguments withKey:@"preferEphemeralSession"] isEqual:@YES];
_preferredExternalAgent = [ArgumentProcessor processArgumentValue:arguments withKey:@"preferredExternalAgent"];
return self;
}
@end
Expand Down Expand Up @@ -149,7 +149,7 @@ -(void)handleAuthorizeMethodCall:(NSDictionary*)arguments result:(FlutterResult)

if(requestParameters.serviceConfigurationParameters != nil) {
OIDServiceConfiguration *serviceConfiguration = [self processServiceConfigurationParameters:requestParameters.serviceConfigurationParameters];
_currentAuthorizationFlow = [authorization performAuthorization:serviceConfiguration clientId:requestParameters.clientId clientSecret:requestParameters.clientSecret scopes:requestParameters.scopes redirectUrl:requestParameters.redirectUrl additionalParameters:requestParameters.additionalParameters preferEphemeralSession:requestParameters.preferEphemeralSession result:result exchangeCode:exchangeCode nonce:requestParameters.nonce];
_currentAuthorizationFlow = [authorization performAuthorization:serviceConfiguration clientId:requestParameters.clientId clientSecret:requestParameters.clientSecret scopes:requestParameters.scopes redirectUrl:requestParameters.redirectUrl additionalParameters:requestParameters.additionalParameters preferredExternalAgent:requestParameters.preferredExternalAgent result:result exchangeCode:exchangeCode nonce:requestParameters.nonce];
} else if (requestParameters.discoveryUrl) {
NSURL *discoveryUrl = [NSURL URLWithString:requestParameters.discoveryUrl];
[OIDAuthorizationService discoverServiceConfigurationForDiscoveryURL:discoveryUrl
Expand All @@ -161,7 +161,7 @@ -(void)handleAuthorizeMethodCall:(NSDictionary*)arguments result:(FlutterResult)
return;
}

self->_currentAuthorizationFlow = [authorization performAuthorization:configuration clientId:requestParameters.clientId clientSecret:requestParameters.clientSecret scopes:requestParameters.scopes redirectUrl:requestParameters.redirectUrl additionalParameters:requestParameters.additionalParameters preferEphemeralSession:requestParameters.preferEphemeralSession result:result exchangeCode:exchangeCode nonce:requestParameters.nonce];
self->_currentAuthorizationFlow = [authorization performAuthorization:configuration clientId:requestParameters.clientId clientSecret:requestParameters.clientSecret scopes:requestParameters.scopes redirectUrl:requestParameters.redirectUrl additionalParameters:requestParameters.additionalParameters preferredExternalAgent:requestParameters.preferredExternalAgent result:result exchangeCode:exchangeCode nonce:requestParameters.nonce];
}];
} else {
NSURL *issuerUrl = [NSURL URLWithString:requestParameters.issuer];
Expand All @@ -174,7 +174,7 @@ -(void)handleAuthorizeMethodCall:(NSDictionary*)arguments result:(FlutterResult)
return;
}

self->_currentAuthorizationFlow = [authorization performAuthorization:configuration clientId:requestParameters.clientId clientSecret:requestParameters.clientSecret scopes:requestParameters.scopes redirectUrl:requestParameters.redirectUrl additionalParameters:requestParameters.additionalParameters preferEphemeralSession:requestParameters.preferEphemeralSession result:result exchangeCode:exchangeCode nonce:requestParameters.nonce];
self->_currentAuthorizationFlow = [authorization performAuthorization:configuration clientId:requestParameters.clientId clientSecret:requestParameters.clientSecret scopes:requestParameters.scopes redirectUrl:requestParameters.redirectUrl additionalParameters:requestParameters.additionalParameters preferredExternalAgent:requestParameters.preferredExternalAgent result:result exchangeCode:exchangeCode nonce:requestParameters.nonce];
}];
}
}
Expand Down
Loading

0 comments on commit 1703094

Please sign in to comment.