From acaef1f598400176958629260981e5861718130f Mon Sep 17 00:00:00 2001
From: Michael Bui <25263378+MaikuB@users.noreply.github.com>
Date: Sat, 28 Sep 2024 16:06:23 +1000
Subject: [PATCH] [various] added formatting workflow to fire on push (#545)

* added formatting workflow that fires on push

* Google Java Format

* updated formatting workflow to be able to run on workflow_dispatch

* Clang Format

---------

Co-authored-by: github-actions <>
Co-authored-by: Anka <runner@Mac-1727501243373.local>
---
 .github/workflows/format.yml                  |   36 +
 .../flutterappauth/FlutterAppauthPlugin.java  | 1406 ++++++++++-------
 .../InsecureConnectionBuilder.java            |   14 +-
 .../ios/Classes/AppAuthIOSAuthorization.h     |    6 +-
 .../ios/Classes/AppAuthIOSAuthorization.m     |  247 ++-
 flutter_appauth/ios/Classes/FlutterAppAuth.h  |   44 +-
 flutter_appauth/ios/Classes/FlutterAppAuth.m  |  206 ++-
 .../ios/Classes/FlutterAppauthPlugin.h        |    9 +-
 .../ios/Classes/FlutterAppauthPlugin.m        |  637 +++++---
 .../Classes/OIDExternalUserAgentIOSNoSSO.h    |   22 +-
 .../Classes/OIDExternalUserAgentIOSNoSSO.m    |  164 +-
 ...ExternalUserAgentIOSSafariViewController.h |   28 +-
 ...ExternalUserAgentIOSSafariViewController.m |  205 +--
 .../macos/Classes/AppAuthMacOSAuthorization.h |    7 +-
 .../macos/Classes/AppAuthMacOSAuthorization.m |  230 ++-
 .../macos/Classes/FlutterAppAuth.m            |  150 +-
 .../macos/Classes/FlutterAppauthPlugin.m      |  514 +++++-
 .../Classes/OIDExternalUserAgentMacNoSSO.h    |   21 +-
 .../Classes/OIDExternalUserAgentMacNoSSO.m    |   84 +-
 19 files changed, 2732 insertions(+), 1298 deletions(-)
 create mode 100644 .github/workflows/format.yml
 mode change 120000 => 100644 flutter_appauth/macos/Classes/FlutterAppAuth.m
 mode change 120000 => 100644 flutter_appauth/macos/Classes/FlutterAppauthPlugin.m

diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml
new file mode 100644
index 00000000..aa29fb2c
--- /dev/null
+++ b/.github/workflows/format.yml
@@ -0,0 +1,36 @@
+name: format
+
+on:
+  - push
+  - workflow_dispatch
+
+jobs:
+  java_format:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - uses: axel-op/googlejavaformat-action@v3
+        with:
+          args: '--skip-sorting-imports --replace'
+
+  objc_format:
+    runs-on: macos-latest
+    steps:
+      - uses: actions/checkout@v4
+      - name: Test
+        run: |
+          which clang-format || brew install clang-format
+          find . -name '*.m' -exec clang-format -i {} \;
+          find . -path '*/ios/**/*.h' -exec clang-format -i {} \;
+          find . -path '*/macos/**/*.h' -exec clang-format -i {} \;
+          git diff --exit-code || (git commit --all -m "Clang Format" && git push)
+
+  swift_format:
+    runs-on: macos-latest
+    steps:
+      - uses: actions/checkout@v4
+      - name: Test
+        run: |
+          which swiftlint || brew install swiftlint
+          swiftlint --fix
+          git diff --exit-code || (git commit --all -m "Swift Format" && git push)
diff --git a/flutter_appauth/android/src/main/java/io/crossingthestreams/flutterappauth/FlutterAppauthPlugin.java b/flutter_appauth/android/src/main/java/io/crossingthestreams/flutterappauth/FlutterAppauthPlugin.java
index 861e095e..8b7b5527 100644
--- a/flutter_appauth/android/src/main/java/io/crossingthestreams/flutterappauth/FlutterAppauthPlugin.java
+++ b/flutter_appauth/android/src/main/java/io/crossingthestreams/flutterappauth/FlutterAppauthPlugin.java
@@ -41,637 +41,857 @@
 import io.flutter.plugin.common.MethodChannel.Result;
 import io.flutter.plugin.common.PluginRegistry;
 
-/**
- * FlutterAppauthPlugin
- */
-public class FlutterAppauthPlugin implements FlutterPlugin, MethodCallHandler, PluginRegistry.ActivityResultListener, ActivityAware {
-    private static final String AUTHORIZE_AND_EXCHANGE_CODE_METHOD = "authorizeAndExchangeCode";
-    private static final String AUTHORIZE_METHOD = "authorize";
-    private static final String TOKEN_METHOD = "token";
-    private static final String END_SESSION_METHOD = "endSession";
-
-    private static final String DISCOVERY_ERROR_CODE = "discovery_failed";
-    private static final String AUTHORIZE_AND_EXCHANGE_CODE_ERROR_CODE = "authorize_and_exchange_code_failed";
-    private static final String AUTHORIZE_ERROR_CODE = "authorize_failed";
-    private static final String TOKEN_ERROR_CODE = "token_failed";
-    private static final String END_SESSION_ERROR_CODE = "end_session_failed";
-    private static final String NULL_INTENT_ERROR_CODE = "null_intent";
-    private static final String INVALID_CLAIMS_ERROR_CODE = "invalid_claims";
-    private static final String NO_BROWSER_AVAILABLE_ERROR_CODE = "no_browser_available";
-
-    private static final String DISCOVERY_ERROR_MESSAGE_FORMAT = "Error retrieving discovery document: [error: %s, description: %s]";
-    private static final String TOKEN_ERROR_MESSAGE_FORMAT = "Failed to get token: [error: %s, description: %s]";
-    private static final String AUTHORIZE_ERROR_MESSAGE_FORMAT = "Failed to authorize: [error: %s, description: %s]";
-    private static final String END_SESSION_ERROR_MESSAGE_FORMAT = "Failed to end session: [error: %s, description: %s]";
-
-    private static final String NULL_INTENT_ERROR_FORMAT = "Failed to authorize: Null intent received";
-    private static final String NO_BROWSER_AVAILABLE_ERROR_FORMAT = "Failed to authorize: No suitable browser is available";
-
-    private final int RC_AUTH_EXCHANGE_CODE = 65030;
-    private final int RC_AUTH = 65031;
-    private final int RC_END_SESSION = 65032;
-
-    private Context applicationContext;
-    private Activity mainActivity;
-    private PendingOperation pendingOperation;
-    private String clientSecret;
-    private boolean allowInsecureConnections;
-    private AuthorizationService defaultAuthorizationService;
-    private AuthorizationService insecureAuthorizationService;
-
-    private void setActivity(Activity flutterActivity) {
-        this.mainActivity = flutterActivity;
-    }
-
-    private void onAttachedToEngine(Context context, BinaryMessenger binaryMessenger) {
-        this.applicationContext = context;
-        defaultAuthorizationService = new AuthorizationService(this.applicationContext);
-        AppAuthConfiguration.Builder authConfigBuilder = new AppAuthConfiguration.Builder();
-        authConfigBuilder.setConnectionBuilder(InsecureConnectionBuilder.INSTANCE);
-        authConfigBuilder.setSkipIssuerHttpsCheck(true);
-        insecureAuthorizationService = new AuthorizationService(applicationContext, authConfigBuilder.build());
-        final MethodChannel channel = new MethodChannel(binaryMessenger, "crossingthestreams.io/flutter_appauth");
-        channel.setMethodCallHandler(this);
-    }
-
-    @Override
-    public void onAttachedToEngine(FlutterPluginBinding binding) {
-        onAttachedToEngine(binding.getApplicationContext(), binding.getBinaryMessenger());
-    }
-
-    @Override
-    public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
-        disposeAuthorizationServices();
-    }
-
-    @Override
-    public void onAttachedToActivity(ActivityPluginBinding binding) {
-        binding.addActivityResultListener(this);
-        mainActivity = binding.getActivity();
-    }
-
-    @Override
-    public void onDetachedFromActivityForConfigChanges() {
-        this.mainActivity = null;
-    }
-
-    @Override
-    public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
-        binding.addActivityResultListener(this);
-        mainActivity = binding.getActivity();
-    }
-
-    @Override
-    public void onDetachedFromActivity() {
-        this.mainActivity = null;
-    }
-
-    private void disposeAuthorizationServices() {
-        defaultAuthorizationService.dispose();
-        insecureAuthorizationService.dispose();
-        defaultAuthorizationService = null;
-        insecureAuthorizationService = null;
-    }
-
-    private void checkAndSetPendingOperation(String method, Result result) {
-        if (pendingOperation != null) {
-            throw new IllegalStateException(
-                    "Concurrent operations detected: " + pendingOperation.method + ", " + method);
-        }
-        pendingOperation = new PendingOperation(method, result);
-    }
-
-
-    @Override
-    public void onMethodCall(MethodCall call, @NonNull Result result) {
-        Map<String, Object> arguments = call.arguments();
-        switch (call.method) {
-            case AUTHORIZE_AND_EXCHANGE_CODE_METHOD:
-                try {
-                    checkAndSetPendingOperation(call.method, result);
-                    handleAuthorizeMethodCall(arguments, true);
-                } catch (Exception ex) {
-                    finishWithError(AUTHORIZE_AND_EXCHANGE_CODE_ERROR_CODE, ex.getLocalizedMessage(), ex);
-                }
-                break;
-            case AUTHORIZE_METHOD:
-                try {
-                    checkAndSetPendingOperation(call.method, result);
-                    handleAuthorizeMethodCall(arguments, false);
-                } catch (Exception ex) {
-                    finishWithError(AUTHORIZE_ERROR_CODE, ex.getLocalizedMessage(), ex);
-                }
-                break;
-            case TOKEN_METHOD:
-                try {
-                    checkAndSetPendingOperation(call.method, result);
-                    handleTokenMethodCall(arguments);
-                } catch (Exception ex) {
-                    finishWithError(TOKEN_ERROR_CODE, ex.getLocalizedMessage(), ex);
-                }
-                break;
-            case END_SESSION_METHOD:
-                try {
-                    checkAndSetPendingOperation(call.method, result);
-                    handleEndSessionMethodCall(arguments);
-                } catch (Exception ex) {
-                    finishWithError(END_SESSION_ERROR_CODE, ex.getLocalizedMessage(), ex);
-                }
-                break;
-            default:
-                result.notImplemented();
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private AuthorizationTokenRequestParameters processAuthorizationTokenRequestArguments(Map<String, Object> arguments) {
-        final String clientId = (String) arguments.get("clientId");
-        final String issuer = (String) arguments.get("issuer");
-        final String discoveryUrl = (String) arguments.get("discoveryUrl");
-        final String redirectUrl = (String) arguments.get("redirectUrl");
-        final String loginHint = (String) arguments.get("loginHint");
-        final String nonce = (String) arguments.get("nonce");
-        clientSecret = (String) arguments.get("clientSecret");
-        final ArrayList<String> scopes = (ArrayList<String>) arguments.get("scopes");
-        final ArrayList<String> promptValues = (ArrayList<String>) arguments.get("promptValues");
-        Map<String, String> serviceConfigurationParameters = (Map<String, String>) arguments.get("serviceConfiguration");
-        Map<String, String> additionalParameters = (Map<String, String>) arguments.get("additionalParameters");
-        allowInsecureConnections = (boolean) arguments.get("allowInsecureConnections");
-        final String responseMode = (String) arguments.get("responseMode");
-
-        return new AuthorizationTokenRequestParameters(clientId, issuer, discoveryUrl, scopes, redirectUrl, serviceConfigurationParameters, additionalParameters, loginHint, nonce, promptValues, responseMode);
-    }
-
-    @SuppressWarnings("unchecked")
-    private TokenRequestParameters processTokenRequestArguments(Map<String, Object> arguments) {
-        final String clientId = (String) arguments.get("clientId");
-        final String issuer = (String) arguments.get("issuer");
-        final String discoveryUrl = (String) arguments.get("discoveryUrl");
-        final String redirectUrl = (String) arguments.get("redirectUrl");
-        final String grantType = (String) arguments.get("grantType");
-        clientSecret = (String) arguments.get("clientSecret");
-        String refreshToken = null;
-        if (arguments.containsKey("refreshToken")) {
-            refreshToken = (String) arguments.get("refreshToken");
-        }
-        String authorizationCode = null;
-        if (arguments.containsKey("authorizationCode")) {
-            authorizationCode = (String) arguments.get("authorizationCode");
+/** FlutterAppauthPlugin */
+public class FlutterAppauthPlugin
+    implements FlutterPlugin,
+        MethodCallHandler,
+        PluginRegistry.ActivityResultListener,
+        ActivityAware {
+  private static final String AUTHORIZE_AND_EXCHANGE_CODE_METHOD = "authorizeAndExchangeCode";
+  private static final String AUTHORIZE_METHOD = "authorize";
+  private static final String TOKEN_METHOD = "token";
+  private static final String END_SESSION_METHOD = "endSession";
+
+  private static final String DISCOVERY_ERROR_CODE = "discovery_failed";
+  private static final String AUTHORIZE_AND_EXCHANGE_CODE_ERROR_CODE =
+      "authorize_and_exchange_code_failed";
+  private static final String AUTHORIZE_ERROR_CODE = "authorize_failed";
+  private static final String TOKEN_ERROR_CODE = "token_failed";
+  private static final String END_SESSION_ERROR_CODE = "end_session_failed";
+  private static final String NULL_INTENT_ERROR_CODE = "null_intent";
+  private static final String INVALID_CLAIMS_ERROR_CODE = "invalid_claims";
+  private static final String NO_BROWSER_AVAILABLE_ERROR_CODE = "no_browser_available";
+
+  private static final String DISCOVERY_ERROR_MESSAGE_FORMAT =
+      "Error retrieving discovery document: [error: %s, description: %s]";
+  private static final String TOKEN_ERROR_MESSAGE_FORMAT =
+      "Failed to get token: [error: %s, description: %s]";
+  private static final String AUTHORIZE_ERROR_MESSAGE_FORMAT =
+      "Failed to authorize: [error: %s, description: %s]";
+  private static final String END_SESSION_ERROR_MESSAGE_FORMAT =
+      "Failed to end session: [error: %s, description: %s]";
+
+  private static final String NULL_INTENT_ERROR_FORMAT =
+      "Failed to authorize: Null intent received";
+  private static final String NO_BROWSER_AVAILABLE_ERROR_FORMAT =
+      "Failed to authorize: No suitable browser is available";
+
+  private final int RC_AUTH_EXCHANGE_CODE = 65030;
+  private final int RC_AUTH = 65031;
+  private final int RC_END_SESSION = 65032;
+
+  private Context applicationContext;
+  private Activity mainActivity;
+  private PendingOperation pendingOperation;
+  private String clientSecret;
+  private boolean allowInsecureConnections;
+  private AuthorizationService defaultAuthorizationService;
+  private AuthorizationService insecureAuthorizationService;
+
+  private void setActivity(Activity flutterActivity) {
+    this.mainActivity = flutterActivity;
+  }
+
+  private void onAttachedToEngine(Context context, BinaryMessenger binaryMessenger) {
+    this.applicationContext = context;
+    defaultAuthorizationService = new AuthorizationService(this.applicationContext);
+    AppAuthConfiguration.Builder authConfigBuilder = new AppAuthConfiguration.Builder();
+    authConfigBuilder.setConnectionBuilder(InsecureConnectionBuilder.INSTANCE);
+    authConfigBuilder.setSkipIssuerHttpsCheck(true);
+    insecureAuthorizationService =
+        new AuthorizationService(applicationContext, authConfigBuilder.build());
+    final MethodChannel channel =
+        new MethodChannel(binaryMessenger, "crossingthestreams.io/flutter_appauth");
+    channel.setMethodCallHandler(this);
+  }
+
+  @Override
+  public void onAttachedToEngine(FlutterPluginBinding binding) {
+    onAttachedToEngine(binding.getApplicationContext(), binding.getBinaryMessenger());
+  }
+
+  @Override
+  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
+    disposeAuthorizationServices();
+  }
+
+  @Override
+  public void onAttachedToActivity(ActivityPluginBinding binding) {
+    binding.addActivityResultListener(this);
+    mainActivity = binding.getActivity();
+  }
+
+  @Override
+  public void onDetachedFromActivityForConfigChanges() {
+    this.mainActivity = null;
+  }
+
+  @Override
+  public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
+    binding.addActivityResultListener(this);
+    mainActivity = binding.getActivity();
+  }
+
+  @Override
+  public void onDetachedFromActivity() {
+    this.mainActivity = null;
+  }
+
+  private void disposeAuthorizationServices() {
+    defaultAuthorizationService.dispose();
+    insecureAuthorizationService.dispose();
+    defaultAuthorizationService = null;
+    insecureAuthorizationService = null;
+  }
+
+  private void checkAndSetPendingOperation(String method, Result result) {
+    if (pendingOperation != null) {
+      throw new IllegalStateException(
+          "Concurrent operations detected: " + pendingOperation.method + ", " + method);
+    }
+    pendingOperation = new PendingOperation(method, result);
+  }
+
+  @Override
+  public void onMethodCall(MethodCall call, @NonNull Result result) {
+    Map<String, Object> arguments = call.arguments();
+    switch (call.method) {
+      case AUTHORIZE_AND_EXCHANGE_CODE_METHOD:
+        try {
+          checkAndSetPendingOperation(call.method, result);
+          handleAuthorizeMethodCall(arguments, true);
+        } catch (Exception ex) {
+          finishWithError(AUTHORIZE_AND_EXCHANGE_CODE_ERROR_CODE, ex.getLocalizedMessage(), ex);
         }
-        String codeVerifier = null;
-        if (arguments.containsKey("codeVerifier")) {
-            codeVerifier = (String) arguments.get("codeVerifier");
+        break;
+      case AUTHORIZE_METHOD:
+        try {
+          checkAndSetPendingOperation(call.method, result);
+          handleAuthorizeMethodCall(arguments, false);
+        } catch (Exception ex) {
+          finishWithError(AUTHORIZE_ERROR_CODE, ex.getLocalizedMessage(), ex);
         }
-        String nonce = null;
-        if (arguments.containsKey("nonce")) {
-            nonce = (String) arguments.get("nonce");
+        break;
+      case TOKEN_METHOD:
+        try {
+          checkAndSetPendingOperation(call.method, result);
+          handleTokenMethodCall(arguments);
+        } catch (Exception ex) {
+          finishWithError(TOKEN_ERROR_CODE, ex.getLocalizedMessage(), ex);
         }
-        final ArrayList<String> scopes = (ArrayList<String>) arguments.get("scopes");
-        final Map<String, String> serviceConfigurationParameters = (Map<String, String>) arguments.get("serviceConfiguration");
-        final Map<String, String> additionalParameters = (Map<String, String>) arguments.get("additionalParameters");
-        allowInsecureConnections = (boolean) arguments.get("allowInsecureConnections");
-        return new TokenRequestParameters(clientId, issuer, discoveryUrl, scopes, redirectUrl, refreshToken, authorizationCode, codeVerifier, nonce, grantType, serviceConfigurationParameters, additionalParameters);
-    }
-
-    @SuppressWarnings("unchecked")
-    private EndSessionRequestParameters processEndSessionRequestArguments(Map<String, Object> arguments) {
-        final String idTokenHint = (String) arguments.get("idTokenHint");
-        final String postLogoutRedirectUrl = (String) arguments.get("postLogoutRedirectUrl");
-        final String state = (String) arguments.get("state");
-        final boolean allowInsecureConnections = (boolean) arguments.get("allowInsecureConnections");
-        final String issuer = (String) arguments.get("issuer");
-        final String discoveryUrl = (String) arguments.get("discoveryUrl");
-        final Map<String, String> serviceConfigurationParameters = (Map<String, String>) arguments.get("serviceConfiguration");
-        final Map<String, String> additionalParameters = (Map<String, String>) arguments.get("additionalParameters");
-        return new EndSessionRequestParameters(idTokenHint, postLogoutRedirectUrl, state, issuer, discoveryUrl, allowInsecureConnections, serviceConfigurationParameters, additionalParameters);
-    }
-
-    private void handleAuthorizeMethodCall(Map<String, Object> arguments, final boolean exchangeCode) {
-        final AuthorizationTokenRequestParameters tokenRequestParameters = processAuthorizationTokenRequestArguments(arguments);
-        if (tokenRequestParameters.serviceConfigurationParameters != null) {
-            AuthorizationServiceConfiguration serviceConfiguration = processServiceConfigurationParameters(tokenRequestParameters.serviceConfigurationParameters);
-            performAuthorization(serviceConfiguration, tokenRequestParameters.clientId, tokenRequestParameters.redirectUrl, tokenRequestParameters.scopes, tokenRequestParameters.loginHint, tokenRequestParameters.nonce, tokenRequestParameters.additionalParameters, exchangeCode, tokenRequestParameters.promptValues, tokenRequestParameters.responseMode);
-        } else {
-            AuthorizationServiceConfiguration.RetrieveConfigurationCallback callback = new AuthorizationServiceConfiguration.RetrieveConfigurationCallback() {
-                @Override
-                public void onFetchConfigurationCompleted(@Nullable AuthorizationServiceConfiguration serviceConfiguration, @Nullable AuthorizationException ex) {
-                    if (ex == null) {
-                        performAuthorization(serviceConfiguration, tokenRequestParameters.clientId, tokenRequestParameters.redirectUrl, tokenRequestParameters.scopes, tokenRequestParameters.loginHint, tokenRequestParameters.nonce, tokenRequestParameters.additionalParameters, exchangeCode, tokenRequestParameters.promptValues, tokenRequestParameters.responseMode);
-                    } else {
-                        finishWithDiscoveryError(ex);
-                    }
-                }
-            };
-            if (tokenRequestParameters.discoveryUrl != null) {
-                AuthorizationServiceConfiguration.fetchFromUrl(Uri.parse(tokenRequestParameters.discoveryUrl), callback, allowInsecureConnections ? InsecureConnectionBuilder.INSTANCE : DefaultConnectionBuilder.INSTANCE);
-            } else {
-                AuthorizationServiceConfiguration.fetchFromIssuer(Uri.parse(tokenRequestParameters.issuer), callback, allowInsecureConnections ? InsecureConnectionBuilder.INSTANCE : DefaultConnectionBuilder.INSTANCE);
+        break;
+      case END_SESSION_METHOD:
+        try {
+          checkAndSetPendingOperation(call.method, result);
+          handleEndSessionMethodCall(arguments);
+        } catch (Exception ex) {
+          finishWithError(END_SESSION_ERROR_CODE, ex.getLocalizedMessage(), ex);
+        }
+        break;
+      default:
+        result.notImplemented();
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  private AuthorizationTokenRequestParameters processAuthorizationTokenRequestArguments(
+      Map<String, Object> arguments) {
+    final String clientId = (String) arguments.get("clientId");
+    final String issuer = (String) arguments.get("issuer");
+    final String discoveryUrl = (String) arguments.get("discoveryUrl");
+    final String redirectUrl = (String) arguments.get("redirectUrl");
+    final String loginHint = (String) arguments.get("loginHint");
+    final String nonce = (String) arguments.get("nonce");
+    clientSecret = (String) arguments.get("clientSecret");
+    final ArrayList<String> scopes = (ArrayList<String>) arguments.get("scopes");
+    final ArrayList<String> promptValues = (ArrayList<String>) arguments.get("promptValues");
+    Map<String, String> serviceConfigurationParameters =
+        (Map<String, String>) arguments.get("serviceConfiguration");
+    Map<String, String> additionalParameters =
+        (Map<String, String>) arguments.get("additionalParameters");
+    allowInsecureConnections = (boolean) arguments.get("allowInsecureConnections");
+    final String responseMode = (String) arguments.get("responseMode");
+
+    return new AuthorizationTokenRequestParameters(
+        clientId,
+        issuer,
+        discoveryUrl,
+        scopes,
+        redirectUrl,
+        serviceConfigurationParameters,
+        additionalParameters,
+        loginHint,
+        nonce,
+        promptValues,
+        responseMode);
+  }
+
+  @SuppressWarnings("unchecked")
+  private TokenRequestParameters processTokenRequestArguments(Map<String, Object> arguments) {
+    final String clientId = (String) arguments.get("clientId");
+    final String issuer = (String) arguments.get("issuer");
+    final String discoveryUrl = (String) arguments.get("discoveryUrl");
+    final String redirectUrl = (String) arguments.get("redirectUrl");
+    final String grantType = (String) arguments.get("grantType");
+    clientSecret = (String) arguments.get("clientSecret");
+    String refreshToken = null;
+    if (arguments.containsKey("refreshToken")) {
+      refreshToken = (String) arguments.get("refreshToken");
+    }
+    String authorizationCode = null;
+    if (arguments.containsKey("authorizationCode")) {
+      authorizationCode = (String) arguments.get("authorizationCode");
+    }
+    String codeVerifier = null;
+    if (arguments.containsKey("codeVerifier")) {
+      codeVerifier = (String) arguments.get("codeVerifier");
+    }
+    String nonce = null;
+    if (arguments.containsKey("nonce")) {
+      nonce = (String) arguments.get("nonce");
+    }
+    final ArrayList<String> scopes = (ArrayList<String>) arguments.get("scopes");
+    final Map<String, String> serviceConfigurationParameters =
+        (Map<String, String>) arguments.get("serviceConfiguration");
+    final Map<String, String> additionalParameters =
+        (Map<String, String>) arguments.get("additionalParameters");
+    allowInsecureConnections = (boolean) arguments.get("allowInsecureConnections");
+    return new TokenRequestParameters(
+        clientId,
+        issuer,
+        discoveryUrl,
+        scopes,
+        redirectUrl,
+        refreshToken,
+        authorizationCode,
+        codeVerifier,
+        nonce,
+        grantType,
+        serviceConfigurationParameters,
+        additionalParameters);
+  }
+
+  @SuppressWarnings("unchecked")
+  private EndSessionRequestParameters processEndSessionRequestArguments(
+      Map<String, Object> arguments) {
+    final String idTokenHint = (String) arguments.get("idTokenHint");
+    final String postLogoutRedirectUrl = (String) arguments.get("postLogoutRedirectUrl");
+    final String state = (String) arguments.get("state");
+    final boolean allowInsecureConnections = (boolean) arguments.get("allowInsecureConnections");
+    final String issuer = (String) arguments.get("issuer");
+    final String discoveryUrl = (String) arguments.get("discoveryUrl");
+    final Map<String, String> serviceConfigurationParameters =
+        (Map<String, String>) arguments.get("serviceConfiguration");
+    final Map<String, String> additionalParameters =
+        (Map<String, String>) arguments.get("additionalParameters");
+    return new EndSessionRequestParameters(
+        idTokenHint,
+        postLogoutRedirectUrl,
+        state,
+        issuer,
+        discoveryUrl,
+        allowInsecureConnections,
+        serviceConfigurationParameters,
+        additionalParameters);
+  }
+
+  private void handleAuthorizeMethodCall(
+      Map<String, Object> arguments, final boolean exchangeCode) {
+    final AuthorizationTokenRequestParameters tokenRequestParameters =
+        processAuthorizationTokenRequestArguments(arguments);
+    if (tokenRequestParameters.serviceConfigurationParameters != null) {
+      AuthorizationServiceConfiguration serviceConfiguration =
+          processServiceConfigurationParameters(
+              tokenRequestParameters.serviceConfigurationParameters);
+      performAuthorization(
+          serviceConfiguration,
+          tokenRequestParameters.clientId,
+          tokenRequestParameters.redirectUrl,
+          tokenRequestParameters.scopes,
+          tokenRequestParameters.loginHint,
+          tokenRequestParameters.nonce,
+          tokenRequestParameters.additionalParameters,
+          exchangeCode,
+          tokenRequestParameters.promptValues,
+          tokenRequestParameters.responseMode);
+    } else {
+      AuthorizationServiceConfiguration.RetrieveConfigurationCallback callback =
+          new AuthorizationServiceConfiguration.RetrieveConfigurationCallback() {
+            @Override
+            public void onFetchConfigurationCompleted(
+                @Nullable AuthorizationServiceConfiguration serviceConfiguration,
+                @Nullable AuthorizationException ex) {
+              if (ex == null) {
+                performAuthorization(
+                    serviceConfiguration,
+                    tokenRequestParameters.clientId,
+                    tokenRequestParameters.redirectUrl,
+                    tokenRequestParameters.scopes,
+                    tokenRequestParameters.loginHint,
+                    tokenRequestParameters.nonce,
+                    tokenRequestParameters.additionalParameters,
+                    exchangeCode,
+                    tokenRequestParameters.promptValues,
+                    tokenRequestParameters.responseMode);
+              } else {
+                finishWithDiscoveryError(ex);
+              }
             }
-        }
-    }
-
-    private AuthorizationServiceConfiguration processServiceConfigurationParameters(Map<String, String> serviceConfigurationArguments) {
-        final String endSessionEndpoint = serviceConfigurationArguments.get("endSessionEndpoint");
-        return new AuthorizationServiceConfiguration(Uri.parse(serviceConfigurationArguments.get("authorizationEndpoint")), Uri.parse(serviceConfigurationArguments.get("tokenEndpoint")), null, endSessionEndpoint == null ? null : Uri.parse(endSessionEndpoint));
-    }
-
-    private void handleTokenMethodCall(Map<String, Object> arguments) {
-        final TokenRequestParameters tokenRequestParameters = processTokenRequestArguments(arguments);
-        if (tokenRequestParameters.serviceConfigurationParameters != null) {
-            AuthorizationServiceConfiguration serviceConfiguration = processServiceConfigurationParameters(tokenRequestParameters.serviceConfigurationParameters);
-            performTokenRequest(serviceConfiguration, tokenRequestParameters);
-        } else {
-            AuthorizationServiceConfiguration.RetrieveConfigurationCallback callback = new AuthorizationServiceConfiguration.RetrieveConfigurationCallback() {
-                @Override
-                public void onFetchConfigurationCompleted(@Nullable AuthorizationServiceConfiguration serviceConfiguration, @Nullable AuthorizationException ex) {
-                    if (ex == null) {
-                        performTokenRequest(serviceConfiguration, tokenRequestParameters);
-                    } else {
-                        finishWithDiscoveryError(ex);
-                    }
-                }
-            };
-            if (tokenRequestParameters.discoveryUrl != null) {
-                AuthorizationServiceConfiguration.fetchFromUrl(Uri.parse(tokenRequestParameters.discoveryUrl), callback, allowInsecureConnections ? InsecureConnectionBuilder.INSTANCE : DefaultConnectionBuilder.INSTANCE);
-            } else {
-                AuthorizationServiceConfiguration.fetchFromIssuer(Uri.parse(tokenRequestParameters.issuer), callback, allowInsecureConnections ? InsecureConnectionBuilder.INSTANCE : DefaultConnectionBuilder.INSTANCE);
+          };
+      if (tokenRequestParameters.discoveryUrl != null) {
+        AuthorizationServiceConfiguration.fetchFromUrl(
+            Uri.parse(tokenRequestParameters.discoveryUrl),
+            callback,
+            allowInsecureConnections
+                ? InsecureConnectionBuilder.INSTANCE
+                : DefaultConnectionBuilder.INSTANCE);
+      } else {
+        AuthorizationServiceConfiguration.fetchFromIssuer(
+            Uri.parse(tokenRequestParameters.issuer),
+            callback,
+            allowInsecureConnections
+                ? InsecureConnectionBuilder.INSTANCE
+                : DefaultConnectionBuilder.INSTANCE);
+      }
+    }
+  }
+
+  private AuthorizationServiceConfiguration processServiceConfigurationParameters(
+      Map<String, String> serviceConfigurationArguments) {
+    final String endSessionEndpoint = serviceConfigurationArguments.get("endSessionEndpoint");
+    return new AuthorizationServiceConfiguration(
+        Uri.parse(serviceConfigurationArguments.get("authorizationEndpoint")),
+        Uri.parse(serviceConfigurationArguments.get("tokenEndpoint")),
+        null,
+        endSessionEndpoint == null ? null : Uri.parse(endSessionEndpoint));
+  }
+
+  private void handleTokenMethodCall(Map<String, Object> arguments) {
+    final TokenRequestParameters tokenRequestParameters = processTokenRequestArguments(arguments);
+    if (tokenRequestParameters.serviceConfigurationParameters != null) {
+      AuthorizationServiceConfiguration serviceConfiguration =
+          processServiceConfigurationParameters(
+              tokenRequestParameters.serviceConfigurationParameters);
+      performTokenRequest(serviceConfiguration, tokenRequestParameters);
+    } else {
+      AuthorizationServiceConfiguration.RetrieveConfigurationCallback callback =
+          new AuthorizationServiceConfiguration.RetrieveConfigurationCallback() {
+            @Override
+            public void onFetchConfigurationCompleted(
+                @Nullable AuthorizationServiceConfiguration serviceConfiguration,
+                @Nullable AuthorizationException ex) {
+              if (ex == null) {
+                performTokenRequest(serviceConfiguration, tokenRequestParameters);
+              } else {
+                finishWithDiscoveryError(ex);
+              }
             }
-        }
+          };
+      if (tokenRequestParameters.discoveryUrl != null) {
+        AuthorizationServiceConfiguration.fetchFromUrl(
+            Uri.parse(tokenRequestParameters.discoveryUrl),
+            callback,
+            allowInsecureConnections
+                ? InsecureConnectionBuilder.INSTANCE
+                : DefaultConnectionBuilder.INSTANCE);
+      } else {
+        AuthorizationServiceConfiguration.fetchFromIssuer(
+            Uri.parse(tokenRequestParameters.issuer),
+            callback,
+            allowInsecureConnections
+                ? InsecureConnectionBuilder.INSTANCE
+                : DefaultConnectionBuilder.INSTANCE);
+      }
     }
+  }
 
+  private void performAuthorization(
+      AuthorizationServiceConfiguration serviceConfiguration,
+      String clientId,
+      String redirectUrl,
+      ArrayList<String> scopes,
+      String loginHint,
+      String nonce,
+      Map<String, String> additionalParameters,
+      boolean exchangeCode,
+      ArrayList<String> promptValues,
+      String responseMode) {
+    AuthorizationRequest.Builder authRequestBuilder =
+        new AuthorizationRequest.Builder(
+            serviceConfiguration, clientId, ResponseTypeValues.CODE, Uri.parse(redirectUrl));
 
-    private void performAuthorization(AuthorizationServiceConfiguration serviceConfiguration, String clientId, String redirectUrl, ArrayList<String> scopes, String loginHint, String nonce, Map<String, String> additionalParameters, boolean exchangeCode, ArrayList<String> promptValues, String responseMode) {
-        AuthorizationRequest.Builder authRequestBuilder =
-                new AuthorizationRequest.Builder(
-                        serviceConfiguration,
-                        clientId,
-                        ResponseTypeValues.CODE,
-                        Uri.parse(redirectUrl));
-
-        if (scopes != null && !scopes.isEmpty()) {
-            authRequestBuilder.setScopes(scopes);
-        }
-
-        if (loginHint != null) {
-            authRequestBuilder.setLoginHint(loginHint);
-        }
-
-        if (promptValues != null && !promptValues.isEmpty()) {
-            authRequestBuilder.setPromptValues(promptValues);
-        }
-
-        if (responseMode != null) {
-            authRequestBuilder.setResponseMode(responseMode);
-        }
-
-        if (nonce != null) {
-            authRequestBuilder.setNonce(nonce);
-        }
-
-        if (additionalParameters != null && !additionalParameters.isEmpty()) {
-
-            if (additionalParameters.containsKey("ui_locales")) {
-                authRequestBuilder.setUiLocales(additionalParameters.get("ui_locales"));
-                additionalParameters.remove("ui_locales");
-            }
-
-            if (additionalParameters.containsKey("claims")) {
-                try {
-                    final JSONObject claimsAsJson = new JSONObject(additionalParameters.get("claims"));
-                    authRequestBuilder.setClaims(claimsAsJson);
-                    additionalParameters.remove("claims");
-                } catch (JSONException ex) {
-                    finishWithError(INVALID_CLAIMS_ERROR_CODE, ex.getLocalizedMessage(), ex);
-                    return;
-                }
-            }
-
-            authRequestBuilder.setAdditionalParameters(additionalParameters);
-        }
-
-        AuthorizationService authorizationService = allowInsecureConnections ? insecureAuthorizationService : defaultAuthorizationService;
-
-        try {
-            Intent authIntent = authorizationService.getAuthorizationRequestIntent(authRequestBuilder.build());
-            mainActivity.startActivityForResult(authIntent, exchangeCode ? RC_AUTH_EXCHANGE_CODE : RC_AUTH);
-        } catch (ActivityNotFoundException ex) {
-            finishWithError(NO_BROWSER_AVAILABLE_ERROR_CODE, NO_BROWSER_AVAILABLE_ERROR_FORMAT, ex);
-        }
+    if (scopes != null && !scopes.isEmpty()) {
+      authRequestBuilder.setScopes(scopes);
     }
 
-    private void performTokenRequest(AuthorizationServiceConfiguration serviceConfiguration, TokenRequestParameters tokenRequestParameters) {
-        TokenRequest.Builder builder = new TokenRequest.Builder(serviceConfiguration, tokenRequestParameters.clientId)
-                .setRefreshToken(tokenRequestParameters.refreshToken)
-                .setAuthorizationCode(tokenRequestParameters.authorizationCode)
-                .setCodeVerifier(tokenRequestParameters.codeVerifier)
-                .setRedirectUri(Uri.parse(tokenRequestParameters.redirectUrl));
-
-        if (tokenRequestParameters.nonce != null) {
-            builder.setNonce(tokenRequestParameters.nonce);
-        }
-        if (tokenRequestParameters.grantType != null) {
-            builder.setGrantType(tokenRequestParameters.grantType);
-        }
-        if (tokenRequestParameters.scopes != null) {
-            builder.setScopes(tokenRequestParameters.scopes);
-        }
-
-        if (tokenRequestParameters.additionalParameters != null && !tokenRequestParameters.additionalParameters.isEmpty()) {
-            builder.setAdditionalParameters(tokenRequestParameters.additionalParameters);
-        }
-
-        AuthorizationService.TokenResponseCallback tokenResponseCallback = new AuthorizationService.TokenResponseCallback() {
-            @Override
-            public void onTokenRequestCompleted(
-                    TokenResponse resp, AuthorizationException ex) {
-                if (resp != null) {
-                    Map<String, Object> responseMap = tokenResponseToMap(resp, null);
-                    finishWithSuccess(responseMap);
-                } else {
-                    finishWithTokenError(ex);
-                }
-            }
-        };
-
-        TokenRequest tokenRequest = builder.build();
-        AuthorizationService authorizationService = allowInsecureConnections ? insecureAuthorizationService : defaultAuthorizationService;
-        if (clientSecret == null) {
-            authorizationService.performTokenRequest(tokenRequest, tokenResponseCallback);
-        } else {
-            authorizationService.performTokenRequest(tokenRequest, new ClientSecretBasic(clientSecret), tokenResponseCallback);
-        }
+    if (loginHint != null) {
+      authRequestBuilder.setLoginHint(loginHint);
     }
 
-    private void handleEndSessionMethodCall(Map<String, Object> arguments) {
-        final EndSessionRequestParameters endSessionRequestParameters = processEndSessionRequestArguments(arguments);
-        if (endSessionRequestParameters.serviceConfigurationParameters != null) {
-            AuthorizationServiceConfiguration serviceConfiguration = processServiceConfigurationParameters(endSessionRequestParameters.serviceConfigurationParameters);
-            performEndSessionRequest(serviceConfiguration, endSessionRequestParameters);
-        } else {
-            AuthorizationServiceConfiguration.RetrieveConfigurationCallback callback = new AuthorizationServiceConfiguration.RetrieveConfigurationCallback() {
-                @Override
-                public void onFetchConfigurationCompleted(@Nullable AuthorizationServiceConfiguration serviceConfiguration, @Nullable AuthorizationException ex) {
-                    if (ex == null) {
-                        performEndSessionRequest(serviceConfiguration, endSessionRequestParameters);
-                    } else {
-                        finishWithDiscoveryError(ex);
-                    }
-                }
-            };
+    if (promptValues != null && !promptValues.isEmpty()) {
+      authRequestBuilder.setPromptValues(promptValues);
+    }
 
-            if (endSessionRequestParameters.discoveryUrl != null) {
-                AuthorizationServiceConfiguration.fetchFromUrl(Uri.parse(endSessionRequestParameters.discoveryUrl), callback, allowInsecureConnections ? InsecureConnectionBuilder.INSTANCE : DefaultConnectionBuilder.INSTANCE);
-            } else {
-                AuthorizationServiceConfiguration.fetchFromIssuer(Uri.parse(endSessionRequestParameters.issuer), callback, allowInsecureConnections ? InsecureConnectionBuilder.INSTANCE : DefaultConnectionBuilder.INSTANCE);
-            }
-        }
+    if (responseMode != null) {
+      authRequestBuilder.setResponseMode(responseMode);
     }
 
-    private void performEndSessionRequest(AuthorizationServiceConfiguration serviceConfiguration, final EndSessionRequestParameters endSessionRequestParameters) {
-        EndSessionRequest.Builder endSessionRequestBuilder = new EndSessionRequest.Builder(serviceConfiguration);
-        if (endSessionRequestParameters.idTokenHint != null) {
-            endSessionRequestBuilder.setIdTokenHint(endSessionRequestParameters.idTokenHint);
-        }
+    if (nonce != null) {
+      authRequestBuilder.setNonce(nonce);
+    }
 
-        if (endSessionRequestParameters.postLogoutRedirectUrl != null) {
-            endSessionRequestBuilder.setPostLogoutRedirectUri(Uri.parse(endSessionRequestParameters.postLogoutRedirectUrl));
-        }
+    if (additionalParameters != null && !additionalParameters.isEmpty()) {
 
-        if (endSessionRequestParameters.state != null) {
-            endSessionRequestBuilder.setState(endSessionRequestParameters.state);
-        }
+      if (additionalParameters.containsKey("ui_locales")) {
+        authRequestBuilder.setUiLocales(additionalParameters.get("ui_locales"));
+        additionalParameters.remove("ui_locales");
+      }
 
-        if (endSessionRequestParameters.additionalParameters != null) {
-            endSessionRequestBuilder.setAdditionalParameters(endSessionRequestParameters.additionalParameters);
+      if (additionalParameters.containsKey("claims")) {
+        try {
+          final JSONObject claimsAsJson = new JSONObject(additionalParameters.get("claims"));
+          authRequestBuilder.setClaims(claimsAsJson);
+          additionalParameters.remove("claims");
+        } catch (JSONException ex) {
+          finishWithError(INVALID_CLAIMS_ERROR_CODE, ex.getLocalizedMessage(), ex);
+          return;
         }
+      }
 
-        final EndSessionRequest endSessionRequest = endSessionRequestBuilder.build();
-        AuthorizationService authorizationService = allowInsecureConnections ? insecureAuthorizationService : defaultAuthorizationService;
-        Intent endSessionIntent = authorizationService.getEndSessionRequestIntent(endSessionRequest);
-        mainActivity.startActivityForResult(endSessionIntent, RC_END_SESSION);
-    }
-
-    private void finishWithTokenError(AuthorizationException ex) {
-        finishWithError(TOKEN_ERROR_CODE, String.format(TOKEN_ERROR_MESSAGE_FORMAT, ex.error, ex.errorDescription), ex);
+      authRequestBuilder.setAdditionalParameters(additionalParameters);
     }
 
+    AuthorizationService authorizationService =
+        allowInsecureConnections ? insecureAuthorizationService : defaultAuthorizationService;
 
-    private void finishWithSuccess(Object data) {
-        if (pendingOperation != null) {
-            pendingOperation.result.success(data);
-            pendingOperation = null;
-        }
+    try {
+      Intent authIntent =
+          authorizationService.getAuthorizationRequestIntent(authRequestBuilder.build());
+      mainActivity.startActivityForResult(
+          authIntent, exchangeCode ? RC_AUTH_EXCHANGE_CODE : RC_AUTH);
+    } catch (ActivityNotFoundException ex) {
+      finishWithError(NO_BROWSER_AVAILABLE_ERROR_CODE, NO_BROWSER_AVAILABLE_ERROR_FORMAT, ex);
     }
+  }
 
-    private void finishWithError(String errorCode, String errorMessage, @Nullable Exception cause) {
-        if (pendingOperation != null) {
-            pendingOperation.result.error(errorCode, errorMessage, createErrorMap(cause));
-            pendingOperation = null;
-        }
-    }
+  private void performTokenRequest(
+      AuthorizationServiceConfiguration serviceConfiguration,
+      TokenRequestParameters tokenRequestParameters) {
+    TokenRequest.Builder builder =
+        new TokenRequest.Builder(serviceConfiguration, tokenRequestParameters.clientId)
+            .setRefreshToken(tokenRequestParameters.refreshToken)
+            .setAuthorizationCode(tokenRequestParameters.authorizationCode)
+            .setCodeVerifier(tokenRequestParameters.codeVerifier)
+            .setRedirectUri(Uri.parse(tokenRequestParameters.redirectUrl));
 
-    private void finishWithDiscoveryError(AuthorizationException ex) {
-        finishWithError(DISCOVERY_ERROR_CODE, String.format(DISCOVERY_ERROR_MESSAGE_FORMAT, ex.error, ex.errorDescription), ex);
+    if (tokenRequestParameters.nonce != null) {
+      builder.setNonce(tokenRequestParameters.nonce);
     }
-
-    private void finishWithEndSessionError(AuthorizationException ex) {
-        finishWithError(END_SESSION_ERROR_CODE, String.format(END_SESSION_ERROR_MESSAGE_FORMAT, ex.error, ex.errorDescription), ex);
+    if (tokenRequestParameters.grantType != null) {
+      builder.setGrantType(tokenRequestParameters.grantType);
     }
-
-    private Map<String, Object> createErrorMap(@Nullable Exception exception) {
-        @Nullable AuthorizationException authException = exception instanceof AuthorizationException ? (AuthorizationException) exception : null;
-        Map<String, Object> responseMap = new HashMap<>();
-        responseMap.put("legacy_error_details", getCauseFromException(exception));
-
-        if (authException != null) {
-            boolean userDidCancel = authException.equals(AuthorizationException.GeneralErrors.USER_CANCELED_AUTH_FLOW);
-            responseMap.put("type", String.valueOf(authException.type));
-            responseMap.put("code", String.valueOf(authException.code));
-            responseMap.put("error", authException.error);
-            responseMap.put("error_description", authException.errorDescription);
-            responseMap.put("error_uri", authException.errorUri == null ? null : authException.errorUri.toString());
-            responseMap.put("root_cause_debug_description", authException.getCause() == null ? null : authException.getCause().toString());
-            responseMap.put("error_debug_description", authException.toString());
-            responseMap.put("user_did_cancel", String.valueOf(userDidCancel));
-        }
-        return responseMap;
+    if (tokenRequestParameters.scopes != null) {
+      builder.setScopes(tokenRequestParameters.scopes);
     }
 
-    private String getCauseFromException(@Nullable Exception ex) {
-        if (ex == null) {
-            return "";
-        }
-        final Throwable cause = ex.getCause();
-        return cause != null ? cause.getMessage() : null;
+    if (tokenRequestParameters.additionalParameters != null
+        && !tokenRequestParameters.additionalParameters.isEmpty()) {
+      builder.setAdditionalParameters(tokenRequestParameters.additionalParameters);
     }
 
-
-    @Override
-    public boolean onActivityResult(int requestCode, int resultCode, Intent intent) {
-        if (pendingOperation == null) {
-            return false;
-        }
-        if (requestCode == RC_AUTH_EXCHANGE_CODE || requestCode == RC_AUTH) {
-            if (intent == null) {
-                finishWithError(NULL_INTENT_ERROR_CODE, NULL_INTENT_ERROR_FORMAT, null);
+    AuthorizationService.TokenResponseCallback tokenResponseCallback =
+        new AuthorizationService.TokenResponseCallback() {
+          @Override
+          public void onTokenRequestCompleted(TokenResponse resp, AuthorizationException ex) {
+            if (resp != null) {
+              Map<String, Object> responseMap = tokenResponseToMap(resp, null);
+              finishWithSuccess(responseMap);
             } else {
-                final AuthorizationResponse authResponse = AuthorizationResponse.fromIntent(intent);
-                AuthorizationException ex = AuthorizationException.fromIntent(intent);
-                processAuthorizationData(authResponse, ex, requestCode == RC_AUTH_EXCHANGE_CODE);
+              finishWithTokenError(ex);
             }
-            return true;
-        }
-        if (requestCode == RC_END_SESSION) {
-            if (intent == null) {
-                finishWithError(NULL_INTENT_ERROR_CODE, NULL_INTENT_ERROR_FORMAT, null);
-            } else {
-                final EndSessionResponse endSessionResponse = EndSessionResponse.fromIntent(intent);
-                AuthorizationException ex = AuthorizationException.fromIntent(intent);
-                if (ex != null) {
-                    finishWithEndSessionError(ex);
-                } else {
-                    Map<String, Object> responseMap = new HashMap<>();
-                    responseMap.put("state", endSessionResponse.state);
-                    finishWithSuccess(responseMap);
-                }
+          }
+        };
+
+    TokenRequest tokenRequest = builder.build();
+    AuthorizationService authorizationService =
+        allowInsecureConnections ? insecureAuthorizationService : defaultAuthorizationService;
+    if (clientSecret == null) {
+      authorizationService.performTokenRequest(tokenRequest, tokenResponseCallback);
+    } else {
+      authorizationService.performTokenRequest(
+          tokenRequest, new ClientSecretBasic(clientSecret), tokenResponseCallback);
+    }
+  }
+
+  private void handleEndSessionMethodCall(Map<String, Object> arguments) {
+    final EndSessionRequestParameters endSessionRequestParameters =
+        processEndSessionRequestArguments(arguments);
+    if (endSessionRequestParameters.serviceConfigurationParameters != null) {
+      AuthorizationServiceConfiguration serviceConfiguration =
+          processServiceConfigurationParameters(
+              endSessionRequestParameters.serviceConfigurationParameters);
+      performEndSessionRequest(serviceConfiguration, endSessionRequestParameters);
+    } else {
+      AuthorizationServiceConfiguration.RetrieveConfigurationCallback callback =
+          new AuthorizationServiceConfiguration.RetrieveConfigurationCallback() {
+            @Override
+            public void onFetchConfigurationCompleted(
+                @Nullable AuthorizationServiceConfiguration serviceConfiguration,
+                @Nullable AuthorizationException ex) {
+              if (ex == null) {
+                performEndSessionRequest(serviceConfiguration, endSessionRequestParameters);
+              } else {
+                finishWithDiscoveryError(ex);
+              }
             }
-            return true;
+          };
+
+      if (endSessionRequestParameters.discoveryUrl != null) {
+        AuthorizationServiceConfiguration.fetchFromUrl(
+            Uri.parse(endSessionRequestParameters.discoveryUrl),
+            callback,
+            allowInsecureConnections
+                ? InsecureConnectionBuilder.INSTANCE
+                : DefaultConnectionBuilder.INSTANCE);
+      } else {
+        AuthorizationServiceConfiguration.fetchFromIssuer(
+            Uri.parse(endSessionRequestParameters.issuer),
+            callback,
+            allowInsecureConnections
+                ? InsecureConnectionBuilder.INSTANCE
+                : DefaultConnectionBuilder.INSTANCE);
+      }
+    }
+  }
+
+  private void performEndSessionRequest(
+      AuthorizationServiceConfiguration serviceConfiguration,
+      final EndSessionRequestParameters endSessionRequestParameters) {
+    EndSessionRequest.Builder endSessionRequestBuilder =
+        new EndSessionRequest.Builder(serviceConfiguration);
+    if (endSessionRequestParameters.idTokenHint != null) {
+      endSessionRequestBuilder.setIdTokenHint(endSessionRequestParameters.idTokenHint);
+    }
+
+    if (endSessionRequestParameters.postLogoutRedirectUrl != null) {
+      endSessionRequestBuilder.setPostLogoutRedirectUri(
+          Uri.parse(endSessionRequestParameters.postLogoutRedirectUrl));
+    }
+
+    if (endSessionRequestParameters.state != null) {
+      endSessionRequestBuilder.setState(endSessionRequestParameters.state);
+    }
+
+    if (endSessionRequestParameters.additionalParameters != null) {
+      endSessionRequestBuilder.setAdditionalParameters(
+          endSessionRequestParameters.additionalParameters);
+    }
+
+    final EndSessionRequest endSessionRequest = endSessionRequestBuilder.build();
+    AuthorizationService authorizationService =
+        allowInsecureConnections ? insecureAuthorizationService : defaultAuthorizationService;
+    Intent endSessionIntent = authorizationService.getEndSessionRequestIntent(endSessionRequest);
+    mainActivity.startActivityForResult(endSessionIntent, RC_END_SESSION);
+  }
+
+  private void finishWithTokenError(AuthorizationException ex) {
+    finishWithError(
+        TOKEN_ERROR_CODE,
+        String.format(TOKEN_ERROR_MESSAGE_FORMAT, ex.error, ex.errorDescription),
+        ex);
+  }
+
+  private void finishWithSuccess(Object data) {
+    if (pendingOperation != null) {
+      pendingOperation.result.success(data);
+      pendingOperation = null;
+    }
+  }
+
+  private void finishWithError(String errorCode, String errorMessage, @Nullable Exception cause) {
+    if (pendingOperation != null) {
+      pendingOperation.result.error(errorCode, errorMessage, createErrorMap(cause));
+      pendingOperation = null;
+    }
+  }
+
+  private void finishWithDiscoveryError(AuthorizationException ex) {
+    finishWithError(
+        DISCOVERY_ERROR_CODE,
+        String.format(DISCOVERY_ERROR_MESSAGE_FORMAT, ex.error, ex.errorDescription),
+        ex);
+  }
+
+  private void finishWithEndSessionError(AuthorizationException ex) {
+    finishWithError(
+        END_SESSION_ERROR_CODE,
+        String.format(END_SESSION_ERROR_MESSAGE_FORMAT, ex.error, ex.errorDescription),
+        ex);
+  }
+
+  private Map<String, Object> createErrorMap(@Nullable Exception exception) {
+    @Nullable
+    AuthorizationException authException =
+        exception instanceof AuthorizationException ? (AuthorizationException) exception : null;
+    Map<String, Object> responseMap = new HashMap<>();
+    responseMap.put("legacy_error_details", getCauseFromException(exception));
+
+    if (authException != null) {
+      boolean userDidCancel =
+          authException.equals(AuthorizationException.GeneralErrors.USER_CANCELED_AUTH_FLOW);
+      responseMap.put("type", String.valueOf(authException.type));
+      responseMap.put("code", String.valueOf(authException.code));
+      responseMap.put("error", authException.error);
+      responseMap.put("error_description", authException.errorDescription);
+      responseMap.put(
+          "error_uri", authException.errorUri == null ? null : authException.errorUri.toString());
+      responseMap.put(
+          "root_cause_debug_description",
+          authException.getCause() == null ? null : authException.getCause().toString());
+      responseMap.put("error_debug_description", authException.toString());
+      responseMap.put("user_did_cancel", String.valueOf(userDidCancel));
+    }
+    return responseMap;
+  }
+
+  private String getCauseFromException(@Nullable Exception ex) {
+    if (ex == null) {
+      return "";
+    }
+    final Throwable cause = ex.getCause();
+    return cause != null ? cause.getMessage() : null;
+  }
+
+  @Override
+  public boolean onActivityResult(int requestCode, int resultCode, Intent intent) {
+    if (pendingOperation == null) {
+      return false;
+    }
+    if (requestCode == RC_AUTH_EXCHANGE_CODE || requestCode == RC_AUTH) {
+      if (intent == null) {
+        finishWithError(NULL_INTENT_ERROR_CODE, NULL_INTENT_ERROR_FORMAT, null);
+      } else {
+        final AuthorizationResponse authResponse = AuthorizationResponse.fromIntent(intent);
+        AuthorizationException ex = AuthorizationException.fromIntent(intent);
+        processAuthorizationData(authResponse, ex, requestCode == RC_AUTH_EXCHANGE_CODE);
+      }
+      return true;
+    }
+    if (requestCode == RC_END_SESSION) {
+      if (intent == null) {
+        finishWithError(NULL_INTENT_ERROR_CODE, NULL_INTENT_ERROR_FORMAT, null);
+      } else {
+        final EndSessionResponse endSessionResponse = EndSessionResponse.fromIntent(intent);
+        AuthorizationException ex = AuthorizationException.fromIntent(intent);
+        if (ex != null) {
+          finishWithEndSessionError(ex);
+        } else {
+          Map<String, Object> responseMap = new HashMap<>();
+          responseMap.put("state", endSessionResponse.state);
+          finishWithSuccess(responseMap);
+        }
+      }
+      return true;
+    }
+    return false;
+  }
+
+  private void processAuthorizationData(
+      final AuthorizationResponse authResponse,
+      AuthorizationException authException,
+      boolean exchangeCode) {
+    if (authException == null) {
+      if (exchangeCode) {
+        AppAuthConfiguration.Builder authConfigBuilder = new AppAuthConfiguration.Builder();
+        if (allowInsecureConnections) {
+          authConfigBuilder.setConnectionBuilder(InsecureConnectionBuilder.INSTANCE);
+          authConfigBuilder.setSkipIssuerHttpsCheck(true);
         }
-        return false;
-    }
-
-    private void processAuthorizationData(final AuthorizationResponse authResponse, AuthorizationException authException, boolean exchangeCode) {
-        if (authException == null) {
-            if (exchangeCode) {
-                AppAuthConfiguration.Builder authConfigBuilder = new AppAuthConfiguration.Builder();
-                if (allowInsecureConnections) {
-                    authConfigBuilder.setConnectionBuilder(InsecureConnectionBuilder.INSTANCE);
-                    authConfigBuilder.setSkipIssuerHttpsCheck(true);
-                }
 
-                AuthorizationService authService = new AuthorizationService(applicationContext, authConfigBuilder.build());
-                AuthorizationService.TokenResponseCallback tokenResponseCallback = new AuthorizationService.TokenResponseCallback() {
-                    @Override
-                    public void onTokenRequestCompleted(
-                            TokenResponse resp, AuthorizationException ex) {
-                        if (resp != null) {
-                            finishWithSuccess(tokenResponseToMap(resp, authResponse));
-                        } else {
-                            finishWithError(AUTHORIZE_AND_EXCHANGE_CODE_ERROR_CODE, String.format(AUTHORIZE_ERROR_MESSAGE_FORMAT, ex.error, ex.errorDescription), ex);
-                        }
-                    }
-                };
-                if (clientSecret == null) {
-                    authService.performTokenRequest(authResponse.createTokenExchangeRequest(), tokenResponseCallback);
+        AuthorizationService authService =
+            new AuthorizationService(applicationContext, authConfigBuilder.build());
+        AuthorizationService.TokenResponseCallback tokenResponseCallback =
+            new AuthorizationService.TokenResponseCallback() {
+              @Override
+              public void onTokenRequestCompleted(TokenResponse resp, AuthorizationException ex) {
+                if (resp != null) {
+                  finishWithSuccess(tokenResponseToMap(resp, authResponse));
                 } else {
-                    authService.performTokenRequest(authResponse.createTokenExchangeRequest(), new ClientSecretBasic(clientSecret), tokenResponseCallback);
+                  finishWithError(
+                      AUTHORIZE_AND_EXCHANGE_CODE_ERROR_CODE,
+                      String.format(AUTHORIZE_ERROR_MESSAGE_FORMAT, ex.error, ex.errorDescription),
+                      ex);
                 }
-            } else {
-                finishWithSuccess(authorizationResponseToMap(authResponse));
-            }
+              }
+            };
+        if (clientSecret == null) {
+          authService.performTokenRequest(
+              authResponse.createTokenExchangeRequest(), tokenResponseCallback);
         } else {
-            finishWithError(exchangeCode ? AUTHORIZE_AND_EXCHANGE_CODE_ERROR_CODE : AUTHORIZE_ERROR_CODE, String.format(AUTHORIZE_ERROR_MESSAGE_FORMAT, authException.error, authException.errorDescription), authException);
-        }
-    }
-
-    private Map<String, Object> tokenResponseToMap(TokenResponse tokenResponse, AuthorizationResponse authResponse) {
-        Map<String, Object> responseMap = new HashMap<>();
-        responseMap.put("accessToken", tokenResponse.accessToken);
-        responseMap.put("accessTokenExpirationTime", tokenResponse.accessTokenExpirationTime != null ? tokenResponse.accessTokenExpirationTime.doubleValue() : null);
-        responseMap.put("refreshToken", tokenResponse.refreshToken);
-        responseMap.put("idToken", tokenResponse.idToken);
-        responseMap.put("tokenType", tokenResponse.tokenType);
-        responseMap.put("scopes", tokenResponse.scope != null ? Arrays.asList(tokenResponse.scope.split(" ")) : null);
-        if (authResponse != null) {
-            responseMap.put("authorizationAdditionalParameters", authResponse.additionalParameters);
-        }
-        responseMap.put("tokenAdditionalParameters", tokenResponse.additionalParameters);
-
-        return responseMap;
-    }
-
-    private Map<String, Object> authorizationResponseToMap(AuthorizationResponse authResponse) {
-        Map<String, Object> responseMap = new HashMap<>();
-        responseMap.put("codeVerifier", authResponse.request.codeVerifier);
-        responseMap.put("nonce", authResponse.request.nonce);
-        responseMap.put("authorizationCode", authResponse.authorizationCode);
-        responseMap.put("authorizationAdditionalParameters", authResponse.additionalParameters);
-        return responseMap;
-    }
-
-    private class PendingOperation {
-        final String method;
-        final Result result;
-
-        PendingOperation(String method, Result result) {
-            this.method = method;
-            this.result = result;
-        }
-    }
-
-    private class TokenRequestParameters {
-        final String clientId;
-        final String issuer;
-        final String discoveryUrl;
-        final ArrayList<String> scopes;
-        final String redirectUrl;
-        final String refreshToken;
-        final String grantType;
-        final String codeVerifier;
-        final String nonce;
-        final String authorizationCode;
-        final Map<String, String> serviceConfigurationParameters;
-        final Map<String, String> additionalParameters;
-
-        private TokenRequestParameters(String clientId, String issuer, String discoveryUrl, ArrayList<String> scopes, String redirectUrl, String refreshToken, String authorizationCode, String codeVerifier, String nonce, String grantType, Map<String, String> serviceConfigurationParameters, Map<String, String> additionalParameters) {
-            this.clientId = clientId;
-            this.issuer = issuer;
-            this.discoveryUrl = discoveryUrl;
-            this.scopes = scopes;
-            this.redirectUrl = redirectUrl;
-            this.refreshToken = refreshToken;
-            this.authorizationCode = authorizationCode;
-            this.codeVerifier = codeVerifier;
-            this.nonce = nonce;
-            this.grantType = grantType;
-            this.serviceConfigurationParameters = serviceConfigurationParameters;
-            this.additionalParameters = additionalParameters;
-        }
-    }
-
-    private class EndSessionRequestParameters {
-        final String idTokenHint;
-        final String postLogoutRedirectUrl;
-        final String state;
-        final String issuer;
-        final String discoveryUrl;
-        final boolean allowInsecureConnections;
-        final Map<String, String> serviceConfigurationParameters;
-        final Map<String, String> additionalParameters;
-
-        private EndSessionRequestParameters(String idTokenHint, String postLogoutRedirectUrl, String state, String issuer, String discoveryUrl, boolean allowInsecureConnections, Map<String, String> serviceConfigurationParameters, Map<String, String> additionalParameters) {
-            this.idTokenHint = idTokenHint;
-            this.postLogoutRedirectUrl = postLogoutRedirectUrl;
-            this.state = state;
-            this.issuer = issuer;
-            this.discoveryUrl = discoveryUrl;
-            this.allowInsecureConnections = allowInsecureConnections;
-            this.serviceConfigurationParameters = serviceConfigurationParameters;
-            this.additionalParameters = additionalParameters;
-        }
-    }
-
-    private class AuthorizationTokenRequestParameters extends TokenRequestParameters {
-        final String loginHint;
-        final ArrayList<String> promptValues;
-        final String responseMode;
-
-        private AuthorizationTokenRequestParameters(String clientId, String issuer, String discoveryUrl, ArrayList<String> scopes, String redirectUrl, Map<String, String> serviceConfigurationParameters, Map<String, String> additionalParameters, String loginHint, String nonce, ArrayList<String> promptValues, String responseMode) {
-            super(clientId, issuer, discoveryUrl, scopes, redirectUrl, null, null, null, nonce, null, serviceConfigurationParameters, additionalParameters);
-            this.loginHint = loginHint;
-            this.promptValues = promptValues;
-            this.responseMode = responseMode;
-        }
-    }
-
+          authService.performTokenRequest(
+              authResponse.createTokenExchangeRequest(),
+              new ClientSecretBasic(clientSecret),
+              tokenResponseCallback);
+        }
+      } else {
+        finishWithSuccess(authorizationResponseToMap(authResponse));
+      }
+    } else {
+      finishWithError(
+          exchangeCode ? AUTHORIZE_AND_EXCHANGE_CODE_ERROR_CODE : AUTHORIZE_ERROR_CODE,
+          String.format(
+              AUTHORIZE_ERROR_MESSAGE_FORMAT, authException.error, authException.errorDescription),
+          authException);
+    }
+  }
+
+  private Map<String, Object> tokenResponseToMap(
+      TokenResponse tokenResponse, AuthorizationResponse authResponse) {
+    Map<String, Object> responseMap = new HashMap<>();
+    responseMap.put("accessToken", tokenResponse.accessToken);
+    responseMap.put(
+        "accessTokenExpirationTime",
+        tokenResponse.accessTokenExpirationTime != null
+            ? tokenResponse.accessTokenExpirationTime.doubleValue()
+            : null);
+    responseMap.put("refreshToken", tokenResponse.refreshToken);
+    responseMap.put("idToken", tokenResponse.idToken);
+    responseMap.put("tokenType", tokenResponse.tokenType);
+    responseMap.put(
+        "scopes",
+        tokenResponse.scope != null ? Arrays.asList(tokenResponse.scope.split(" ")) : null);
+    if (authResponse != null) {
+      responseMap.put("authorizationAdditionalParameters", authResponse.additionalParameters);
+    }
+    responseMap.put("tokenAdditionalParameters", tokenResponse.additionalParameters);
+
+    return responseMap;
+  }
+
+  private Map<String, Object> authorizationResponseToMap(AuthorizationResponse authResponse) {
+    Map<String, Object> responseMap = new HashMap<>();
+    responseMap.put("codeVerifier", authResponse.request.codeVerifier);
+    responseMap.put("nonce", authResponse.request.nonce);
+    responseMap.put("authorizationCode", authResponse.authorizationCode);
+    responseMap.put("authorizationAdditionalParameters", authResponse.additionalParameters);
+    return responseMap;
+  }
+
+  private class PendingOperation {
+    final String method;
+    final Result result;
+
+    PendingOperation(String method, Result result) {
+      this.method = method;
+      this.result = result;
+    }
+  }
+
+  private class TokenRequestParameters {
+    final String clientId;
+    final String issuer;
+    final String discoveryUrl;
+    final ArrayList<String> scopes;
+    final String redirectUrl;
+    final String refreshToken;
+    final String grantType;
+    final String codeVerifier;
+    final String nonce;
+    final String authorizationCode;
+    final Map<String, String> serviceConfigurationParameters;
+    final Map<String, String> additionalParameters;
+
+    private TokenRequestParameters(
+        String clientId,
+        String issuer,
+        String discoveryUrl,
+        ArrayList<String> scopes,
+        String redirectUrl,
+        String refreshToken,
+        String authorizationCode,
+        String codeVerifier,
+        String nonce,
+        String grantType,
+        Map<String, String> serviceConfigurationParameters,
+        Map<String, String> additionalParameters) {
+      this.clientId = clientId;
+      this.issuer = issuer;
+      this.discoveryUrl = discoveryUrl;
+      this.scopes = scopes;
+      this.redirectUrl = redirectUrl;
+      this.refreshToken = refreshToken;
+      this.authorizationCode = authorizationCode;
+      this.codeVerifier = codeVerifier;
+      this.nonce = nonce;
+      this.grantType = grantType;
+      this.serviceConfigurationParameters = serviceConfigurationParameters;
+      this.additionalParameters = additionalParameters;
+    }
+  }
+
+  private class EndSessionRequestParameters {
+    final String idTokenHint;
+    final String postLogoutRedirectUrl;
+    final String state;
+    final String issuer;
+    final String discoveryUrl;
+    final boolean allowInsecureConnections;
+    final Map<String, String> serviceConfigurationParameters;
+    final Map<String, String> additionalParameters;
+
+    private EndSessionRequestParameters(
+        String idTokenHint,
+        String postLogoutRedirectUrl,
+        String state,
+        String issuer,
+        String discoveryUrl,
+        boolean allowInsecureConnections,
+        Map<String, String> serviceConfigurationParameters,
+        Map<String, String> additionalParameters) {
+      this.idTokenHint = idTokenHint;
+      this.postLogoutRedirectUrl = postLogoutRedirectUrl;
+      this.state = state;
+      this.issuer = issuer;
+      this.discoveryUrl = discoveryUrl;
+      this.allowInsecureConnections = allowInsecureConnections;
+      this.serviceConfigurationParameters = serviceConfigurationParameters;
+      this.additionalParameters = additionalParameters;
+    }
+  }
+
+  private class AuthorizationTokenRequestParameters extends TokenRequestParameters {
+    final String loginHint;
+    final ArrayList<String> promptValues;
+    final String responseMode;
+
+    private AuthorizationTokenRequestParameters(
+        String clientId,
+        String issuer,
+        String discoveryUrl,
+        ArrayList<String> scopes,
+        String redirectUrl,
+        Map<String, String> serviceConfigurationParameters,
+        Map<String, String> additionalParameters,
+        String loginHint,
+        String nonce,
+        ArrayList<String> promptValues,
+        String responseMode) {
+      super(
+          clientId,
+          issuer,
+          discoveryUrl,
+          scopes,
+          redirectUrl,
+          null,
+          null,
+          null,
+          nonce,
+          null,
+          serviceConfigurationParameters,
+          additionalParameters);
+      this.loginHint = loginHint;
+      this.promptValues = promptValues;
+      this.responseMode = responseMode;
+    }
+  }
 }
diff --git a/flutter_appauth/android/src/main/java/io/crossingthestreams/flutterappauth/InsecureConnectionBuilder.java b/flutter_appauth/android/src/main/java/io/crossingthestreams/flutterappauth/InsecureConnectionBuilder.java
index b46d730c..a52cc368 100644
--- a/flutter_appauth/android/src/main/java/io/crossingthestreams/flutterappauth/InsecureConnectionBuilder.java
+++ b/flutter_appauth/android/src/main/java/io/crossingthestreams/flutterappauth/InsecureConnectionBuilder.java
@@ -12,13 +12,13 @@
 
 public class InsecureConnectionBuilder implements ConnectionBuilder {
 
-    public static final InsecureConnectionBuilder INSTANCE = new InsecureConnectionBuilder();
+  public static final InsecureConnectionBuilder INSTANCE = new InsecureConnectionBuilder();
 
-    private InsecureConnectionBuilder() { }
+  private InsecureConnectionBuilder() {}
 
-    @NonNull
-    @Override
-    public HttpURLConnection openConnection(@NonNull Uri uri) throws IOException {
-        return (HttpURLConnection) new URL(uri.toString()).openConnection();
-    }
+  @NonNull
+  @Override
+  public HttpURLConnection openConnection(@NonNull Uri uri) throws IOException {
+    return (HttpURLConnection) new URL(uri.toString()).openConnection();
+  }
 }
diff --git a/flutter_appauth/ios/Classes/AppAuthIOSAuthorization.h b/flutter_appauth/ios/Classes/AppAuthIOSAuthorization.h
index 9c80bc5d..4635170e 100644
--- a/flutter_appauth/ios/Classes/AppAuthIOSAuthorization.h
+++ b/flutter_appauth/ios/Classes/AppAuthIOSAuthorization.h
@@ -1,8 +1,8 @@
-#import <AppAuth/AppAuth.h>
-#import <Flutter/Flutter.h>
+#import "FlutterAppAuth.h"
 #import "OIDExternalUserAgentIOSNoSSO.h"
 #import "OIDExternalUserAgentIOSSafariViewController.h"
-#import "FlutterAppAuth.h"
+#import <AppAuth/AppAuth.h>
+#import <Flutter/Flutter.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
diff --git a/flutter_appauth/ios/Classes/AppAuthIOSAuthorization.m b/flutter_appauth/ios/Classes/AppAuthIOSAuthorization.m
index 7d1737e9..e2ecb71f 100644
--- a/flutter_appauth/ios/Classes/AppAuthIOSAuthorization.m
+++ b/flutter_appauth/ios/Classes/AppAuthIOSAuthorization.m
@@ -2,96 +2,193 @@
 
 @implementation AppAuthIOSAuthorization
 
-- (id<OIDExternalUserAgentSession>) performAuthorization:(OIDServiceConfiguration *)serviceConfiguration clientId:(NSString*)clientId clientSecret:(NSString*)clientSecret scopes:(NSArray *)scopes redirectUrl:(NSString*)redirectUrl additionalParameters:(NSDictionary *)additionalParameters externalUserAgent:(NSNumber*)externalUserAgent 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
+       externalUserAgent:(NSNumber *)externalUserAgent
+                  result:(FlutterResult)result
+            exchangeCode:(BOOL)exchangeCode
+                   nonce:(NSString *)nonce {
   NSString *codeVerifier = [OIDAuthorizationRequest generateCodeVerifier];
-  NSString *codeChallenge = [OIDAuthorizationRequest codeChallengeS256ForVerifier:codeVerifier];
+  NSString *codeChallenge =
+      [OIDAuthorizationRequest codeChallengeS256ForVerifier:codeVerifier];
 
-  OIDAuthorizationRequest *request =
-  [[OIDAuthorizationRequest alloc] initWithConfiguration:serviceConfiguration
-                                                clientId:clientId
-                                            clientSecret:clientSecret
-                                                   scope:[OIDScopeUtilities scopesWithArray:scopes]
-                                             redirectURL:[NSURL URLWithString:redirectUrl]
-                                            responseType:OIDResponseTypeCode
-                                                   state:[OIDAuthorizationRequest generateState]
-                                                   nonce: nonce != nil ? nonce : [OIDAuthorizationRequest generateState]
-                                            codeVerifier:codeVerifier
-                                           codeChallenge:codeChallenge
-                                     codeChallengeMethod:OIDOAuthorizationRequestCodeChallengeMethodS256
-                                    additionalParameters:additionalParameters];
+  OIDAuthorizationRequest *request = [[OIDAuthorizationRequest alloc]
+      initWithConfiguration:serviceConfiguration
+                   clientId:clientId
+               clientSecret:clientSecret
+                      scope:[OIDScopeUtilities scopesWithArray:scopes]
+                redirectURL:[NSURL URLWithString:redirectUrl]
+               responseType:OIDResponseTypeCode
+                      state:[OIDAuthorizationRequest generateState]
+                      nonce:nonce != nil
+                                ? nonce
+                                : [OIDAuthorizationRequest generateState]
+               codeVerifier:codeVerifier
+              codeChallenge:codeChallenge
+        codeChallengeMethod:OIDOAuthorizationRequestCodeChallengeMethodS256
+       additionalParameters:additionalParameters];
   UIViewController *rootViewController = [self rootViewController];
-  if(exchangeCode) {
-      id<OIDExternalUserAgent> agent = [self userAgentWithViewController:rootViewController externalUserAgent:externalUserAgent];
-      return [OIDAuthState authStateByPresentingAuthorizationRequest:request externalUserAgent:agent callback:^(OIDAuthState *_Nullable authState,
-                                                                                                                                                  NSError *_Nullable error) {
-          if(authState) {
-              result([FlutterAppAuth processResponses:authState.lastTokenResponse authResponse:authState.lastAuthorizationResponse]);
-              
-          } else {
-              [FlutterAppAuth finishWithError:AUTHORIZE_AND_EXCHANGE_CODE_ERROR_CODE message:[FlutterAppAuth formatMessageWithError:AUTHORIZE_ERROR_MESSAGE_FORMAT error:error] result:result error:error];
-          }
-      }];
+  if (exchangeCode) {
+    id<OIDExternalUserAgent> agent =
+        [self userAgentWithViewController:rootViewController
+                        externalUserAgent:externalUserAgent];
+    return [OIDAuthState
+        authStateByPresentingAuthorizationRequest:request
+                                externalUserAgent:agent
+                                         callback:^(
+                                             OIDAuthState *_Nullable authState,
+                                             NSError *_Nullable error) {
+                                           if (authState) {
+                                             result([FlutterAppAuth
+                                                 processResponses:
+                                                     authState.lastTokenResponse
+                                                     authResponse:
+                                                         authState
+                                                             .lastAuthorizationResponse]);
+
+                                           } else {
+                                             [FlutterAppAuth
+                                                 finishWithError:
+                                                     AUTHORIZE_AND_EXCHANGE_CODE_ERROR_CODE
+                                                         message:
+                                                             [FlutterAppAuth
+                                                                 formatMessageWithError:
+                                                                     AUTHORIZE_ERROR_MESSAGE_FORMAT
+                                                                                  error:
+                                                                                      error]
+                                                          result:result
+                                                           error:error];
+                                           }
+                                         }];
   } else {
-      id<OIDExternalUserAgent> agent = [self userAgentWithViewController:rootViewController externalUserAgent:externalUserAgent];
-      return [OIDAuthorizationService presentAuthorizationRequest:request externalUserAgent:agent callback:^(OIDAuthorizationResponse *_Nullable authorizationResponse, NSError *_Nullable error) {
-          if(authorizationResponse) {
-              NSMutableDictionary *processedResponse = [[NSMutableDictionary alloc] init];
-              [processedResponse setObject:authorizationResponse.additionalParameters forKey:@"authorizationAdditionalParameters"];
-              [processedResponse setObject:authorizationResponse.authorizationCode forKey:@"authorizationCode"];
-              [processedResponse setObject:authorizationResponse.request.codeVerifier forKey:@"codeVerifier"];
-              [processedResponse setObject:authorizationResponse.request.nonce forKey:@"nonce"];
-              result(processedResponse);
-          } else {
-              [FlutterAppAuth finishWithError:AUTHORIZE_ERROR_CODE message:[FlutterAppAuth formatMessageWithError:AUTHORIZE_ERROR_MESSAGE_FORMAT error:error] result:result error:error];
-          }
-      }];
+    id<OIDExternalUserAgent> agent =
+        [self userAgentWithViewController:rootViewController
+                        externalUserAgent:externalUserAgent];
+    return [OIDAuthorizationService
+        presentAuthorizationRequest:request
+                  externalUserAgent:agent
+                           callback:^(OIDAuthorizationResponse
+                                          *_Nullable authorizationResponse,
+                                      NSError *_Nullable error) {
+                             if (authorizationResponse) {
+                               NSMutableDictionary *processedResponse =
+                                   [[NSMutableDictionary alloc] init];
+                               [processedResponse
+                                   setObject:authorizationResponse
+                                                 .additionalParameters
+                                      forKey:
+                                          @"authorizationAdditionalParameters"];
+                               [processedResponse
+                                   setObject:authorizationResponse
+                                                 .authorizationCode
+                                      forKey:@"authorizationCode"];
+                               [processedResponse
+                                   setObject:authorizationResponse.request
+                                                 .codeVerifier
+                                      forKey:@"codeVerifier"];
+                               [processedResponse
+                                   setObject:authorizationResponse.request.nonce
+                                      forKey:@"nonce"];
+                               result(processedResponse);
+                             } else {
+                               [FlutterAppAuth
+                                   finishWithError:AUTHORIZE_ERROR_CODE
+                                           message:
+                                               [FlutterAppAuth
+                                                   formatMessageWithError:
+                                                       AUTHORIZE_ERROR_MESSAGE_FORMAT
+                                                                    error:error]
+                                            result:result
+                                             error:error];
+                             }
+                           }];
   }
 }
 
-- (id<OIDExternalUserAgentSession>)performEndSessionRequest:(OIDServiceConfiguration *)serviceConfiguration requestParameters:(EndSessionRequestParameters *)requestParameters result:(FlutterResult)result {
-  NSURL *postLogoutRedirectURL = requestParameters.postLogoutRedirectUrl ? [NSURL URLWithString:requestParameters.postLogoutRedirectUrl] : nil;
-  
-  OIDEndSessionRequest *endSessionRequest = requestParameters.state ? [[OIDEndSessionRequest alloc] initWithConfiguration:serviceConfiguration idTokenHint:requestParameters.idTokenHint postLogoutRedirectURL:postLogoutRedirectURL
-                                                                                                                    state:requestParameters.state additionalParameters:requestParameters.additionalParameters] :[[OIDEndSessionRequest alloc] initWithConfiguration:serviceConfiguration idTokenHint:requestParameters.idTokenHint postLogoutRedirectURL:postLogoutRedirectURL
-                                                                                                                                                                                                                                               additionalParameters:requestParameters.additionalParameters];
+- (id<OIDExternalUserAgentSession>)
+    performEndSessionRequest:(OIDServiceConfiguration *)serviceConfiguration
+           requestParameters:(EndSessionRequestParameters *)requestParameters
+                      result:(FlutterResult)result {
+  NSURL *postLogoutRedirectURL =
+      requestParameters.postLogoutRedirectUrl
+          ? [NSURL URLWithString:requestParameters.postLogoutRedirectUrl]
+          : nil;
+
+  OIDEndSessionRequest *endSessionRequest =
+      requestParameters.state
+          ? [[OIDEndSessionRequest alloc]
+                initWithConfiguration:serviceConfiguration
+                          idTokenHint:requestParameters.idTokenHint
+                postLogoutRedirectURL:postLogoutRedirectURL
+                                state:requestParameters.state
+                 additionalParameters:requestParameters.additionalParameters]
+          : [[OIDEndSessionRequest alloc]
+                initWithConfiguration:serviceConfiguration
+                          idTokenHint:requestParameters.idTokenHint
+                postLogoutRedirectURL:postLogoutRedirectURL
+                 additionalParameters:requestParameters.additionalParameters];
 
   UIViewController *rootViewController = [self rootViewController];
-  id<OIDExternalUserAgent> externalUserAgent = [self userAgentWithViewController:rootViewController externalUserAgent:requestParameters.externalUserAgent];
+  id<OIDExternalUserAgent> externalUserAgent =
+      [self userAgentWithViewController:rootViewController
+                      externalUserAgent:requestParameters.externalUserAgent];
 
-  
-  return [OIDAuthorizationService presentEndSessionRequest:endSessionRequest externalUserAgent:externalUserAgent callback:^(OIDEndSessionResponse * _Nullable endSessionResponse, NSError * _Nullable error) {
-      if(!endSessionResponse) {
-          NSString *message = [NSString stringWithFormat:END_SESSION_ERROR_MESSAGE_FORMAT, [error localizedDescription]];
-          [FlutterAppAuth finishWithError:END_SESSION_ERROR_CODE message:message result:result error:error];
-          return;
-      }
-      NSMutableDictionary *processedResponse = [[NSMutableDictionary alloc] init];
-      [processedResponse setObject:endSessionResponse.state forKey:@"state"];
-      result(processedResponse);
-  }];
+  return [OIDAuthorizationService
+      presentEndSessionRequest:endSessionRequest
+             externalUserAgent:externalUserAgent
+                      callback:^(
+                          OIDEndSessionResponse *_Nullable endSessionResponse,
+                          NSError *_Nullable error) {
+                        if (!endSessionResponse) {
+                          NSString *message = [NSString
+                              stringWithFormat:END_SESSION_ERROR_MESSAGE_FORMAT,
+                                               [error localizedDescription]];
+                          [FlutterAppAuth finishWithError:END_SESSION_ERROR_CODE
+                                                  message:message
+                                                   result:result
+                                                    error:error];
+                          return;
+                        }
+                        NSMutableDictionary *processedResponse =
+                            [[NSMutableDictionary alloc] init];
+                        [processedResponse setObject:endSessionResponse.state
+                                              forKey:@"state"];
+                        result(processedResponse);
+                      }];
 }
 
-- (id<OIDExternalUserAgent>)userAgentWithViewController:(UIViewController *)rootViewController externalUserAgent:(NSNumber*)externalUserAgent {
-    if ([externalUserAgent integerValue] == EphemeralASWebAuthenticationSession) {
-        return [[OIDExternalUserAgentIOSNoSSO alloc]
-                initWithPresentingViewController:rootViewController];
-    }
-    if ([externalUserAgent integerValue] == SafariViewController) {
-        return [[OIDExternalUserAgentIOSNoSSO alloc]
-                initWithPresentingViewController:rootViewController];
-    }
-    return [[OIDExternalUserAgentIOS alloc]
-            initWithPresentingViewController:rootViewController];
+- (id<OIDExternalUserAgent>)
+    userAgentWithViewController:(UIViewController *)rootViewController
+              externalUserAgent:(NSNumber *)externalUserAgent {
+  if ([externalUserAgent integerValue] == EphemeralASWebAuthenticationSession) {
+    return [[OIDExternalUserAgentIOSNoSSO alloc]
+        initWithPresentingViewController:rootViewController];
+  }
+  if ([externalUserAgent integerValue] == SafariViewController) {
+    return [[OIDExternalUserAgentIOSNoSSO alloc]
+        initWithPresentingViewController:rootViewController];
+  }
+  return [[OIDExternalUserAgentIOS alloc]
+      initWithPresentingViewController:rootViewController];
 }
 
 - (UIViewController *)rootViewController {
-    if (@available(iOS 13, *)) {
-      return [[UIApplication sharedApplication].windows filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id window, NSDictionary *bindings) {
-        return [window isKeyWindow];
-      }]].firstObject.rootViewController;
-    }
-    return [UIApplication sharedApplication].delegate.window.rootViewController;
-    
+  if (@available(iOS 13, *)) {
+    return [[UIApplication sharedApplication].windows
+               filteredArrayUsingPredicate:[NSPredicate
+                                               predicateWithBlock:^BOOL(
+                                                   id window,
+                                                   NSDictionary *bindings) {
+                                                 return [window isKeyWindow];
+                                               }]]
+        .firstObject.rootViewController;
+  }
+  return [UIApplication sharedApplication].delegate.window.rootViewController;
 }
 
 @end
diff --git a/flutter_appauth/ios/Classes/FlutterAppAuth.h b/flutter_appauth/ios/Classes/FlutterAppAuth.h
index 92524b94..3b2c2de3 100644
--- a/flutter_appauth/ios/Classes/FlutterAppAuth.h
+++ b/flutter_appauth/ios/Classes/FlutterAppAuth.h
@@ -11,25 +11,36 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface FlutterAppAuth : NSObject
 
-+ (NSMutableDictionary *)processResponses:(OIDTokenResponse*) tokenResponse authResponse:(OIDAuthorizationResponse* _Nullable) authResponse;
-+ (void)finishWithError:(NSString *)errorCode message:(NSString *)message  result:(FlutterResult)result error:(NSError * _Nullable)error;
-+ (NSString *) formatMessageWithError:(NSString *)messageFormat error:(NSError * _Nullable)error;
++ (NSMutableDictionary *)processResponses:(OIDTokenResponse *)tokenResponse
+                             authResponse:(OIDAuthorizationResponse *_Nullable)
+                                              authResponse;
++ (void)finishWithError:(NSString *)errorCode
+                message:(NSString *)message
+                 result:(FlutterResult)result
+                  error:(NSError *_Nullable)error;
++ (NSString *)formatMessageWithError:(NSString *)messageFormat
+                               error:(NSError *_Nullable)error;
 
 @end
 
 static NSString *const AUTHORIZE_METHOD = @"authorize";
-static NSString *const AUTHORIZE_AND_EXCHANGE_CODE_METHOD = @"authorizeAndExchangeCode";
+static NSString *const AUTHORIZE_AND_EXCHANGE_CODE_METHOD =
+    @"authorizeAndExchangeCode";
 static NSString *const TOKEN_METHOD = @"token";
 static NSString *const END_SESSION_METHOD = @"endSession";
 static NSString *const AUTHORIZE_ERROR_CODE = @"authorize_failed";
-static NSString *const AUTHORIZE_AND_EXCHANGE_CODE_ERROR_CODE = @"authorize_and_exchange_code_failed";
+static NSString *const AUTHORIZE_AND_EXCHANGE_CODE_ERROR_CODE =
+    @"authorize_and_exchange_code_failed";
 static NSString *const DISCOVERY_ERROR_CODE = @"discovery_failed";
 static NSString *const TOKEN_ERROR_CODE = @"token_failed";
 static NSString *const END_SESSION_ERROR_CODE = @"end_session_failed";
-static NSString *const DISCOVERY_ERROR_MESSAGE_FORMAT = @"Error retrieving discovery document: %@";
+static NSString *const DISCOVERY_ERROR_MESSAGE_FORMAT =
+    @"Error retrieving discovery document: %@";
 static NSString *const TOKEN_ERROR_MESSAGE_FORMAT = @"Failed to get token: %@";
-static NSString *const AUTHORIZE_ERROR_MESSAGE_FORMAT = @"Failed to authorize: %@";
-static NSString *const END_SESSION_ERROR_MESSAGE_FORMAT = @"Failed to end session: %@";
+static NSString *const AUTHORIZE_ERROR_MESSAGE_FORMAT =
+    @"Failed to authorize: %@";
+static NSString *const END_SESSION_ERROR_MESSAGE_FORMAT =
+    @"Failed to end session: %@";
 
 @interface EndSessionRequestParameters : NSObject
 @property(nonatomic, strong) NSString *idTokenHint;
@@ -50,9 +61,22 @@ typedef NS_ENUM(NSInteger, ExternalUserAgent) {
 
 @interface AppAuthAuthorization : NSObject
 
-- (id<OIDExternalUserAgentSession>)performAuthorization:(OIDServiceConfiguration *)serviceConfiguration clientId:(NSString*)clientId clientSecret:(NSString*)clientSecret scopes:(NSArray *)scopes redirectUrl:(NSString*)redirectUrl additionalParameters:(NSDictionary *)additionalParameters externalUserAgent:(NSNumber*)externalUserAgent 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
+       externalUserAgent:(NSNumber *)externalUserAgent
+                  result:(FlutterResult)result
+            exchangeCode:(BOOL)exchangeCode
+                   nonce:(NSString *)nonce;
 
-- (id<OIDExternalUserAgentSession>)performEndSessionRequest:(OIDServiceConfiguration *)serviceConfiguration requestParameters:(EndSessionRequestParameters *)requestParameters result:(FlutterResult)result;
+- (id<OIDExternalUserAgentSession>)
+    performEndSessionRequest:(OIDServiceConfiguration *)serviceConfiguration
+           requestParameters:(EndSessionRequestParameters *)requestParameters
+                      result:(FlutterResult)result;
 
 @end
 
diff --git a/flutter_appauth/ios/Classes/FlutterAppAuth.m b/flutter_appauth/ios/Classes/FlutterAppAuth.m
index 1d6a3022..4b448d7b 100644
--- a/flutter_appauth/ios/Classes/FlutterAppAuth.m
+++ b/flutter_appauth/ios/Classes/FlutterAppAuth.m
@@ -2,106 +2,148 @@
 
 @implementation FlutterAppAuth
 
-+ (NSMutableDictionary *)processResponses:(OIDTokenResponse*) tokenResponse authResponse:(OIDAuthorizationResponse*) authResponse {
-    NSMutableDictionary *processedResponses = [[NSMutableDictionary alloc] init];
-    if(tokenResponse.accessToken) {
-        [processedResponses setValue:tokenResponse.accessToken forKey:@"accessToken"];
++ (NSMutableDictionary *)processResponses:(OIDTokenResponse *)tokenResponse
+                             authResponse:
+                                 (OIDAuthorizationResponse *)authResponse {
+  NSMutableDictionary *processedResponses = [[NSMutableDictionary alloc] init];
+  if (tokenResponse.accessToken) {
+    [processedResponses setValue:tokenResponse.accessToken
+                          forKey:@"accessToken"];
+  }
+  if (tokenResponse.accessTokenExpirationDate) {
+    [processedResponses
+        setValue:[[NSNumber alloc]
+                     initWithDouble:[tokenResponse.accessTokenExpirationDate
+                                            timeIntervalSince1970] *
+                                    1000]
+          forKey:@"accessTokenExpirationTime"];
+  }
+  if (authResponse) {
+    if (authResponse.additionalParameters) {
+      [processedResponses setObject:authResponse.additionalParameters
+                             forKey:@"authorizationAdditionalParameters"];
     }
-    if(tokenResponse.accessTokenExpirationDate) {
-        [processedResponses setValue:[[NSNumber alloc] initWithDouble:[tokenResponse.accessTokenExpirationDate timeIntervalSince1970] * 1000] forKey:@"accessTokenExpirationTime"];
+    if (authResponse.request && authResponse.request.nonce) {
+      [processedResponses setObject:authResponse.request.nonce forKey:@"nonce"];
     }
-    if(authResponse) {
-        if (authResponse.additionalParameters) {
-            [processedResponses setObject:authResponse.additionalParameters forKey:@"authorizationAdditionalParameters"];
-        }
-        if (authResponse.request && authResponse.request.nonce) {
-            [processedResponses setObject:authResponse.request.nonce forKey:@"nonce"];
-        }
-     }
-    if(tokenResponse.additionalParameters) {
-        [processedResponses setObject:tokenResponse.additionalParameters forKey:@"tokenAdditionalParameters"];
-    }
-    if(tokenResponse.idToken) {
-        [processedResponses setValue:tokenResponse.idToken forKey:@"idToken"];
-    }
-    if(tokenResponse.refreshToken) {
-        [processedResponses setValue:tokenResponse.refreshToken forKey:@"refreshToken"];
+  }
+  if (tokenResponse.additionalParameters) {
+    [processedResponses setObject:tokenResponse.additionalParameters
+                           forKey:@"tokenAdditionalParameters"];
+  }
+  if (tokenResponse.idToken) {
+    [processedResponses setValue:tokenResponse.idToken forKey:@"idToken"];
+  }
+  if (tokenResponse.refreshToken) {
+    [processedResponses setValue:tokenResponse.refreshToken
+                          forKey:@"refreshToken"];
+  }
+  if (tokenResponse.tokenType) {
+    [processedResponses setValue:tokenResponse.tokenType forKey:@"tokenType"];
+  }
+  if (tokenResponse.scope) {
+    [processedResponses
+        setObject:[tokenResponse.scope componentsSeparatedByString:@" "]
+           forKey:@"scopes"];
+  }
+
+  return processedResponses;
+}
+
++ (void)finishWithError:(NSString *)errorCode
+                message:(NSString *)message
+                 result:(FlutterResult)result
+                  error:(NSError *_Nullable)error {
+
+  NSMutableDictionary<NSString *, id> *details =
+      [NSMutableDictionary dictionary];
+
+  if (error) {
+    id authError = error.userInfo[OIDOAuthErrorResponseErrorKey];
+    NSDictionary<NSString *, id> *authErrorMap =
+        [authError isKindOfClass:[NSDictionary class]] ? authError : nil;
+
+    if (authErrorMap) {
+      if ([authErrorMap objectForKey:OIDOAuthErrorFieldError]) {
+        [details setObject:authErrorMap[OIDOAuthErrorFieldError]
+                    forKey:OIDOAuthErrorFieldError];
+      }
+      if ([authErrorMap objectForKey:OIDOAuthErrorFieldErrorDescription]) {
+        [details setObject:authErrorMap[OIDOAuthErrorFieldErrorDescription]
+                    forKey:OIDOAuthErrorFieldErrorDescription];
+      }
+      if ([authErrorMap objectForKey:OIDOAuthErrorFieldErrorURI]) {
+        [details setObject:authErrorMap[OIDOAuthErrorFieldErrorURI]
+                    forKey:OIDOAuthErrorFieldErrorURI];
+      }
     }
-    if(tokenResponse.tokenType) {
-        [processedResponses setValue:tokenResponse.tokenType forKey:@"tokenType"];
+    if (error.domain) {
+      [details setObject:error.domain forKey:@"type"];
     }
-    if (tokenResponse.scope) {
-        [processedResponses setObject:[tokenResponse.scope componentsSeparatedByString: @" "] forKey:@"scopes"];
+    if (error.code) {
+      [details setObject:[@(error.code) stringValue] forKey:@"code"];
     }
-    
-    return processedResponses;
-}
 
-+ (void)finishWithError:(NSString *)errorCode message:(NSString *)message result:(FlutterResult)result error:(NSError * _Nullable)error {
-
-    NSMutableDictionary<NSString *, id> *details = [NSMutableDictionary dictionary];
-
-    if (error) {
-        id authError = error.userInfo[OIDOAuthErrorResponseErrorKey];
-        NSDictionary<NSString *, id> *authErrorMap = [authError isKindOfClass:[NSDictionary class]] ? authError : nil;
-        
-        if (authErrorMap) {
-            if ([authErrorMap objectForKey:OIDOAuthErrorFieldError]) {
-                [details setObject:authErrorMap[OIDOAuthErrorFieldError] forKey:OIDOAuthErrorFieldError];
-            }
-            if ([authErrorMap objectForKey:OIDOAuthErrorFieldErrorDescription]) {
-                [details setObject:authErrorMap[OIDOAuthErrorFieldErrorDescription] forKey:OIDOAuthErrorFieldErrorDescription];
-            }
-            if ([authErrorMap objectForKey:OIDOAuthErrorFieldErrorURI]) {
-                [details setObject:authErrorMap[OIDOAuthErrorFieldErrorURI] forKey:OIDOAuthErrorFieldErrorURI];
-            }
-        }
-        if (error.domain) {
-            [details setObject:error.domain forKey:@"type"];
-        }
-        if (error.code) {
-            [details setObject:[@(error.code) stringValue] forKey:@"code"];
-        }
-        
-        id underlyingErr = [error.userInfo objectForKey:NSUnderlyingErrorKey];
-        NSError *underlyingError = [underlyingErr isKindOfClass:[NSError class]] ? underlyingErr : nil;
-        if (underlyingError) {
-            if (underlyingError.domain) {
-                [details setObject:underlyingError.domain forKey:@"domain"];
-            }
-
-            if (underlyingError.debugDescription) {
-                [details setObject:underlyingError.debugDescription forKey:@"root_cause_debug_description"];
-            }
-        }
-        
-        if (error.debugDescription) {
-            [details setObject:error.debugDescription forKey:@"error_debug_description"];
-        }
-        
-        bool userDidCancel = [error.domain  isEqual: @"org.openid.appauth.general"] 
-                             && error.code == OIDErrorCodeUserCanceledAuthorizationFlow;
-        [details setObject:(userDidCancel ? @"true" : @"false") forKey:@"user_did_cancel"];
+    id underlyingErr = [error.userInfo objectForKey:NSUnderlyingErrorKey];
+    NSError *underlyingError =
+        [underlyingErr isKindOfClass:[NSError class]] ? underlyingErr : nil;
+    if (underlyingError) {
+      if (underlyingError.domain) {
+        [details setObject:underlyingError.domain forKey:@"domain"];
+      }
 
+      if (underlyingError.debugDescription) {
+        [details setObject:underlyingError.debugDescription
+                    forKey:@"root_cause_debug_description"];
+      }
     }
-    result([FlutterError errorWithCode:errorCode message:message details:details]);
+
+    if (error.debugDescription) {
+      [details setObject:error.debugDescription
+                  forKey:@"error_debug_description"];
+    }
+
+    bool userDidCancel =
+        [error.domain isEqual:@"org.openid.appauth.general"] &&
+        error.code == OIDErrorCodeUserCanceledAuthorizationFlow;
+    [details setObject:(userDidCancel ? @"true" : @"false")
+                forKey:@"user_did_cancel"];
+  }
+  result([FlutterError errorWithCode:errorCode
+                             message:message
+                             details:details]);
 }
 
-+ (NSString *) formatMessageWithError:(NSString *)messageFormat error:(NSError * _Nullable)error {
-    NSString *formattedMessage = [NSString stringWithFormat:messageFormat, [error localizedDescription]];
-    return formattedMessage;
++ (NSString *)formatMessageWithError:(NSString *)messageFormat
+                               error:(NSError *_Nullable)error {
+  NSString *formattedMessage =
+      [NSString stringWithFormat:messageFormat, [error localizedDescription]];
+  return formattedMessage;
 }
 
 @end
 
 @implementation AppAuthAuthorization
 
-- (id<OIDExternalUserAgentSession>)performAuthorization:(OIDServiceConfiguration *)serviceConfiguration clientId:(NSString*)clientId clientSecret:(NSString*)clientSecret scopes:(NSArray *)scopes redirectUrl:(NSString*)redirectUrl additionalParameters:(NSDictionary *)additionalParameters externalUserAgent:(NSNumber*)externalUserAgent result:(FlutterResult)result exchangeCode:(BOOL)exchangeCode nonce:(NSString*)nonce {
-    return nil;
+- (id<OIDExternalUserAgentSession>)
+    performAuthorization:(OIDServiceConfiguration *)serviceConfiguration
+                clientId:(NSString *)clientId
+            clientSecret:(NSString *)clientSecret
+                  scopes:(NSArray *)scopes
+             redirectUrl:(NSString *)redirectUrl
+    additionalParameters:(NSDictionary *)additionalParameters
+       externalUserAgent:(NSNumber *)externalUserAgent
+                  result:(FlutterResult)result
+            exchangeCode:(BOOL)exchangeCode
+                   nonce:(NSString *)nonce {
+  return nil;
 }
 
-- (id<OIDExternalUserAgentSession>)performEndSessionRequest:(OIDServiceConfiguration *)serviceConfiguration requestParameters:(EndSessionRequestParameters *)requestParameters result:(FlutterResult)result {
-    return nil;
+- (id<OIDExternalUserAgentSession>)
+    performEndSessionRequest:(OIDServiceConfiguration *)serviceConfiguration
+           requestParameters:(EndSessionRequestParameters *)requestParameters
+                      result:(FlutterResult)result {
+  return nil;
 }
 
 @end
diff --git a/flutter_appauth/ios/Classes/FlutterAppauthPlugin.h b/flutter_appauth/ios/Classes/FlutterAppauthPlugin.h
index a2c96d89..13428373 100644
--- a/flutter_appauth/ios/Classes/FlutterAppauthPlugin.h
+++ b/flutter_appauth/ios/Classes/FlutterAppauthPlugin.h
@@ -1,17 +1,18 @@
 #import <TargetConditionals.h>
 
 #if TARGET_OS_OSX
-#import <FlutterMacOS/FlutterMacOS.h>
 #import "AppAuthMacOSAuthorization.h"
+#import <FlutterMacOS/FlutterMacOS.h>
 #else
-#import <Flutter/Flutter.h>
 #import "AppAuthIOSAuthorization.h"
+#import <Flutter/Flutter.h>
 #endif
 
 #import <AppAuth/AppAuth.h>
 
-@interface FlutterAppauthPlugin : NSObject<FlutterPlugin>
+@interface FlutterAppauthPlugin : NSObject <FlutterPlugin>
 
-@property(nonatomic, strong, nullable) id<OIDExternalUserAgentSession> currentAuthorizationFlow;
+@property(nonatomic, strong, nullable) id<OIDExternalUserAgentSession>
+    currentAuthorizationFlow;
 
 @end
diff --git a/flutter_appauth/ios/Classes/FlutterAppauthPlugin.m b/flutter_appauth/ios/Classes/FlutterAppauthPlugin.m
index 63d73a9b..293cf8c0 100644
--- a/flutter_appauth/ios/Classes/FlutterAppauthPlugin.m
+++ b/flutter_appauth/ios/Classes/FlutterAppauthPlugin.m
@@ -3,13 +3,15 @@
 #import "FlutterAppauthPlugin.h"
 
 @interface ArgumentProcessor : NSObject
-+ (id _Nullable)processArgumentValue:(NSDictionary *)arguments withKey:(NSString *)key;
++ (id _Nullable)processArgumentValue:(NSDictionary *)arguments
+                             withKey:(NSString *)key;
 @end
 
 @implementation ArgumentProcessor
 
-+ (id _Nullable)processArgumentValue:(NSDictionary *)arguments withKey:(NSString *)key {
-    return [arguments objectForKey:key] != [NSNull null] ? arguments[key] : nil;
++ (id _Nullable)processArgumentValue:(NSDictionary *)arguments
+                             withKey:(NSString *)key {
+  return [arguments objectForKey:key] != [NSNull null] ? arguments[key] : nil;
 }
 
 @end
@@ -34,25 +36,42 @@ @interface TokenRequestParameters : NSObject
 
 @implementation TokenRequestParameters
 - (void)processArguments:(NSDictionary *)arguments {
-    _clientId = [ArgumentProcessor processArgumentValue:arguments withKey:@"clientId"];
-    _clientSecret = [ArgumentProcessor processArgumentValue:arguments withKey:@"clientSecret"];
-    _issuer = [ArgumentProcessor processArgumentValue:arguments withKey:@"issuer"];
-    _discoveryUrl = [ArgumentProcessor processArgumentValue:arguments withKey:@"discoveryUrl"];
-    _redirectUrl = [ArgumentProcessor processArgumentValue:arguments withKey:@"redirectUrl"];
-    _refreshToken = [ArgumentProcessor processArgumentValue:arguments withKey:@"refreshToken"];
-    _nonce = [ArgumentProcessor processArgumentValue:arguments withKey:@"nonce"];
-    _authorizationCode = [ArgumentProcessor processArgumentValue:arguments withKey:@"authorizationCode"];
-    _codeVerifier = [ArgumentProcessor processArgumentValue:arguments withKey:@"codeVerifier"];
-    _grantType = [ArgumentProcessor processArgumentValue:arguments withKey:@"grantType"];
-    _scopes = [ArgumentProcessor processArgumentValue:arguments withKey:@"scopes"];
-    _serviceConfigurationParameters = [ArgumentProcessor processArgumentValue:arguments withKey:@"serviceConfiguration"];
-    _additionalParameters = [ArgumentProcessor processArgumentValue:arguments withKey:@"additionalParameters"];
-    _externalUserAgent = [ArgumentProcessor processArgumentValue:arguments withKey:@"externalUserAgent"];
+  _clientId = [ArgumentProcessor processArgumentValue:arguments
+                                              withKey:@"clientId"];
+  _clientSecret = [ArgumentProcessor processArgumentValue:arguments
+                                                  withKey:@"clientSecret"];
+  _issuer = [ArgumentProcessor processArgumentValue:arguments
+                                            withKey:@"issuer"];
+  _discoveryUrl = [ArgumentProcessor processArgumentValue:arguments
+                                                  withKey:@"discoveryUrl"];
+  _redirectUrl = [ArgumentProcessor processArgumentValue:arguments
+                                                 withKey:@"redirectUrl"];
+  _refreshToken = [ArgumentProcessor processArgumentValue:arguments
+                                                  withKey:@"refreshToken"];
+  _nonce = [ArgumentProcessor processArgumentValue:arguments withKey:@"nonce"];
+  _authorizationCode =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"authorizationCode"];
+  _codeVerifier = [ArgumentProcessor processArgumentValue:arguments
+                                                  withKey:@"codeVerifier"];
+  _grantType = [ArgumentProcessor processArgumentValue:arguments
+                                               withKey:@"grantType"];
+  _scopes = [ArgumentProcessor processArgumentValue:arguments
+                                            withKey:@"scopes"];
+  _serviceConfigurationParameters =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"serviceConfiguration"];
+  _additionalParameters =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"additionalParameters"];
+  _externalUserAgent =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"externalUserAgent"];
 }
 
 - (id)initWithArguments:(NSDictionary *)arguments {
-    [self processArguments:arguments];
-    return self;
+  [self processArguments:arguments];
+  return self;
 }
 
 @end
@@ -65,251 +84,429 @@ @interface AuthorizationTokenRequestParameters : TokenRequestParameters
 
 @implementation AuthorizationTokenRequestParameters
 - (id)initWithArguments:(NSDictionary *)arguments {
-    [super processArguments:arguments];
-    _loginHint = [ArgumentProcessor processArgumentValue:arguments withKey:@"loginHint"];
-    _promptValues = [ArgumentProcessor processArgumentValue:arguments withKey:@"promptValues"];
-    _responseMode = [ArgumentProcessor processArgumentValue:arguments withKey:@"responseMode"];
-    return self;
+  [super processArguments:arguments];
+  _loginHint = [ArgumentProcessor processArgumentValue:arguments
+                                               withKey:@"loginHint"];
+  _promptValues = [ArgumentProcessor processArgumentValue:arguments
+                                                  withKey:@"promptValues"];
+  _responseMode = [ArgumentProcessor processArgumentValue:arguments
+                                                  withKey:@"responseMode"];
+  return self;
 }
 @end
 
 @implementation EndSessionRequestParameters
 - (id)initWithArguments:(NSDictionary *)arguments {
-    _idTokenHint= [ArgumentProcessor processArgumentValue:arguments withKey:@"idTokenHint"];
-    _postLogoutRedirectUrl = [ArgumentProcessor processArgumentValue:arguments withKey:@"postLogoutRedirectUrl"];
-    _state = [ArgumentProcessor processArgumentValue:arguments withKey:@"state"];
-    _issuer = [ArgumentProcessor processArgumentValue:arguments withKey:@"issuer"];
-    _discoveryUrl = [ArgumentProcessor processArgumentValue:arguments withKey:@"discoveryUrl"];
-    _serviceConfigurationParameters = [ArgumentProcessor processArgumentValue:arguments withKey:@"serviceConfiguration"];
-    _additionalParameters = [ArgumentProcessor processArgumentValue:arguments withKey:@"additionalParameters"];
-    _externalUserAgent = [ArgumentProcessor processArgumentValue:arguments withKey:@"externalUserAgent"];
-    return self;
+  _idTokenHint = [ArgumentProcessor processArgumentValue:arguments
+                                                 withKey:@"idTokenHint"];
+  _postLogoutRedirectUrl =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"postLogoutRedirectUrl"];
+  _state = [ArgumentProcessor processArgumentValue:arguments withKey:@"state"];
+  _issuer = [ArgumentProcessor processArgumentValue:arguments
+                                            withKey:@"issuer"];
+  _discoveryUrl = [ArgumentProcessor processArgumentValue:arguments
+                                                  withKey:@"discoveryUrl"];
+  _serviceConfigurationParameters =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"serviceConfiguration"];
+  _additionalParameters =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"additionalParameters"];
+  _externalUserAgent =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"externalUserAgent"];
+  return self;
 }
 @end
 
 @implementation FlutterAppauthPlugin
 
-FlutterMethodChannel* channel;
-AppAuthAuthorization* authorization;
+FlutterMethodChannel *channel;
+AppAuthAuthorization *authorization;
+
++ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
+  channel = [FlutterMethodChannel
+      methodChannelWithName:@"crossingthestreams.io/flutter_appauth"
+            binaryMessenger:[registrar messenger]];
+  FlutterAppauthPlugin *instance = [[FlutterAppauthPlugin alloc] init];
+  [registrar addMethodCallDelegate:instance channel:channel];
 
-+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
-    channel = [FlutterMethodChannel
-               methodChannelWithName:@"crossingthestreams.io/flutter_appauth"
-               binaryMessenger:[registrar messenger]];
-    FlutterAppauthPlugin* instance = [[FlutterAppauthPlugin alloc] init];
-    [registrar addMethodCallDelegate:instance channel:channel];
-    
 #if TARGET_OS_OSX
-    authorization = [[AppAuthMacOSAuthorization alloc] init];
-    
-    NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
-    [appleEventManager setEventHandler:instance
-                           andSelector:@selector(handleGetURLEvent:withReplyEvent:)
-                         forEventClass:kInternetEventClass
-                            andEventID:kAEGetURL];
+  authorization = [[AppAuthMacOSAuthorization alloc] init];
+
+  NSAppleEventManager *appleEventManager =
+      [NSAppleEventManager sharedAppleEventManager];
+  [appleEventManager setEventHandler:instance
+                         andSelector:@selector(handleGetURLEvent:
+                                                  withReplyEvent:)
+                       forEventClass:kInternetEventClass
+                          andEventID:kAEGetURL];
 #else
-    authorization = [[AppAuthIOSAuthorization alloc] init];
-    
-    [registrar addApplicationDelegate:instance];
+  authorization = [[AppAuthIOSAuthorization alloc] init];
+
+  [registrar addApplicationDelegate:instance];
 #endif
 }
 
-- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
-    if ([AUTHORIZE_AND_EXCHANGE_CODE_METHOD isEqualToString:call.method]) {
-        [self handleAuthorizeMethodCall:[call arguments] result:result exchangeCode:true];
-    } else if([AUTHORIZE_METHOD isEqualToString:call.method]) {
-        [self handleAuthorizeMethodCall:[call arguments] result:result exchangeCode:false];
-    } else if([TOKEN_METHOD isEqualToString:call.method]) {
-        [self handleTokenMethodCall:[call arguments] result:result];
-    } else if([END_SESSION_METHOD isEqualToString:call.method]) {
-        [self handleEndSessionMethodCall:[call arguments] result:result];
-    } else {
-        result(FlutterMethodNotImplemented);
-    }
+- (void)handleMethodCall:(FlutterMethodCall *)call
+                  result:(FlutterResult)result {
+  if ([AUTHORIZE_AND_EXCHANGE_CODE_METHOD isEqualToString:call.method]) {
+    [self handleAuthorizeMethodCall:[call arguments]
+                             result:result
+                       exchangeCode:true];
+  } else if ([AUTHORIZE_METHOD isEqualToString:call.method]) {
+    [self handleAuthorizeMethodCall:[call arguments]
+                             result:result
+                       exchangeCode:false];
+  } else if ([TOKEN_METHOD isEqualToString:call.method]) {
+    [self handleTokenMethodCall:[call arguments] result:result];
+  } else if ([END_SESSION_METHOD isEqualToString:call.method]) {
+    [self handleEndSessionMethodCall:[call arguments] result:result];
+  } else {
+    result(FlutterMethodNotImplemented);
+  }
 }
 
-- (void)ensureAdditionalParametersInitialized:(AuthorizationTokenRequestParameters *)requestParameters {
-    if(!requestParameters.additionalParameters) {
-        requestParameters.additionalParameters = [[NSMutableDictionary alloc] init];
-    }
+- (void)ensureAdditionalParametersInitialized:
+    (AuthorizationTokenRequestParameters *)requestParameters {
+  if (!requestParameters.additionalParameters) {
+    requestParameters.additionalParameters = [[NSMutableDictionary alloc] init];
+  }
 }
 
--(void)handleAuthorizeMethodCall:(NSDictionary*)arguments result:(FlutterResult)result exchangeCode:(BOOL)exchangeCode {
-    AuthorizationTokenRequestParameters *requestParameters = [[AuthorizationTokenRequestParameters alloc] initWithArguments:arguments];
-    [self ensureAdditionalParametersInitialized:requestParameters];
-    if(requestParameters.loginHint) {
-        [requestParameters.additionalParameters setValue:requestParameters.loginHint forKey:@"login_hint"];
-    }
-    if(requestParameters.promptValues) {
-        [requestParameters.additionalParameters setValue:[requestParameters.promptValues componentsJoinedByString:@" "] forKey:@"prompt"];
-    }
-    if(requestParameters.responseMode) {
-        [requestParameters.additionalParameters setValue:requestParameters.responseMode forKey:@"response_mode"];
-    }
-
-    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 externalUserAgent:requestParameters.externalUserAgent result:result exchangeCode:exchangeCode nonce:requestParameters.nonce];
-    } else if (requestParameters.discoveryUrl) {
-        NSURL *discoveryUrl = [NSURL URLWithString:requestParameters.discoveryUrl];
-        [OIDAuthorizationService discoverServiceConfigurationForDiscoveryURL:discoveryUrl
-                                                                  completion:^(OIDServiceConfiguration *_Nullable configuration,
-                                                                               NSError *_Nullable error) {
-
-            if (!configuration) {
-                [self finishWithDiscoveryError:error result:result];
-                return;
-            }
-
-            self->_currentAuthorizationFlow = [authorization performAuthorization:configuration clientId:requestParameters.clientId clientSecret:requestParameters.clientSecret scopes:requestParameters.scopes redirectUrl:requestParameters.redirectUrl additionalParameters:requestParameters.additionalParameters externalUserAgent:requestParameters.externalUserAgent result:result exchangeCode:exchangeCode nonce:requestParameters.nonce];
-        }];
-    } else {
-        NSURL *issuerUrl = [NSURL URLWithString:requestParameters.issuer];
-        [OIDAuthorizationService discoverServiceConfigurationForIssuer:issuerUrl
-                                                            completion:^(OIDServiceConfiguration *_Nullable configuration,
-                                                                         NSError *_Nullable error) {
-
-            if (!configuration) {
-                [self finishWithDiscoveryError:error result:result];
-                return;
-            }
-
-            self->_currentAuthorizationFlow = [authorization performAuthorization:configuration clientId:requestParameters.clientId clientSecret:requestParameters.clientSecret scopes:requestParameters.scopes redirectUrl:requestParameters.redirectUrl additionalParameters:requestParameters.additionalParameters externalUserAgent:requestParameters.externalUserAgent result:result exchangeCode:exchangeCode nonce:requestParameters.nonce];
-        }];
-    }
+- (void)handleAuthorizeMethodCall:(NSDictionary *)arguments
+                           result:(FlutterResult)result
+                     exchangeCode:(BOOL)exchangeCode {
+  AuthorizationTokenRequestParameters *requestParameters =
+      [[AuthorizationTokenRequestParameters alloc] initWithArguments:arguments];
+  [self ensureAdditionalParametersInitialized:requestParameters];
+  if (requestParameters.loginHint) {
+    [requestParameters.additionalParameters setValue:requestParameters.loginHint
+                                              forKey:@"login_hint"];
+  }
+  if (requestParameters.promptValues) {
+    [requestParameters.additionalParameters
+        setValue:[requestParameters.promptValues componentsJoinedByString:@" "]
+          forKey:@"prompt"];
+  }
+  if (requestParameters.responseMode) {
+    [requestParameters.additionalParameters
+        setValue:requestParameters.responseMode
+          forKey:@"response_mode"];
+  }
+
+  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
+           externalUserAgent:requestParameters.externalUserAgent
+                      result:result
+                exchangeCode:exchangeCode
+                       nonce:requestParameters.nonce];
+  } else if (requestParameters.discoveryUrl) {
+    NSURL *discoveryUrl = [NSURL URLWithString:requestParameters.discoveryUrl];
+    [OIDAuthorizationService
+        discoverServiceConfigurationForDiscoveryURL:discoveryUrl
+                                         completion:^(
+                                             OIDServiceConfiguration
+                                                 *_Nullable configuration,
+                                             NSError *_Nullable error) {
+                                           if (!configuration) {
+                                             [self
+                                                 finishWithDiscoveryError:error
+                                                                   result:
+                                                                       result];
+                                             return;
+                                           }
+
+                                           self->_currentAuthorizationFlow = [authorization
+                                               performAuthorization:
+                                                   configuration
+                                                           clientId:
+                                                               requestParameters
+                                                                   .clientId
+                                                       clientSecret:
+                                                           requestParameters
+                                                               .clientSecret
+                                                             scopes:
+                                                                 requestParameters
+                                                                     .scopes
+                                                        redirectUrl:
+                                                            requestParameters
+                                                                .redirectUrl
+                                               additionalParameters:
+                                                   requestParameters
+                                                       .additionalParameters
+                                                  externalUserAgent:
+                                                      requestParameters
+                                                          .externalUserAgent
+                                                             result:result
+                                                       exchangeCode:exchangeCode
+                                                              nonce:
+                                                                  requestParameters
+                                                                      .nonce];
+                                         }];
+  } else {
+    NSURL *issuerUrl = [NSURL URLWithString:requestParameters.issuer];
+    [OIDAuthorizationService
+        discoverServiceConfigurationForIssuer:issuerUrl
+                                   completion:^(OIDServiceConfiguration
+                                                    *_Nullable configuration,
+                                                NSError *_Nullable error) {
+                                     if (!configuration) {
+                                       [self finishWithDiscoveryError:error
+                                                               result:result];
+                                       return;
+                                     }
+
+                                     self->_currentAuthorizationFlow =
+                                         [authorization
+                                             performAuthorization:configuration
+                                                         clientId:
+                                                             requestParameters
+                                                                 .clientId
+                                                     clientSecret:
+                                                         requestParameters
+                                                             .clientSecret
+                                                           scopes:
+                                                               requestParameters
+                                                                   .scopes
+                                                      redirectUrl:
+                                                          requestParameters
+                                                              .redirectUrl
+                                             additionalParameters:
+                                                 requestParameters
+                                                     .additionalParameters
+                                                externalUserAgent:
+                                                    requestParameters
+                                                        .externalUserAgent
+                                                           result:result
+                                                     exchangeCode:exchangeCode
+                                                            nonce:
+                                                                requestParameters
+                                                                    .nonce];
+                                   }];
+  }
 }
 
-- (void)finishWithDiscoveryError:(NSError * _Nullable)error result:(FlutterResult)result {
-    NSString *message = [NSString stringWithFormat:DISCOVERY_ERROR_MESSAGE_FORMAT, [error localizedDescription]];
-    [FlutterAppAuth finishWithError:DISCOVERY_ERROR_CODE message:message result:result error:error];
+- (void)finishWithDiscoveryError:(NSError *_Nullable)error
+                          result:(FlutterResult)result {
+  NSString *message = [NSString stringWithFormat:DISCOVERY_ERROR_MESSAGE_FORMAT,
+                                                 [error localizedDescription]];
+  [FlutterAppAuth finishWithError:DISCOVERY_ERROR_CODE
+                          message:message
+                           result:result
+                            error:error];
 }
 
-
-- (OIDServiceConfiguration *)processServiceConfigurationParameters:(NSDictionary*)serviceConfigurationParameters {
-    NSURL *endSessionEndpoint = serviceConfigurationParameters[@"endSessionEndpoint"] == [NSNull null] ? nil : [NSURL URLWithString:serviceConfigurationParameters[@"endSessionEndpoint"]];
-    OIDServiceConfiguration *serviceConfiguration =
-    [[OIDServiceConfiguration alloc]
-     initWithAuthorizationEndpoint:[NSURL URLWithString:serviceConfigurationParameters[@"authorizationEndpoint"]]
-     tokenEndpoint:[NSURL URLWithString:serviceConfigurationParameters[@"tokenEndpoint"]] issuer:nil registrationEndpoint:nil endSessionEndpoint:endSessionEndpoint];
-    return serviceConfiguration;
+- (OIDServiceConfiguration *)processServiceConfigurationParameters:
+    (NSDictionary *)serviceConfigurationParameters {
+  NSURL *endSessionEndpoint =
+      serviceConfigurationParameters[@"endSessionEndpoint"] == [NSNull null]
+          ? nil
+          : [NSURL URLWithString:serviceConfigurationParameters
+                                     [@"endSessionEndpoint"]];
+  OIDServiceConfiguration *serviceConfiguration =
+      [[OIDServiceConfiguration alloc]
+          initWithAuthorizationEndpoint:
+              [NSURL URLWithString:serviceConfigurationParameters
+                                       [@"authorizationEndpoint"]]
+                          tokenEndpoint:
+                              [NSURL
+                                  URLWithString:serviceConfigurationParameters
+                                                    [@"tokenEndpoint"]]
+                                 issuer:nil
+                   registrationEndpoint:nil
+                     endSessionEndpoint:endSessionEndpoint];
+  return serviceConfiguration;
 }
 
--(void)handleTokenMethodCall:(NSDictionary*)arguments result:(FlutterResult)result {
-    TokenRequestParameters *requestParameters = [[TokenRequestParameters alloc] initWithArguments:arguments];
-    if(requestParameters.serviceConfigurationParameters != nil) {
-        OIDServiceConfiguration *serviceConfiguration = [self processServiceConfigurationParameters:requestParameters.serviceConfigurationParameters];
-        [self performTokenRequest:serviceConfiguration requestParameters:requestParameters result:result];
-    } else if (requestParameters.discoveryUrl) {
-        NSURL *discoveryUrl = [NSURL URLWithString:requestParameters.discoveryUrl];
-        
-        [OIDAuthorizationService discoverServiceConfigurationForDiscoveryURL:discoveryUrl
-                                                                  completion:^(OIDServiceConfiguration *_Nullable configuration,
-                                                                               NSError *_Nullable error) {
-            if (!configuration) {
-                [self finishWithDiscoveryError:error result:result];
-                return;
-            }
-            
-            [self performTokenRequest:configuration requestParameters:requestParameters result:result];
-        }];
-    } else {
-        NSURL *issuerUrl = [NSURL URLWithString:requestParameters.issuer];
-        [OIDAuthorizationService discoverServiceConfigurationForIssuer:issuerUrl
-                                                            completion:^(OIDServiceConfiguration *_Nullable configuration,
-                                                                         NSError *_Nullable error) {
-            if (!configuration) {
-                [self finishWithDiscoveryError:error result:result];
-                return;
-            }
-            
-            [self performTokenRequest:configuration requestParameters:requestParameters result:result];
-        }];
-    }
+- (void)handleTokenMethodCall:(NSDictionary *)arguments
+                       result:(FlutterResult)result {
+  TokenRequestParameters *requestParameters =
+      [[TokenRequestParameters alloc] initWithArguments:arguments];
+  if (requestParameters.serviceConfigurationParameters != nil) {
+    OIDServiceConfiguration *serviceConfiguration =
+        [self processServiceConfigurationParameters:
+                  requestParameters.serviceConfigurationParameters];
+    [self performTokenRequest:serviceConfiguration
+            requestParameters:requestParameters
+                       result:result];
+  } else if (requestParameters.discoveryUrl) {
+    NSURL *discoveryUrl = [NSURL URLWithString:requestParameters.discoveryUrl];
+
+    [OIDAuthorizationService
+        discoverServiceConfigurationForDiscoveryURL:discoveryUrl
+                                         completion:^(
+                                             OIDServiceConfiguration
+                                                 *_Nullable configuration,
+                                             NSError *_Nullable error) {
+                                           if (!configuration) {
+                                             [self
+                                                 finishWithDiscoveryError:error
+                                                                   result:
+                                                                       result];
+                                             return;
+                                           }
+
+                                           [self
+                                               performTokenRequest:configuration
+                                                 requestParameters:
+                                                     requestParameters
+                                                            result:result];
+                                         }];
+  } else {
+    NSURL *issuerUrl = [NSURL URLWithString:requestParameters.issuer];
+    [OIDAuthorizationService
+        discoverServiceConfigurationForIssuer:issuerUrl
+                                   completion:^(OIDServiceConfiguration
+                                                    *_Nullable configuration,
+                                                NSError *_Nullable error) {
+                                     if (!configuration) {
+                                       [self finishWithDiscoveryError:error
+                                                               result:result];
+                                       return;
+                                     }
+
+                                     [self performTokenRequest:configuration
+                                             requestParameters:requestParameters
+                                                        result:result];
+                                   }];
+  }
 }
 
--(void)handleEndSessionMethodCall:(NSDictionary*)arguments result:(FlutterResult)result {
-    EndSessionRequestParameters *requestParameters = [[EndSessionRequestParameters alloc] initWithArguments:arguments];
-    if(requestParameters.serviceConfigurationParameters != nil) {
-        OIDServiceConfiguration *serviceConfiguration = [self processServiceConfigurationParameters:requestParameters.serviceConfigurationParameters];
-        _currentAuthorizationFlow = [authorization performEndSessionRequest:serviceConfiguration requestParameters:requestParameters result:result];
-    } else if (requestParameters.discoveryUrl) {
-        NSURL *discoveryUrl = [NSURL URLWithString:requestParameters.discoveryUrl];
-        
-        [OIDAuthorizationService discoverServiceConfigurationForDiscoveryURL:discoveryUrl
-                                                                  completion:^(OIDServiceConfiguration *_Nullable configuration,
-                                                                               NSError *_Nullable error) {
-            if (!configuration) {
-                [self finishWithDiscoveryError:error result:result];
-                return;
-            }
-            
-            self->_currentAuthorizationFlow = [authorization performEndSessionRequest:configuration requestParameters:requestParameters result:result];
-        }];
-    } else {
-        NSURL *issuerUrl = [NSURL URLWithString:requestParameters.issuer];
-        [OIDAuthorizationService discoverServiceConfigurationForIssuer:issuerUrl
-                                                            completion:^(OIDServiceConfiguration *_Nullable configuration,
-                                                                         NSError *_Nullable error) {
-            if (!configuration) {
-                [self finishWithDiscoveryError:error result:result];
-                return;
-            }
-            
-            self->_currentAuthorizationFlow = [authorization performEndSessionRequest:configuration requestParameters:requestParameters result:result];
-        }];
-    }
+- (void)handleEndSessionMethodCall:(NSDictionary *)arguments
+                            result:(FlutterResult)result {
+  EndSessionRequestParameters *requestParameters =
+      [[EndSessionRequestParameters alloc] initWithArguments:arguments];
+  if (requestParameters.serviceConfigurationParameters != nil) {
+    OIDServiceConfiguration *serviceConfiguration =
+        [self processServiceConfigurationParameters:
+                  requestParameters.serviceConfigurationParameters];
+    _currentAuthorizationFlow =
+        [authorization performEndSessionRequest:serviceConfiguration
+                              requestParameters:requestParameters
+                                         result:result];
+  } else if (requestParameters.discoveryUrl) {
+    NSURL *discoveryUrl = [NSURL URLWithString:requestParameters.discoveryUrl];
+
+    [OIDAuthorizationService
+        discoverServiceConfigurationForDiscoveryURL:discoveryUrl
+                                         completion:^(
+                                             OIDServiceConfiguration
+                                                 *_Nullable configuration,
+                                             NSError *_Nullable error) {
+                                           if (!configuration) {
+                                             [self
+                                                 finishWithDiscoveryError:error
+                                                                   result:
+                                                                       result];
+                                             return;
+                                           }
+
+                                           self->_currentAuthorizationFlow =
+                                               [authorization
+                                                   performEndSessionRequest:
+                                                       configuration
+                                                          requestParameters:
+                                                              requestParameters
+                                                                     result:
+                                                                         result];
+                                         }];
+  } else {
+    NSURL *issuerUrl = [NSURL URLWithString:requestParameters.issuer];
+    [OIDAuthorizationService
+        discoverServiceConfigurationForIssuer:issuerUrl
+                                   completion:^(OIDServiceConfiguration
+                                                    *_Nullable configuration,
+                                                NSError *_Nullable error) {
+                                     if (!configuration) {
+                                       [self finishWithDiscoveryError:error
+                                                               result:result];
+                                       return;
+                                     }
+
+                                     self->_currentAuthorizationFlow =
+                                         [authorization
+                                             performEndSessionRequest:
+                                                 configuration
+                                                    requestParameters:
+                                                        requestParameters
+                                                               result:result];
+                                   }];
+  }
 }
 
-- (void)performTokenRequest:(OIDServiceConfiguration *)serviceConfiguration requestParameters:(TokenRequestParameters *)requestParameters result:(FlutterResult)result {
-    OIDTokenRequest *tokenRequest =
-    [[OIDTokenRequest alloc] initWithConfiguration:serviceConfiguration
-                                         grantType:requestParameters.grantType
-                                 authorizationCode:requestParameters.authorizationCode
-                                       redirectURL:[NSURL URLWithString:requestParameters.redirectUrl]
-                                          clientID:requestParameters.clientId
-                                      clientSecret:requestParameters.clientSecret
-                                            scopes:requestParameters.scopes
-                                      refreshToken:requestParameters.refreshToken
-                                      codeVerifier:requestParameters.codeVerifier
-                              additionalParameters:requestParameters.additionalParameters];
-    [OIDAuthorizationService performTokenRequest:tokenRequest
-                                        callback:^(OIDTokenResponse *_Nullable response,
-                                                   NSError *_Nullable error) {
-        if (response) {
-            result([FlutterAppAuth processResponses:response authResponse:nil]);                                           } else {
-                NSString *message = [NSString stringWithFormat:TOKEN_ERROR_MESSAGE_FORMAT, [error localizedDescription]];
-                [FlutterAppAuth finishWithError:TOKEN_ERROR_CODE message:message result:result error:error];
-            }
-    }];
+- (void)performTokenRequest:(OIDServiceConfiguration *)serviceConfiguration
+          requestParameters:(TokenRequestParameters *)requestParameters
+                     result:(FlutterResult)result {
+  OIDTokenRequest *tokenRequest = [[OIDTokenRequest alloc]
+      initWithConfiguration:serviceConfiguration
+                  grantType:requestParameters.grantType
+          authorizationCode:requestParameters.authorizationCode
+                redirectURL:[NSURL URLWithString:requestParameters.redirectUrl]
+                   clientID:requestParameters.clientId
+               clientSecret:requestParameters.clientSecret
+                     scopes:requestParameters.scopes
+               refreshToken:requestParameters.refreshToken
+               codeVerifier:requestParameters.codeVerifier
+       additionalParameters:requestParameters.additionalParameters];
+  [OIDAuthorizationService
+      performTokenRequest:tokenRequest
+                 callback:^(OIDTokenResponse *_Nullable response,
+                            NSError *_Nullable error) {
+                   if (response) {
+                     result([FlutterAppAuth processResponses:response
+                                                authResponse:nil]);
+                   } else {
+                     NSString *message = [NSString
+                         stringWithFormat:TOKEN_ERROR_MESSAGE_FORMAT,
+                                          [error localizedDescription]];
+                     [FlutterAppAuth finishWithError:TOKEN_ERROR_CODE
+                                             message:message
+                                              result:result
+                                               error:error];
+                   }
+                 }];
 }
 
 #if TARGET_OS_IOS
 - (BOOL)application:(UIApplication *)application
             openURL:(NSURL *)url
-            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
-    if ([_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]) {
-        _currentAuthorizationFlow = nil;
-        return YES;
-    }
-    
-    return NO;
+            options:
+                (NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
+  if ([_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]) {
+    _currentAuthorizationFlow = nil;
+    return YES;
+  }
+
+  return NO;
 }
 
 - (BOOL)application:(UIApplication *)application
-            openURL:(NSURL *)url
-  sourceApplication:(NSString *)sourceApplication
-         annotation:(id)annotation {
-    return [self application:application openURL:url options:@{}];
+              openURL:(NSURL *)url
+    sourceApplication:(NSString *)sourceApplication
+           annotation:(id)annotation {
+  return [self application:application openURL:url options:@{}];
 }
 #endif
 
 #if TARGET_OS_OSX
 - (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
            withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
-    NSString *URLString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
-    NSURL *URL = [NSURL URLWithString:URLString];
-    [_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:URL];
-    _currentAuthorizationFlow = nil;
+  NSString *URLString =
+      [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
+  NSURL *URL = [NSURL URLWithString:URLString];
+  [_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:URL];
+  _currentAuthorizationFlow = nil;
 }
 #endif
 
diff --git a/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSNoSSO.h b/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSNoSSO.h
index 5d8c9de7..7c376460 100644
--- a/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSNoSSO.h
+++ b/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSNoSSO.h
@@ -1,7 +1,9 @@
 /*! @file OIDExternalUserAgentIOSNoSSO.h
-    @brief OIDExternalUserAgentIOSNoSSO is a custom user agent based on the default user agent in the AppAuth iOS SDK found here:
+    @brief OIDExternalUserAgentIOSNoSSO is a custom user agent based on the
+   default user agent in the AppAuth iOS SDK found here:
             https://github.com/openid/AppAuth-iOS/blob/master/Source/iOS/OIDExternalUserAgentIOS.h
-            Ths user agent allows setting `prefersEphemeralSession` flag on iOS 13 or newer to avoid cookies being shared across the device.
+            Ths user agent allows setting `prefersEphemeralSession` flag on iOS
+   13 or newer to avoid cookies being shared across the device.
     @copydetails
         Licensed under the Apache License, Version 2.0 (the "License");
         you may not use this file except in compliance with the License.
@@ -16,27 +18,27 @@
         limitations under the License.
  */
 
-#import <UIKit/UIKit.h>
 #import <AppAuth/AppAuth.h>
+#import <UIKit/UIKit.h>
 
 @class SFSafariViewController;
 
 NS_ASSUME_NONNULL_BEGIN
 
 API_UNAVAILABLE(macCatalyst)
-@interface OIDExternalUserAgentIOSNoSSO : NSObject<OIDExternalUserAgent>
+@interface OIDExternalUserAgentIOSNoSSO : NSObject <OIDExternalUserAgent>
 
-- (nullable instancetype)init API_AVAILABLE(ios(11))
-    __deprecated_msg("This method will not work on iOS 13, use "
-                     "initWithPresentingViewController:presentingViewController");
+- (nullable instancetype)init API_AVAILABLE(ios(11))__deprecated_msg(
+    "This method will not work on iOS 13, use "
+    "initWithPresentingViewController:presentingViewController");
 
 /*! @brief The designated initializer.
-    @param presentingViewController The view controller from which to present the
+    @param presentingViewController The view controller from which to present
+   the
         \SFSafariViewController.
  */
 - (nullable instancetype)initWithPresentingViewController:
-    (UIViewController *)presentingViewController
-    NS_DESIGNATED_INITIALIZER;
+    (UIViewController *)presentingViewController NS_DESIGNATED_INITIALIZER;
 
 @end
 
diff --git a/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSNoSSO.m b/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSNoSSO.m
index a4e018ea..1ded133d 100644
--- a/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSNoSSO.m
+++ b/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSNoSSO.m
@@ -1,24 +1,27 @@
 /*! @file OIDExternalUserAgentIOSNoSSO.m
-    @brief OIDExternalUserAgentIOSNoSSO is a custom user agent based on the default user agent in the AppAuth iOS SDK found here:
+    @brief OIDExternalUserAgentIOSNoSSO is a custom user agent based on the
+   default user agent in the AppAuth iOS SDK found here:
            https://github.com/openid/AppAuth-iOS/blob/master/Source/iOS/OIDExternalUserAgentIOS.m
-           This user agent allows setting `prefersEphemeralSession` flag on iOS 13 or newer to avoid cookies being shared across the device.
+           This user agent allows setting `prefersEphemeralSession` flag on iOS
+   13 or newer to avoid cookies being shared across the device.
  */
 
 #import "OIDExternalUserAgentIOSNoSSO.h"
 
-#import <SafariServices/SafariServices.h>
 #import <AuthenticationServices/AuthenticationServices.h>
-
+#import <SafariServices/SafariServices.h>
 
 #if !TARGET_OS_MACCATALYST
 
 NS_ASSUME_NONNULL_BEGIN
 
 #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
-@interface OIDExternalUserAgentIOSNoSSO ()<SFSafariViewControllerDelegate, ASWebAuthenticationPresentationContextProviding>
+@interface OIDExternalUserAgentIOSNoSSO () <
+    SFSafariViewControllerDelegate,
+    ASWebAuthenticationPresentationContextProviding>
 @end
 #else
-@interface OIDExternalUserAgentIOSNoSSO ()<SFSafariViewControllerDelegate>
+@interface OIDExternalUserAgentIOSNoSSO () <SFSafariViewControllerDelegate>
 @end
 #endif
 
@@ -50,14 +53,15 @@ - (nullable instancetype)initWithPresentingViewController:
     NSAssert(presentingViewController != nil,
              @"presentingViewController cannot be nil on iOS 13");
 #endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
-    
+
     _presentingViewController = presentingViewController;
   }
   return self;
 }
 
 - (BOOL)presentExternalUserAgentRequest:(id<OIDExternalUserAgentRequest>)request
-                                session:(id<OIDExternalUserAgentSession>)session {
+                                session:
+                                    (id<OIDExternalUserAgentSession>)session {
   if (_externalUserAgentFlowInProgress) {
     // TODO: Handle errors as authorization is already in progress.
     return NO;
@@ -70,39 +74,43 @@ - (BOOL)presentExternalUserAgentRequest:(id<OIDExternalUserAgentRequest>)request
 
   // iOS 12 and later, use ASWebAuthenticationSession
   if (@available(iOS 12.0, *)) {
-    // ASWebAuthenticationSession doesn't work with guided access (rdar://40809553)
+    // ASWebAuthenticationSession doesn't work with guided access
+    // (rdar://40809553)
     if (!UIAccessibilityIsGuidedAccessEnabled()) {
       __weak OIDExternalUserAgentIOSNoSSO *weakSelf = self;
       NSString *redirectScheme = request.redirectScheme;
       ASWebAuthenticationSession *authenticationVC =
-          [[ASWebAuthenticationSession alloc] initWithURL:requestURL
-                                        callbackURLScheme:redirectScheme
-                                        completionHandler:^(NSURL * _Nullable callbackURL,
-                                                            NSError * _Nullable error) {
-        __strong OIDExternalUserAgentIOSNoSSO *strongSelf = weakSelf;
-        if (!strongSelf) {
-            return;
-        }
-        strongSelf->_webAuthenticationVC = nil;
-        if (callbackURL) {
-          [strongSelf->_session resumeExternalUserAgentFlowWithURL:callbackURL];
-        } else {
-          NSError *safariError =
-              [OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
-                               underlyingError:error
-                                   description:nil];
-          [strongSelf->_session failExternalUserAgentFlowWithError:safariError];
-        }
-      }];
+          [[ASWebAuthenticationSession alloc]
+                    initWithURL:requestURL
+              callbackURLScheme:redirectScheme
+              completionHandler:^(NSURL *_Nullable callbackURL,
+                                  NSError *_Nullable error) {
+                __strong OIDExternalUserAgentIOSNoSSO *strongSelf = weakSelf;
+                if (!strongSelf) {
+                  return;
+                }
+                strongSelf->_webAuthenticationVC = nil;
+                if (callbackURL) {
+                  [strongSelf->_session
+                      resumeExternalUserAgentFlowWithURL:callbackURL];
+                } else {
+                  NSError *safariError = [OIDErrorUtilities
+                        errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
+                      underlyingError:error
+                          description:nil];
+                  [strongSelf->_session
+                      failExternalUserAgentFlowWithError:safariError];
+                }
+              }];
 #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
       if (@available(iOS 13.0, *)) {
-          authenticationVC.presentationContextProvider = self;
+        authenticationVC.presentationContextProvider = self;
       }
 #endif
       _webAuthenticationVC = authenticationVC;
-        if (@available(iOS 13.0, *)) {
-            authenticationVC.prefersEphemeralWebBrowserSession = YES;
-        }
+      if (@available(iOS 13.0, *)) {
+        authenticationVC.prefersEphemeralWebBrowserSession = YES;
+      }
       openedUserAgent = [authenticationVC start];
     }
   }
@@ -113,25 +121,28 @@ - (BOOL)presentExternalUserAgentRequest:(id<OIDExternalUserAgentRequest>)request
       __weak OIDExternalUserAgentIOSNoSSO *weakSelf = self;
       NSString *redirectScheme = request.redirectScheme;
       SFAuthenticationSession *authenticationVC =
-          [[SFAuthenticationSession alloc] initWithURL:requestURL
-                                     callbackURLScheme:redirectScheme
-                                     completionHandler:^(NSURL * _Nullable callbackURL,
-                                                         NSError * _Nullable error) {
-        __strong OIDExternalUserAgentIOSNoSSO *strongSelf = weakSelf;
-        if (!strongSelf) {
-            return;
-        }
-        strongSelf->_authenticationVC = nil;
-        if (callbackURL) {
-          [strongSelf->_session resumeExternalUserAgentFlowWithURL:callbackURL];
-        } else {
-          NSError *safariError =
-              [OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
-                               underlyingError:error
-                                   description:@"User cancelled."];
-          [strongSelf->_session failExternalUserAgentFlowWithError:safariError];
-        }
-      }];
+          [[SFAuthenticationSession alloc]
+                    initWithURL:requestURL
+              callbackURLScheme:redirectScheme
+              completionHandler:^(NSURL *_Nullable callbackURL,
+                                  NSError *_Nullable error) {
+                __strong OIDExternalUserAgentIOSNoSSO *strongSelf = weakSelf;
+                if (!strongSelf) {
+                  return;
+                }
+                strongSelf->_authenticationVC = nil;
+                if (callbackURL) {
+                  [strongSelf->_session
+                      resumeExternalUserAgentFlowWithURL:callbackURL];
+                } else {
+                  NSError *safariError = [OIDErrorUtilities
+                        errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
+                      underlyingError:error
+                          description:@"User cancelled."];
+                  [strongSelf->_session
+                      failExternalUserAgentFlowWithError:safariError];
+                }
+              }];
       _authenticationVC = authenticationVC;
       openedUserAgent = [authenticationVC start];
     }
@@ -143,60 +154,68 @@ - (BOOL)presentExternalUserAgentRequest:(id<OIDExternalUserAgentRequest>)request
           [[SFSafariViewController alloc] initWithURL:requestURL];
       safariVC.delegate = self;
       _safariVC = safariVC;
-      [_presentingViewController presentViewController:safariVC animated:YES completion:nil];
+      [_presentingViewController presentViewController:safariVC
+                                              animated:YES
+                                            completion:nil];
       openedUserAgent = YES;
     }
   }
   // iOS 8 and earlier, use mobile Safari
-  if (!openedUserAgent){
+  if (!openedUserAgent) {
     openedUserAgent = [[UIApplication sharedApplication] openURL:requestURL];
   }
 
   if (!openedUserAgent) {
     [self cleanUp];
-    NSError *safariError = [OIDErrorUtilities errorWithCode:OIDErrorCodeSafariOpenError
-                                            underlyingError:nil
-                                                description:@"Unable to open Safari."];
+    NSError *safariError =
+        [OIDErrorUtilities errorWithCode:OIDErrorCodeSafariOpenError
+                         underlyingError:nil
+                             description:@"Unable to open Safari."];
     [session failExternalUserAgentFlowWithError:safariError];
   }
   return openedUserAgent;
 }
 
-- (void)dismissExternalUserAgentAnimated:(BOOL)animated completion:(void (^)(void))completion {
+- (void)dismissExternalUserAgentAnimated:(BOOL)animated
+                              completion:(void (^)(void))completion {
   if (!_externalUserAgentFlowInProgress) {
     // Ignore this call if there is no authorization flow in progress.
-    if (completion) completion();
+    if (completion)
+      completion();
     return;
   }
-  
+
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wpartial-availability"
   SFSafariViewController *safariVC = _safariVC;
   SFAuthenticationSession *authenticationVC = _authenticationVC;
   ASWebAuthenticationSession *webAuthenticationVC = _webAuthenticationVC;
 #pragma clang diagnostic pop
-  
+
   [self cleanUp];
-  
+
   if (webAuthenticationVC) {
     // dismiss the ASWebAuthenticationSession
     [webAuthenticationVC cancel];
-    if (completion) completion();
+    if (completion)
+      completion();
   } else if (authenticationVC) {
     // dismiss the SFAuthenticationSession
     [authenticationVC cancel];
-    if (completion) completion();
+    if (completion)
+      completion();
   } else if (safariVC) {
     // dismiss the SFSafariViewController
     [safariVC dismissViewControllerAnimated:YES completion:completion];
   } else {
-    if (completion) completion();
+    if (completion)
+      completion();
   }
 }
 
 - (void)cleanUp {
-  // The weak references to |_safariVC| and |_session| are set to nil to avoid accidentally using
-  // them while not in an authorization flow.
+  // The weak references to |_safariVC| and |_session| are set to nil to avoid
+  // accidentally using them while not in an authorization flow.
   _safariVC = nil;
   _authenticationVC = nil;
   _webAuthenticationVC = nil;
@@ -206,7 +225,8 @@ - (void)cleanUp {
 
 #pragma mark - SFSafariViewControllerDelegate
 
-- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller NS_AVAILABLE_IOS(9.0) {
+- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller
+    NS_AVAILABLE_IOS(9.0) {
   if (controller != _safariVC) {
     // Ignore this call if the safari view controller do not match.
     return;
@@ -217,16 +237,18 @@ - (void)safariViewControllerDidFinish:(SFSafariViewController *)controller NS_AV
   }
   id<OIDExternalUserAgentSession> session = _session;
   [self cleanUp];
-  NSError *error = [OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
-                                    underlyingError:nil
-                                        description:@"No external user agent flow in progress."];
+  NSError *error = [OIDErrorUtilities
+        errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
+      underlyingError:nil
+          description:@"No external user agent flow in progress."];
   [session failExternalUserAgentFlowWithError:error];
 }
 
 #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
 #pragma mark - ASWebAuthenticationPresentationContextProviding
 
-- (ASPresentationAnchor)presentationAnchorForWebAuthenticationSession:(ASWebAuthenticationSession *)session API_AVAILABLE(ios(13.0)){
+- (ASPresentationAnchor)presentationAnchorForWebAuthenticationSession:
+    (ASWebAuthenticationSession *)session API_AVAILABLE(ios(13.0)) {
   return _presentingViewController.view.window;
 }
 #endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
diff --git a/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSSafariViewController.h b/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSSafariViewController.h
index cbf6dc87..ed4745db 100644
--- a/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSSafariViewController.h
+++ b/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSSafariViewController.h
@@ -16,19 +16,21 @@
 
 #import <UIKit/UIKit.h>
 
-#import "OIDExternalUserAgentIOSSafariViewController.h"
 #import "OIDExternalUserAgent.h"
 #import "OIDExternalUserAgentIOS.h"
+#import "OIDExternalUserAgentIOSSafariViewController.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
-/*! @brief Allows library consumers to bootstrap an @c SFSafariViewController as they see fit.
+/*! @brief Allows library consumers to bootstrap an @c SFSafariViewController as
+   they see fit.
     @remarks Useful for customizing tint colors and presentation styles.
  */
 @protocol OIDSafariViewControllerFactory
 
 /*! @brief Creates and returns a new @c SFSafariViewController.
-    @param URL The URL which the @c SFSafariViewController should load initially.
+    @param URL The URL which the @c SFSafariViewController should load
+   initially.
  */
 - (SFSafariViewController *)safariViewControllerWithURL:(NSURL *)URL;
 
@@ -40,15 +42,19 @@ NS_ASSUME_NONNULL_BEGIN
         AppAuth user-agent handling with the benefits of Single Sign-on (SSO)
         for all supported versions of iOS.
  */
-@interface OIDExternalUserAgentIOSSafariViewController : NSObject<OIDExternalUserAgent>
+@interface OIDExternalUserAgentIOSSafariViewController
+    : NSObject <OIDExternalUserAgent>
 
-/*! @brief Allows library consumers to change the @c OIDSafariViewControllerFactory used to create
-        new instances of @c SFSafariViewController.
+/*! @brief Allows library consumers to change the @c
+   OIDSafariViewControllerFactory used to create new instances of @c
+   SFSafariViewController.
     @remarks Useful for customizing tint colors and presentation styles.
-    @param factory The @c OIDSafariViewControllerFactory to use for creating new instances of
+    @param factory The @c OIDSafariViewControllerFactory to use for creating new
+   instances of
         @c SFSafariViewController.
  */
-+ (void)setSafariViewControllerFactory:(id<OIDSafariViewControllerFactory>)factory;
++ (void)setSafariViewControllerFactory:
+    (id<OIDSafariViewControllerFactory>)factory;
 
 /*! @internal
     @brief Unavailable. Please use @c initWithPresentingViewController:
@@ -56,12 +62,12 @@ NS_ASSUME_NONNULL_BEGIN
 - (nonnull instancetype)init NS_UNAVAILABLE;
 
 /*! @brief The designated initializer.
-    @param presentingViewController The view controller from which to present the
+    @param presentingViewController The view controller from which to present
+   the
         \SFSafariViewController.
  */
 - (nullable instancetype)initWithPresentingViewController:
-    (UIViewController *)presentingViewController
-            NS_DESIGNATED_INITIALIZER;
+    (UIViewController *)presentingViewController NS_DESIGNATED_INITIALIZER;
 
 @end
 
diff --git a/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSSafariViewController.m b/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSSafariViewController.m
index 5de4e168..ff6d3ce8 100644
--- a/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSSafariViewController.m
+++ b/flutter_appauth/ios/Classes/OIDExternalUserAgentIOSSafariViewController.m
@@ -19,154 +19,171 @@
 #import <SafariServices/SafariServices.h>
 
 #import "OIDErrorUtilities.h"
-#import "OIDExternalUserAgentSession.h"
 #import "OIDExternalUserAgentRequest.h"
+#import "OIDExternalUserAgentSession.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
-/** @brief The global/shared Safari view controller factory. Responsible for creating all new
- instances of @c SFSafariViewController.
+/** @brief The global/shared Safari view controller factory. Responsible for
+ creating all new instances of @c SFSafariViewController.
  */
-static id<OIDSafariViewControllerFactory> __nullable gSafariViewControllerFactory;
+static id<OIDSafariViewControllerFactory> __nullable
+    gSafariViewControllerFactory;
 
-/** @brief The default @c OIDSafariViewControllerFactory which creates new instances of
+/** @brief The default @c OIDSafariViewControllerFactory which creates new
+   instances of
         @c SFSafariViewController using known best practices.
  */
-@interface OIDDefaultSafariViewControllerFactory : NSObject<OIDSafariViewControllerFactory>
+@interface OIDDefaultSafariViewControllerFactory
+    : NSObject <OIDSafariViewControllerFactory>
 @end
 
-@interface OIDExternalUserAgentIOSSafariViewController ()<SFSafariViewControllerDelegate>
+@interface OIDExternalUserAgentIOSSafariViewController () <
+    SFSafariViewControllerDelegate>
 @end
 
 @implementation OIDExternalUserAgentIOSSafariViewController {
-    UIViewController *_presentingViewController;
+  UIViewController *_presentingViewController;
 
-    BOOL _externalUserAgentFlowInProgress;
-    __weak id<OIDExternalUserAgentSession> _session;
+  BOOL _externalUserAgentFlowInProgress;
+  __weak id<OIDExternalUserAgentSession> _session;
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wpartial-availability"
-    __weak SFSafariViewController *_safariVC;
+  __weak SFSafariViewController *_safariVC;
 #pragma clang diagnostic pop
 }
 
-/** @brief Obtains the current @c OIDSafariViewControllerFactory; creating a new default instance if
-        required.
+/** @brief Obtains the current @c OIDSafariViewControllerFactory; creating a new
+   default instance if required.
  */
 + (id<OIDSafariViewControllerFactory>)safariViewControllerFactory {
-    if (!gSafariViewControllerFactory) {
-        gSafariViewControllerFactory = [[OIDDefaultSafariViewControllerFactory alloc] init];
-    }
-    return gSafariViewControllerFactory;
+  if (!gSafariViewControllerFactory) {
+    gSafariViewControllerFactory =
+        [[OIDDefaultSafariViewControllerFactory alloc] init];
+  }
+  return gSafariViewControllerFactory;
 }
 
-+ (void)setSafariViewControllerFactory:(id<OIDSafariViewControllerFactory>)factory {
-    NSAssert(factory, @"Parameter: |factory| must be non-nil.");
-    gSafariViewControllerFactory = factory;
++ (void)setSafariViewControllerFactory:
+    (id<OIDSafariViewControllerFactory>)factory {
+  NSAssert(factory, @"Parameter: |factory| must be non-nil.");
+  gSafariViewControllerFactory = factory;
 }
 
 - (nullable instancetype)initWithPresentingViewController:
-        (UIViewController *)presentingViewController {
-    self = [super init];
-    if (self) {
-        _presentingViewController = presentingViewController;
-    }
-    return self;
+    (UIViewController *)presentingViewController {
+  self = [super init];
+  if (self) {
+    _presentingViewController = presentingViewController;
+  }
+  return self;
 }
 
 - (BOOL)presentExternalUserAgentRequest:(id<OIDExternalUserAgentRequest>)request
-                                session:(id<OIDExternalUserAgentSession>)session {
-    if (_externalUserAgentFlowInProgress) {
-        // TODO: Handle errors as authorization is already in progress.
-        return NO;
-    }
-
-    _externalUserAgentFlowInProgress = YES;
-    _session = session;
-    BOOL openedSafari = NO;
-    NSURL *requestURL = [request externalUserAgentRequestURL];
-
-    if (@available(iOS 9.0, *)) {
-        SFSafariViewController *safariVC =
-                [[[self class] safariViewControllerFactory] safariViewControllerWithURL:requestURL];
-        safariVC.delegate = self;
-        safariVC.modalPresentationStyle = UIModalPresentationFormSheet;
-        _safariVC = safariVC;
-        [_presentingViewController presentViewController:safariVC animated:YES completion:nil];
-        openedSafari = YES;
-    } else {
+                                session:
+                                    (id<OIDExternalUserAgentSession>)session {
+  if (_externalUserAgentFlowInProgress) {
+    // TODO: Handle errors as authorization is already in progress.
+    return NO;
+  }
+
+  _externalUserAgentFlowInProgress = YES;
+  _session = session;
+  BOOL openedSafari = NO;
+  NSURL *requestURL = [request externalUserAgentRequestURL];
+
+  if (@available(iOS 9.0, *)) {
+    SFSafariViewController *safariVC = [[[self class]
+        safariViewControllerFactory] safariViewControllerWithURL:requestURL];
+    safariVC.delegate = self;
+    safariVC.modalPresentationStyle = UIModalPresentationFormSheet;
+    _safariVC = safariVC;
+    [_presentingViewController presentViewController:safariVC
+                                            animated:YES
+                                          completion:nil];
+    openedSafari = YES;
+  } else {
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
-        openedSafari = [[UIApplication sharedApplication] openURL:requestURL];
-    }
+    openedSafari = [[UIApplication sharedApplication] openURL:requestURL];
+  }
 
-    if (!openedSafari) {
-        [self cleanUp];
-        NSError *safariError = [OIDErrorUtilities errorWithCode:OIDErrorCodeSafariOpenError
-                                                underlyingError:nil
-                                                    description:@"Unable to open Safari."];
-        [session failExternalUserAgentFlowWithError:safariError];
-    }
-    return openedSafari;
+  if (!openedSafari) {
+    [self cleanUp];
+    NSError *safariError =
+        [OIDErrorUtilities errorWithCode:OIDErrorCodeSafariOpenError
+                         underlyingError:nil
+                             description:@"Unable to open Safari."];
+    [session failExternalUserAgentFlowWithError:safariError];
+  }
+  return openedSafari;
 }
 
-- (void)dismissExternalUserAgentAnimated:(BOOL)animated completion:(void (^)(void))completion {
-    if (!_externalUserAgentFlowInProgress) {
-        // Ignore this call if there is no authorization flow in progress.
-        return;
-    }
+- (void)dismissExternalUserAgentAnimated:(BOOL)animated
+                              completion:(void (^)(void))completion {
+  if (!_externalUserAgentFlowInProgress) {
+    // Ignore this call if there is no authorization flow in progress.
+    return;
+  }
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wpartial-availability"
-    SFSafariViewController *safariVC = _safariVC;
+  SFSafariViewController *safariVC = _safariVC;
 #pragma clang diagnostic pop
 
-    [self cleanUp];
+  [self cleanUp];
 
-    if (@available(iOS 9.0, *)) {
-        if (safariVC) {
-            [safariVC dismissViewControllerAnimated:YES completion:completion];
-        } else {
-            if (completion) completion();
-        }
+  if (@available(iOS 9.0, *)) {
+    if (safariVC) {
+      [safariVC dismissViewControllerAnimated:YES completion:completion];
     } else {
-        if (completion) completion();
+      if (completion)
+        completion();
     }
+  } else {
+    if (completion)
+      completion();
+  }
 }
 
 - (void)cleanUp {
-    // The weak references to |_safariVC| and |_session| are set to nil to avoid accidentally using
-    // them while not in an authorization flow.
-    _safariVC = nil;
-    _session = nil;
-    _externalUserAgentFlowInProgress = NO;
+  // The weak references to |_safariVC| and |_session| are set to nil to avoid
+  // accidentally using them while not in an authorization flow.
+  _safariVC = nil;
+  _session = nil;
+  _externalUserAgentFlowInProgress = NO;
 }
 
 #pragma mark - SFSafariViewControllerDelegate
 
-- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller NS_AVAILABLE_IOS(9.0) {
-    if (controller != _safariVC) {
-        // Ignore this call if the safari view controller do not match.
-        return;
-    }
-    if (!_externalUserAgentFlowInProgress) {
-        // Ignore this call if there is no authorization flow in progress.
-        return;
-    }
-    id<OIDExternalUserAgentSession> session = _session;
-    [self cleanUp];
-    NSError *error = [OIDErrorUtilities errorWithCode:OIDErrorCodeProgramCanceledAuthorizationFlow
-                                      underlyingError:nil
-                                          description:nil];
-    [session failExternalUserAgentFlowWithError:error];
+- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller
+    NS_AVAILABLE_IOS(9.0) {
+  if (controller != _safariVC) {
+    // Ignore this call if the safari view controller do not match.
+    return;
+  }
+  if (!_externalUserAgentFlowInProgress) {
+    // Ignore this call if there is no authorization flow in progress.
+    return;
+  }
+  id<OIDExternalUserAgentSession> session = _session;
+  [self cleanUp];
+  NSError *error = [OIDErrorUtilities
+        errorWithCode:OIDErrorCodeProgramCanceledAuthorizationFlow
+      underlyingError:nil
+          description:nil];
+  [session failExternalUserAgentFlowWithError:error];
 }
 
 @end
 
 @implementation OIDDefaultSafariViewControllerFactory
 
-- (SFSafariViewController *)safariViewControllerWithURL:(NSURL *)URL NS_AVAILABLE_IOS(9.0) {
-    SFSafariViewController *safariViewController =
-            [[SFSafariViewController alloc] initWithURL:URL entersReaderIfAvailable:NO];
-    return safariViewController;
+- (SFSafariViewController *)safariViewControllerWithURL:(NSURL *)URL
+    NS_AVAILABLE_IOS(9.0) {
+  SFSafariViewController *safariViewController =
+      [[SFSafariViewController alloc] initWithURL:URL
+                          entersReaderIfAvailable:NO];
+  return safariViewController;
 }
 
 @end
diff --git a/flutter_appauth/macos/Classes/AppAuthMacOSAuthorization.h b/flutter_appauth/macos/Classes/AppAuthMacOSAuthorization.h
index 5f748e95..7bd7d860 100644
--- a/flutter_appauth/macos/Classes/AppAuthMacOSAuthorization.h
+++ b/flutter_appauth/macos/Classes/AppAuthMacOSAuthorization.h
@@ -1,8 +1,7 @@
-#import <FlutterMacOS/FlutterMacOS.h>
-#import <AppAuth/AppAuth.h>
-#import "OIDExternalUserAgentMacNoSSO.h"
 #import "FlutterAppAuth.h"
-
+#import "OIDExternalUserAgentMacNoSSO.h"
+#import <AppAuth/AppAuth.h>
+#import <FlutterMacOS/FlutterMacOS.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
diff --git a/flutter_appauth/macos/Classes/AppAuthMacOSAuthorization.m b/flutter_appauth/macos/Classes/AppAuthMacOSAuthorization.m
index c5cdcb03..30a4694c 100644
--- a/flutter_appauth/macos/Classes/AppAuthMacOSAuthorization.m
+++ b/flutter_appauth/macos/Classes/AppAuthMacOSAuthorization.m
@@ -2,78 +2,174 @@
 
 @implementation AppAuthMacOSAuthorization
 
-- (id<OIDExternalUserAgentSession>)performAuthorization:(OIDServiceConfiguration *)serviceConfiguration clientId:(NSString*)clientId clientSecret:(NSString*)clientSecret scopes:(NSArray *)scopes redirectUrl:(NSString*)redirectUrl additionalParameters:(NSDictionary *)additionalParameters externalUserAgent:(NSNumber*)externalUserAgent result:(FlutterResult)result exchangeCode:(BOOL)exchangeCode nonce:(NSString*)nonce {
-    NSString *codeVerifier = [OIDAuthorizationRequest generateCodeVerifier];
-    NSString *codeChallenge = [OIDAuthorizationRequest codeChallengeS256ForVerifier:codeVerifier];
+- (id<OIDExternalUserAgentSession>)
+    performAuthorization:(OIDServiceConfiguration *)serviceConfiguration
+                clientId:(NSString *)clientId
+            clientSecret:(NSString *)clientSecret
+                  scopes:(NSArray *)scopes
+             redirectUrl:(NSString *)redirectUrl
+    additionalParameters:(NSDictionary *)additionalParameters
+       externalUserAgent:(NSNumber *)externalUserAgent
+                  result:(FlutterResult)result
+            exchangeCode:(BOOL)exchangeCode
+                   nonce:(NSString *)nonce {
+  NSString *codeVerifier = [OIDAuthorizationRequest generateCodeVerifier];
+  NSString *codeChallenge =
+      [OIDAuthorizationRequest codeChallengeS256ForVerifier:codeVerifier];
 
-    OIDAuthorizationRequest *request =
-    [[OIDAuthorizationRequest alloc] initWithConfiguration:serviceConfiguration
-                                                  clientId:clientId
-                                              clientSecret:clientSecret
-                                                     scope:[OIDScopeUtilities scopesWithArray:scopes]
-                                               redirectURL:[NSURL URLWithString:redirectUrl]
-                                              responseType:OIDResponseTypeCode
-                                                     state:[OIDAuthorizationRequest generateState]
-                                                     nonce: nonce != nil ? nonce : [OIDAuthorizationRequest generateState]
-                                              codeVerifier:codeVerifier
-                                             codeChallenge:codeChallenge
-                                       codeChallengeMethod:OIDOAuthorizationRequestCodeChallengeMethodS256
-                                      additionalParameters:additionalParameters];
-    NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow];
-    if(exchangeCode) {
-        NSObject<OIDExternalUserAgent> *agent = [self userAgentWithPresentingWindow:keyWindow externalUserAgent:externalUserAgent];
-        return [OIDAuthState authStateByPresentingAuthorizationRequest:request externalUserAgent:agent callback:^(OIDAuthState *_Nullable authState,
-                                                                                                                  NSError *_Nullable error) {
-            if(authState) {
-                result([FlutterAppAuth processResponses:authState.lastTokenResponse authResponse:authState.lastAuthorizationResponse]);
-                
-            } else {
-                [FlutterAppAuth finishWithError:AUTHORIZE_AND_EXCHANGE_CODE_ERROR_CODE message:[FlutterAppAuth formatMessageWithError:AUTHORIZE_ERROR_MESSAGE_FORMAT error:error] result:result error:error];
-            }
-        }];
-    } else {
-        NSObject<OIDExternalUserAgent> *agent = [self userAgentWithPresentingWindow:keyWindow externalUserAgent:externalUserAgent];
-        return [OIDAuthorizationService presentAuthorizationRequest:request externalUserAgent:agent callback:^(OIDAuthorizationResponse *_Nullable authorizationResponse, NSError *_Nullable error) {
-            if(authorizationResponse) {
-                NSMutableDictionary *processedResponse = [[NSMutableDictionary alloc] init];
-                [processedResponse setObject:authorizationResponse.additionalParameters forKey:@"authorizationAdditionalParameters"];
-                [processedResponse setObject:authorizationResponse.authorizationCode forKey:@"authorizationCode"];
-                [processedResponse setObject:authorizationResponse.request.codeVerifier forKey:@"codeVerifier"];
-                [processedResponse setObject:authorizationResponse.request.nonce forKey:@"nonce"];
-                result(processedResponse);
-            } else {
-                [FlutterAppAuth finishWithError:AUTHORIZE_ERROR_CODE message:[FlutterAppAuth formatMessageWithError:AUTHORIZE_ERROR_MESSAGE_FORMAT error:error] result:result error:error];
-            }
-        }];
-    }
+  OIDAuthorizationRequest *request = [[OIDAuthorizationRequest alloc]
+      initWithConfiguration:serviceConfiguration
+                   clientId:clientId
+               clientSecret:clientSecret
+                      scope:[OIDScopeUtilities scopesWithArray:scopes]
+                redirectURL:[NSURL URLWithString:redirectUrl]
+               responseType:OIDResponseTypeCode
+                      state:[OIDAuthorizationRequest generateState]
+                      nonce:nonce != nil
+                                ? nonce
+                                : [OIDAuthorizationRequest generateState]
+               codeVerifier:codeVerifier
+              codeChallenge:codeChallenge
+        codeChallengeMethod:OIDOAuthorizationRequestCodeChallengeMethodS256
+       additionalParameters:additionalParameters];
+  NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow];
+  if (exchangeCode) {
+    NSObject<OIDExternalUserAgent> *agent =
+        [self userAgentWithPresentingWindow:keyWindow
+                          externalUserAgent:externalUserAgent];
+    return [OIDAuthState
+        authStateByPresentingAuthorizationRequest:request
+                                externalUserAgent:agent
+                                         callback:^(
+                                             OIDAuthState *_Nullable authState,
+                                             NSError *_Nullable error) {
+                                           if (authState) {
+                                             result([FlutterAppAuth
+                                                 processResponses:
+                                                     authState.lastTokenResponse
+                                                     authResponse:
+                                                         authState
+                                                             .lastAuthorizationResponse]);
+
+                                           } else {
+                                             [FlutterAppAuth
+                                                 finishWithError:
+                                                     AUTHORIZE_AND_EXCHANGE_CODE_ERROR_CODE
+                                                         message:
+                                                             [FlutterAppAuth
+                                                                 formatMessageWithError:
+                                                                     AUTHORIZE_ERROR_MESSAGE_FORMAT
+                                                                                  error:
+                                                                                      error]
+                                                          result:result
+                                                           error:error];
+                                           }
+                                         }];
+  } else {
+    NSObject<OIDExternalUserAgent> *agent =
+        [self userAgentWithPresentingWindow:keyWindow
+                          externalUserAgent:externalUserAgent];
+    return [OIDAuthorizationService
+        presentAuthorizationRequest:request
+                  externalUserAgent:agent
+                           callback:^(OIDAuthorizationResponse
+                                          *_Nullable authorizationResponse,
+                                      NSError *_Nullable error) {
+                             if (authorizationResponse) {
+                               NSMutableDictionary *processedResponse =
+                                   [[NSMutableDictionary alloc] init];
+                               [processedResponse
+                                   setObject:authorizationResponse
+                                                 .additionalParameters
+                                      forKey:
+                                          @"authorizationAdditionalParameters"];
+                               [processedResponse
+                                   setObject:authorizationResponse
+                                                 .authorizationCode
+                                      forKey:@"authorizationCode"];
+                               [processedResponse
+                                   setObject:authorizationResponse.request
+                                                 .codeVerifier
+                                      forKey:@"codeVerifier"];
+                               [processedResponse
+                                   setObject:authorizationResponse.request.nonce
+                                      forKey:@"nonce"];
+                               result(processedResponse);
+                             } else {
+                               [FlutterAppAuth
+                                   finishWithError:AUTHORIZE_ERROR_CODE
+                                           message:
+                                               [FlutterAppAuth
+                                                   formatMessageWithError:
+                                                       AUTHORIZE_ERROR_MESSAGE_FORMAT
+                                                                    error:error]
+                                            result:result
+                                             error:error];
+                             }
+                           }];
+  }
 }
 
-- (id<OIDExternalUserAgentSession>)performEndSessionRequest:(OIDServiceConfiguration *)serviceConfiguration requestParameters:(EndSessionRequestParameters *)requestParameters result:(FlutterResult)result {
-    NSURL *postLogoutRedirectURL = requestParameters.postLogoutRedirectUrl ? [NSURL URLWithString:requestParameters.postLogoutRedirectUrl] : nil;
-    
-    OIDEndSessionRequest *endSessionRequest = requestParameters.state ? [[OIDEndSessionRequest alloc] initWithConfiguration:serviceConfiguration idTokenHint:requestParameters.idTokenHint postLogoutRedirectURL:postLogoutRedirectURL
-                                                                                                                      state:requestParameters.state additionalParameters:requestParameters.additionalParameters] :[[OIDEndSessionRequest alloc] initWithConfiguration:serviceConfiguration idTokenHint:requestParameters.idTokenHint postLogoutRedirectURL:postLogoutRedirectURL
-                                                                                                                                                                                                                                                 additionalParameters:requestParameters.additionalParameters];
-    
-    NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow];
-    id<OIDExternalUserAgent> externalUserAgent = [self userAgentWithPresentingWindow:keyWindow externalUserAgent:requestParameters.externalUserAgent];
-    return [OIDAuthorizationService presentEndSessionRequest:endSessionRequest externalUserAgent:externalUserAgent callback:^(OIDEndSessionResponse * _Nullable endSessionResponse, NSError * _Nullable error) {
-        if(!endSessionResponse) {
-            NSString *message = [NSString stringWithFormat:END_SESSION_ERROR_MESSAGE_FORMAT, [error localizedDescription]];
-            [FlutterAppAuth finishWithError:END_SESSION_ERROR_CODE message:message result:result error:error];
-            return;
-        }
-        NSMutableDictionary *processedResponse = [[NSMutableDictionary alloc] init];
-        [processedResponse setObject:endSessionResponse.state forKey:@"state"];
-        result(processedResponse);
-    }];
+- (id<OIDExternalUserAgentSession>)
+    performEndSessionRequest:(OIDServiceConfiguration *)serviceConfiguration
+           requestParameters:(EndSessionRequestParameters *)requestParameters
+                      result:(FlutterResult)result {
+  NSURL *postLogoutRedirectURL =
+      requestParameters.postLogoutRedirectUrl
+          ? [NSURL URLWithString:requestParameters.postLogoutRedirectUrl]
+          : nil;
+
+  OIDEndSessionRequest *endSessionRequest =
+      requestParameters.state
+          ? [[OIDEndSessionRequest alloc]
+                initWithConfiguration:serviceConfiguration
+                          idTokenHint:requestParameters.idTokenHint
+                postLogoutRedirectURL:postLogoutRedirectURL
+                                state:requestParameters.state
+                 additionalParameters:requestParameters.additionalParameters]
+          : [[OIDEndSessionRequest alloc]
+                initWithConfiguration:serviceConfiguration
+                          idTokenHint:requestParameters.idTokenHint
+                postLogoutRedirectURL:postLogoutRedirectURL
+                 additionalParameters:requestParameters.additionalParameters];
+
+  NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow];
+  id<OIDExternalUserAgent> externalUserAgent =
+      [self userAgentWithPresentingWindow:keyWindow
+                        externalUserAgent:requestParameters.externalUserAgent];
+  return [OIDAuthorizationService
+      presentEndSessionRequest:endSessionRequest
+             externalUserAgent:externalUserAgent
+                      callback:^(
+                          OIDEndSessionResponse *_Nullable endSessionResponse,
+                          NSError *_Nullable error) {
+                        if (!endSessionResponse) {
+                          NSString *message = [NSString
+                              stringWithFormat:END_SESSION_ERROR_MESSAGE_FORMAT,
+                                               [error localizedDescription]];
+                          [FlutterAppAuth finishWithError:END_SESSION_ERROR_CODE
+                                                  message:message
+                                                   result:result
+                                                    error:error];
+                          return;
+                        }
+                        NSMutableDictionary *processedResponse =
+                            [[NSMutableDictionary alloc] init];
+                        [processedResponse setObject:endSessionResponse.state
+                                              forKey:@"state"];
+                        result(processedResponse);
+                      }];
 }
 
-- (id<OIDExternalUserAgent>)userAgentWithPresentingWindow:(NSWindow *)presentingWindow externalUserAgent:(NSNumber*)externalUserAgent {
-    if ([externalUserAgent integerValue] == EphemeralASWebAuthenticationSession) {
-        return [[OIDExternalUserAgentMacNoSSO alloc] initWithPresentingWindow:presentingWindow];
-    }
-    return [[OIDExternalUserAgentMac alloc] initWithPresentingWindow:presentingWindow];
+- (id<OIDExternalUserAgent>)
+    userAgentWithPresentingWindow:(NSWindow *)presentingWindow
+                externalUserAgent:(NSNumber *)externalUserAgent {
+  if ([externalUserAgent integerValue] == EphemeralASWebAuthenticationSession) {
+    return [[OIDExternalUserAgentMacNoSSO alloc]
+        initWithPresentingWindow:presentingWindow];
+  }
+  return [[OIDExternalUserAgentMac alloc]
+      initWithPresentingWindow:presentingWindow];
 }
 
 @end
diff --git a/flutter_appauth/macos/Classes/FlutterAppAuth.m b/flutter_appauth/macos/Classes/FlutterAppAuth.m
deleted file mode 120000
index 0d1e69b4..00000000
--- a/flutter_appauth/macos/Classes/FlutterAppAuth.m
+++ /dev/null
@@ -1 +0,0 @@
-../../ios/Classes/FlutterAppAuth.m
\ No newline at end of file
diff --git a/flutter_appauth/macos/Classes/FlutterAppAuth.m b/flutter_appauth/macos/Classes/FlutterAppAuth.m
new file mode 100644
index 00000000..4b448d7b
--- /dev/null
+++ b/flutter_appauth/macos/Classes/FlutterAppAuth.m
@@ -0,0 +1,149 @@
+#import "FlutterAppAuth.h"
+
+@implementation FlutterAppAuth
+
++ (NSMutableDictionary *)processResponses:(OIDTokenResponse *)tokenResponse
+                             authResponse:
+                                 (OIDAuthorizationResponse *)authResponse {
+  NSMutableDictionary *processedResponses = [[NSMutableDictionary alloc] init];
+  if (tokenResponse.accessToken) {
+    [processedResponses setValue:tokenResponse.accessToken
+                          forKey:@"accessToken"];
+  }
+  if (tokenResponse.accessTokenExpirationDate) {
+    [processedResponses
+        setValue:[[NSNumber alloc]
+                     initWithDouble:[tokenResponse.accessTokenExpirationDate
+                                            timeIntervalSince1970] *
+                                    1000]
+          forKey:@"accessTokenExpirationTime"];
+  }
+  if (authResponse) {
+    if (authResponse.additionalParameters) {
+      [processedResponses setObject:authResponse.additionalParameters
+                             forKey:@"authorizationAdditionalParameters"];
+    }
+    if (authResponse.request && authResponse.request.nonce) {
+      [processedResponses setObject:authResponse.request.nonce forKey:@"nonce"];
+    }
+  }
+  if (tokenResponse.additionalParameters) {
+    [processedResponses setObject:tokenResponse.additionalParameters
+                           forKey:@"tokenAdditionalParameters"];
+  }
+  if (tokenResponse.idToken) {
+    [processedResponses setValue:tokenResponse.idToken forKey:@"idToken"];
+  }
+  if (tokenResponse.refreshToken) {
+    [processedResponses setValue:tokenResponse.refreshToken
+                          forKey:@"refreshToken"];
+  }
+  if (tokenResponse.tokenType) {
+    [processedResponses setValue:tokenResponse.tokenType forKey:@"tokenType"];
+  }
+  if (tokenResponse.scope) {
+    [processedResponses
+        setObject:[tokenResponse.scope componentsSeparatedByString:@" "]
+           forKey:@"scopes"];
+  }
+
+  return processedResponses;
+}
+
++ (void)finishWithError:(NSString *)errorCode
+                message:(NSString *)message
+                 result:(FlutterResult)result
+                  error:(NSError *_Nullable)error {
+
+  NSMutableDictionary<NSString *, id> *details =
+      [NSMutableDictionary dictionary];
+
+  if (error) {
+    id authError = error.userInfo[OIDOAuthErrorResponseErrorKey];
+    NSDictionary<NSString *, id> *authErrorMap =
+        [authError isKindOfClass:[NSDictionary class]] ? authError : nil;
+
+    if (authErrorMap) {
+      if ([authErrorMap objectForKey:OIDOAuthErrorFieldError]) {
+        [details setObject:authErrorMap[OIDOAuthErrorFieldError]
+                    forKey:OIDOAuthErrorFieldError];
+      }
+      if ([authErrorMap objectForKey:OIDOAuthErrorFieldErrorDescription]) {
+        [details setObject:authErrorMap[OIDOAuthErrorFieldErrorDescription]
+                    forKey:OIDOAuthErrorFieldErrorDescription];
+      }
+      if ([authErrorMap objectForKey:OIDOAuthErrorFieldErrorURI]) {
+        [details setObject:authErrorMap[OIDOAuthErrorFieldErrorURI]
+                    forKey:OIDOAuthErrorFieldErrorURI];
+      }
+    }
+    if (error.domain) {
+      [details setObject:error.domain forKey:@"type"];
+    }
+    if (error.code) {
+      [details setObject:[@(error.code) stringValue] forKey:@"code"];
+    }
+
+    id underlyingErr = [error.userInfo objectForKey:NSUnderlyingErrorKey];
+    NSError *underlyingError =
+        [underlyingErr isKindOfClass:[NSError class]] ? underlyingErr : nil;
+    if (underlyingError) {
+      if (underlyingError.domain) {
+        [details setObject:underlyingError.domain forKey:@"domain"];
+      }
+
+      if (underlyingError.debugDescription) {
+        [details setObject:underlyingError.debugDescription
+                    forKey:@"root_cause_debug_description"];
+      }
+    }
+
+    if (error.debugDescription) {
+      [details setObject:error.debugDescription
+                  forKey:@"error_debug_description"];
+    }
+
+    bool userDidCancel =
+        [error.domain isEqual:@"org.openid.appauth.general"] &&
+        error.code == OIDErrorCodeUserCanceledAuthorizationFlow;
+    [details setObject:(userDidCancel ? @"true" : @"false")
+                forKey:@"user_did_cancel"];
+  }
+  result([FlutterError errorWithCode:errorCode
+                             message:message
+                             details:details]);
+}
+
++ (NSString *)formatMessageWithError:(NSString *)messageFormat
+                               error:(NSError *_Nullable)error {
+  NSString *formattedMessage =
+      [NSString stringWithFormat:messageFormat, [error localizedDescription]];
+  return formattedMessage;
+}
+
+@end
+
+@implementation AppAuthAuthorization
+
+- (id<OIDExternalUserAgentSession>)
+    performAuthorization:(OIDServiceConfiguration *)serviceConfiguration
+                clientId:(NSString *)clientId
+            clientSecret:(NSString *)clientSecret
+                  scopes:(NSArray *)scopes
+             redirectUrl:(NSString *)redirectUrl
+    additionalParameters:(NSDictionary *)additionalParameters
+       externalUserAgent:(NSNumber *)externalUserAgent
+                  result:(FlutterResult)result
+            exchangeCode:(BOOL)exchangeCode
+                   nonce:(NSString *)nonce {
+  return nil;
+}
+
+- (id<OIDExternalUserAgentSession>)
+    performEndSessionRequest:(OIDServiceConfiguration *)serviceConfiguration
+           requestParameters:(EndSessionRequestParameters *)requestParameters
+                      result:(FlutterResult)result {
+  return nil;
+}
+
+@end
diff --git a/flutter_appauth/macos/Classes/FlutterAppauthPlugin.m b/flutter_appauth/macos/Classes/FlutterAppauthPlugin.m
deleted file mode 120000
index 15348db3..00000000
--- a/flutter_appauth/macos/Classes/FlutterAppauthPlugin.m
+++ /dev/null
@@ -1 +0,0 @@
-../../ios/Classes/FlutterAppauthPlugin.m
\ No newline at end of file
diff --git a/flutter_appauth/macos/Classes/FlutterAppauthPlugin.m b/flutter_appauth/macos/Classes/FlutterAppauthPlugin.m
new file mode 100644
index 00000000..293cf8c0
--- /dev/null
+++ b/flutter_appauth/macos/Classes/FlutterAppauthPlugin.m
@@ -0,0 +1,513 @@
+#import <TargetConditionals.h>
+
+#import "FlutterAppauthPlugin.h"
+
+@interface ArgumentProcessor : NSObject
++ (id _Nullable)processArgumentValue:(NSDictionary *)arguments
+                             withKey:(NSString *)key;
+@end
+
+@implementation ArgumentProcessor
+
++ (id _Nullable)processArgumentValue:(NSDictionary *)arguments
+                             withKey:(NSString *)key {
+  return [arguments objectForKey:key] != [NSNull null] ? arguments[key] : nil;
+}
+
+@end
+
+@interface TokenRequestParameters : NSObject
+@property(nonatomic, strong) NSString *clientId;
+@property(nonatomic, strong) NSString *clientSecret;
+@property(nonatomic, strong) NSString *issuer;
+@property(nonatomic, strong) NSString *grantType;
+@property(nonatomic, strong) NSString *discoveryUrl;
+@property(nonatomic, strong) NSString *redirectUrl;
+@property(nonatomic, strong) NSString *refreshToken;
+@property(nonatomic, strong) NSString *codeVerifier;
+@property(nonatomic, strong) NSString *nonce;
+@property(nonatomic, strong) NSString *authorizationCode;
+@property(nonatomic, strong) NSArray *scopes;
+@property(nonatomic, strong) NSDictionary *serviceConfigurationParameters;
+@property(nonatomic, strong) NSDictionary *additionalParameters;
+@property(nonatomic, strong) NSNumber *externalUserAgent;
+
+@end
+
+@implementation TokenRequestParameters
+- (void)processArguments:(NSDictionary *)arguments {
+  _clientId = [ArgumentProcessor processArgumentValue:arguments
+                                              withKey:@"clientId"];
+  _clientSecret = [ArgumentProcessor processArgumentValue:arguments
+                                                  withKey:@"clientSecret"];
+  _issuer = [ArgumentProcessor processArgumentValue:arguments
+                                            withKey:@"issuer"];
+  _discoveryUrl = [ArgumentProcessor processArgumentValue:arguments
+                                                  withKey:@"discoveryUrl"];
+  _redirectUrl = [ArgumentProcessor processArgumentValue:arguments
+                                                 withKey:@"redirectUrl"];
+  _refreshToken = [ArgumentProcessor processArgumentValue:arguments
+                                                  withKey:@"refreshToken"];
+  _nonce = [ArgumentProcessor processArgumentValue:arguments withKey:@"nonce"];
+  _authorizationCode =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"authorizationCode"];
+  _codeVerifier = [ArgumentProcessor processArgumentValue:arguments
+                                                  withKey:@"codeVerifier"];
+  _grantType = [ArgumentProcessor processArgumentValue:arguments
+                                               withKey:@"grantType"];
+  _scopes = [ArgumentProcessor processArgumentValue:arguments
+                                            withKey:@"scopes"];
+  _serviceConfigurationParameters =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"serviceConfiguration"];
+  _additionalParameters =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"additionalParameters"];
+  _externalUserAgent =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"externalUserAgent"];
+}
+
+- (id)initWithArguments:(NSDictionary *)arguments {
+  [self processArguments:arguments];
+  return self;
+}
+
+@end
+
+@interface AuthorizationTokenRequestParameters : TokenRequestParameters
+@property(nonatomic, strong) NSString *loginHint;
+@property(nonatomic, strong) NSArray *promptValues;
+@property(nonatomic, strong) NSString *responseMode;
+@end
+
+@implementation AuthorizationTokenRequestParameters
+- (id)initWithArguments:(NSDictionary *)arguments {
+  [super processArguments:arguments];
+  _loginHint = [ArgumentProcessor processArgumentValue:arguments
+                                               withKey:@"loginHint"];
+  _promptValues = [ArgumentProcessor processArgumentValue:arguments
+                                                  withKey:@"promptValues"];
+  _responseMode = [ArgumentProcessor processArgumentValue:arguments
+                                                  withKey:@"responseMode"];
+  return self;
+}
+@end
+
+@implementation EndSessionRequestParameters
+- (id)initWithArguments:(NSDictionary *)arguments {
+  _idTokenHint = [ArgumentProcessor processArgumentValue:arguments
+                                                 withKey:@"idTokenHint"];
+  _postLogoutRedirectUrl =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"postLogoutRedirectUrl"];
+  _state = [ArgumentProcessor processArgumentValue:arguments withKey:@"state"];
+  _issuer = [ArgumentProcessor processArgumentValue:arguments
+                                            withKey:@"issuer"];
+  _discoveryUrl = [ArgumentProcessor processArgumentValue:arguments
+                                                  withKey:@"discoveryUrl"];
+  _serviceConfigurationParameters =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"serviceConfiguration"];
+  _additionalParameters =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"additionalParameters"];
+  _externalUserAgent =
+      [ArgumentProcessor processArgumentValue:arguments
+                                      withKey:@"externalUserAgent"];
+  return self;
+}
+@end
+
+@implementation FlutterAppauthPlugin
+
+FlutterMethodChannel *channel;
+AppAuthAuthorization *authorization;
+
++ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
+  channel = [FlutterMethodChannel
+      methodChannelWithName:@"crossingthestreams.io/flutter_appauth"
+            binaryMessenger:[registrar messenger]];
+  FlutterAppauthPlugin *instance = [[FlutterAppauthPlugin alloc] init];
+  [registrar addMethodCallDelegate:instance channel:channel];
+
+#if TARGET_OS_OSX
+  authorization = [[AppAuthMacOSAuthorization alloc] init];
+
+  NSAppleEventManager *appleEventManager =
+      [NSAppleEventManager sharedAppleEventManager];
+  [appleEventManager setEventHandler:instance
+                         andSelector:@selector(handleGetURLEvent:
+                                                  withReplyEvent:)
+                       forEventClass:kInternetEventClass
+                          andEventID:kAEGetURL];
+#else
+  authorization = [[AppAuthIOSAuthorization alloc] init];
+
+  [registrar addApplicationDelegate:instance];
+#endif
+}
+
+- (void)handleMethodCall:(FlutterMethodCall *)call
+                  result:(FlutterResult)result {
+  if ([AUTHORIZE_AND_EXCHANGE_CODE_METHOD isEqualToString:call.method]) {
+    [self handleAuthorizeMethodCall:[call arguments]
+                             result:result
+                       exchangeCode:true];
+  } else if ([AUTHORIZE_METHOD isEqualToString:call.method]) {
+    [self handleAuthorizeMethodCall:[call arguments]
+                             result:result
+                       exchangeCode:false];
+  } else if ([TOKEN_METHOD isEqualToString:call.method]) {
+    [self handleTokenMethodCall:[call arguments] result:result];
+  } else if ([END_SESSION_METHOD isEqualToString:call.method]) {
+    [self handleEndSessionMethodCall:[call arguments] result:result];
+  } else {
+    result(FlutterMethodNotImplemented);
+  }
+}
+
+- (void)ensureAdditionalParametersInitialized:
+    (AuthorizationTokenRequestParameters *)requestParameters {
+  if (!requestParameters.additionalParameters) {
+    requestParameters.additionalParameters = [[NSMutableDictionary alloc] init];
+  }
+}
+
+- (void)handleAuthorizeMethodCall:(NSDictionary *)arguments
+                           result:(FlutterResult)result
+                     exchangeCode:(BOOL)exchangeCode {
+  AuthorizationTokenRequestParameters *requestParameters =
+      [[AuthorizationTokenRequestParameters alloc] initWithArguments:arguments];
+  [self ensureAdditionalParametersInitialized:requestParameters];
+  if (requestParameters.loginHint) {
+    [requestParameters.additionalParameters setValue:requestParameters.loginHint
+                                              forKey:@"login_hint"];
+  }
+  if (requestParameters.promptValues) {
+    [requestParameters.additionalParameters
+        setValue:[requestParameters.promptValues componentsJoinedByString:@" "]
+          forKey:@"prompt"];
+  }
+  if (requestParameters.responseMode) {
+    [requestParameters.additionalParameters
+        setValue:requestParameters.responseMode
+          forKey:@"response_mode"];
+  }
+
+  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
+           externalUserAgent:requestParameters.externalUserAgent
+                      result:result
+                exchangeCode:exchangeCode
+                       nonce:requestParameters.nonce];
+  } else if (requestParameters.discoveryUrl) {
+    NSURL *discoveryUrl = [NSURL URLWithString:requestParameters.discoveryUrl];
+    [OIDAuthorizationService
+        discoverServiceConfigurationForDiscoveryURL:discoveryUrl
+                                         completion:^(
+                                             OIDServiceConfiguration
+                                                 *_Nullable configuration,
+                                             NSError *_Nullable error) {
+                                           if (!configuration) {
+                                             [self
+                                                 finishWithDiscoveryError:error
+                                                                   result:
+                                                                       result];
+                                             return;
+                                           }
+
+                                           self->_currentAuthorizationFlow = [authorization
+                                               performAuthorization:
+                                                   configuration
+                                                           clientId:
+                                                               requestParameters
+                                                                   .clientId
+                                                       clientSecret:
+                                                           requestParameters
+                                                               .clientSecret
+                                                             scopes:
+                                                                 requestParameters
+                                                                     .scopes
+                                                        redirectUrl:
+                                                            requestParameters
+                                                                .redirectUrl
+                                               additionalParameters:
+                                                   requestParameters
+                                                       .additionalParameters
+                                                  externalUserAgent:
+                                                      requestParameters
+                                                          .externalUserAgent
+                                                             result:result
+                                                       exchangeCode:exchangeCode
+                                                              nonce:
+                                                                  requestParameters
+                                                                      .nonce];
+                                         }];
+  } else {
+    NSURL *issuerUrl = [NSURL URLWithString:requestParameters.issuer];
+    [OIDAuthorizationService
+        discoverServiceConfigurationForIssuer:issuerUrl
+                                   completion:^(OIDServiceConfiguration
+                                                    *_Nullable configuration,
+                                                NSError *_Nullable error) {
+                                     if (!configuration) {
+                                       [self finishWithDiscoveryError:error
+                                                               result:result];
+                                       return;
+                                     }
+
+                                     self->_currentAuthorizationFlow =
+                                         [authorization
+                                             performAuthorization:configuration
+                                                         clientId:
+                                                             requestParameters
+                                                                 .clientId
+                                                     clientSecret:
+                                                         requestParameters
+                                                             .clientSecret
+                                                           scopes:
+                                                               requestParameters
+                                                                   .scopes
+                                                      redirectUrl:
+                                                          requestParameters
+                                                              .redirectUrl
+                                             additionalParameters:
+                                                 requestParameters
+                                                     .additionalParameters
+                                                externalUserAgent:
+                                                    requestParameters
+                                                        .externalUserAgent
+                                                           result:result
+                                                     exchangeCode:exchangeCode
+                                                            nonce:
+                                                                requestParameters
+                                                                    .nonce];
+                                   }];
+  }
+}
+
+- (void)finishWithDiscoveryError:(NSError *_Nullable)error
+                          result:(FlutterResult)result {
+  NSString *message = [NSString stringWithFormat:DISCOVERY_ERROR_MESSAGE_FORMAT,
+                                                 [error localizedDescription]];
+  [FlutterAppAuth finishWithError:DISCOVERY_ERROR_CODE
+                          message:message
+                           result:result
+                            error:error];
+}
+
+- (OIDServiceConfiguration *)processServiceConfigurationParameters:
+    (NSDictionary *)serviceConfigurationParameters {
+  NSURL *endSessionEndpoint =
+      serviceConfigurationParameters[@"endSessionEndpoint"] == [NSNull null]
+          ? nil
+          : [NSURL URLWithString:serviceConfigurationParameters
+                                     [@"endSessionEndpoint"]];
+  OIDServiceConfiguration *serviceConfiguration =
+      [[OIDServiceConfiguration alloc]
+          initWithAuthorizationEndpoint:
+              [NSURL URLWithString:serviceConfigurationParameters
+                                       [@"authorizationEndpoint"]]
+                          tokenEndpoint:
+                              [NSURL
+                                  URLWithString:serviceConfigurationParameters
+                                                    [@"tokenEndpoint"]]
+                                 issuer:nil
+                   registrationEndpoint:nil
+                     endSessionEndpoint:endSessionEndpoint];
+  return serviceConfiguration;
+}
+
+- (void)handleTokenMethodCall:(NSDictionary *)arguments
+                       result:(FlutterResult)result {
+  TokenRequestParameters *requestParameters =
+      [[TokenRequestParameters alloc] initWithArguments:arguments];
+  if (requestParameters.serviceConfigurationParameters != nil) {
+    OIDServiceConfiguration *serviceConfiguration =
+        [self processServiceConfigurationParameters:
+                  requestParameters.serviceConfigurationParameters];
+    [self performTokenRequest:serviceConfiguration
+            requestParameters:requestParameters
+                       result:result];
+  } else if (requestParameters.discoveryUrl) {
+    NSURL *discoveryUrl = [NSURL URLWithString:requestParameters.discoveryUrl];
+
+    [OIDAuthorizationService
+        discoverServiceConfigurationForDiscoveryURL:discoveryUrl
+                                         completion:^(
+                                             OIDServiceConfiguration
+                                                 *_Nullable configuration,
+                                             NSError *_Nullable error) {
+                                           if (!configuration) {
+                                             [self
+                                                 finishWithDiscoveryError:error
+                                                                   result:
+                                                                       result];
+                                             return;
+                                           }
+
+                                           [self
+                                               performTokenRequest:configuration
+                                                 requestParameters:
+                                                     requestParameters
+                                                            result:result];
+                                         }];
+  } else {
+    NSURL *issuerUrl = [NSURL URLWithString:requestParameters.issuer];
+    [OIDAuthorizationService
+        discoverServiceConfigurationForIssuer:issuerUrl
+                                   completion:^(OIDServiceConfiguration
+                                                    *_Nullable configuration,
+                                                NSError *_Nullable error) {
+                                     if (!configuration) {
+                                       [self finishWithDiscoveryError:error
+                                                               result:result];
+                                       return;
+                                     }
+
+                                     [self performTokenRequest:configuration
+                                             requestParameters:requestParameters
+                                                        result:result];
+                                   }];
+  }
+}
+
+- (void)handleEndSessionMethodCall:(NSDictionary *)arguments
+                            result:(FlutterResult)result {
+  EndSessionRequestParameters *requestParameters =
+      [[EndSessionRequestParameters alloc] initWithArguments:arguments];
+  if (requestParameters.serviceConfigurationParameters != nil) {
+    OIDServiceConfiguration *serviceConfiguration =
+        [self processServiceConfigurationParameters:
+                  requestParameters.serviceConfigurationParameters];
+    _currentAuthorizationFlow =
+        [authorization performEndSessionRequest:serviceConfiguration
+                              requestParameters:requestParameters
+                                         result:result];
+  } else if (requestParameters.discoveryUrl) {
+    NSURL *discoveryUrl = [NSURL URLWithString:requestParameters.discoveryUrl];
+
+    [OIDAuthorizationService
+        discoverServiceConfigurationForDiscoveryURL:discoveryUrl
+                                         completion:^(
+                                             OIDServiceConfiguration
+                                                 *_Nullable configuration,
+                                             NSError *_Nullable error) {
+                                           if (!configuration) {
+                                             [self
+                                                 finishWithDiscoveryError:error
+                                                                   result:
+                                                                       result];
+                                             return;
+                                           }
+
+                                           self->_currentAuthorizationFlow =
+                                               [authorization
+                                                   performEndSessionRequest:
+                                                       configuration
+                                                          requestParameters:
+                                                              requestParameters
+                                                                     result:
+                                                                         result];
+                                         }];
+  } else {
+    NSURL *issuerUrl = [NSURL URLWithString:requestParameters.issuer];
+    [OIDAuthorizationService
+        discoverServiceConfigurationForIssuer:issuerUrl
+                                   completion:^(OIDServiceConfiguration
+                                                    *_Nullable configuration,
+                                                NSError *_Nullable error) {
+                                     if (!configuration) {
+                                       [self finishWithDiscoveryError:error
+                                                               result:result];
+                                       return;
+                                     }
+
+                                     self->_currentAuthorizationFlow =
+                                         [authorization
+                                             performEndSessionRequest:
+                                                 configuration
+                                                    requestParameters:
+                                                        requestParameters
+                                                               result:result];
+                                   }];
+  }
+}
+
+- (void)performTokenRequest:(OIDServiceConfiguration *)serviceConfiguration
+          requestParameters:(TokenRequestParameters *)requestParameters
+                     result:(FlutterResult)result {
+  OIDTokenRequest *tokenRequest = [[OIDTokenRequest alloc]
+      initWithConfiguration:serviceConfiguration
+                  grantType:requestParameters.grantType
+          authorizationCode:requestParameters.authorizationCode
+                redirectURL:[NSURL URLWithString:requestParameters.redirectUrl]
+                   clientID:requestParameters.clientId
+               clientSecret:requestParameters.clientSecret
+                     scopes:requestParameters.scopes
+               refreshToken:requestParameters.refreshToken
+               codeVerifier:requestParameters.codeVerifier
+       additionalParameters:requestParameters.additionalParameters];
+  [OIDAuthorizationService
+      performTokenRequest:tokenRequest
+                 callback:^(OIDTokenResponse *_Nullable response,
+                            NSError *_Nullable error) {
+                   if (response) {
+                     result([FlutterAppAuth processResponses:response
+                                                authResponse:nil]);
+                   } else {
+                     NSString *message = [NSString
+                         stringWithFormat:TOKEN_ERROR_MESSAGE_FORMAT,
+                                          [error localizedDescription]];
+                     [FlutterAppAuth finishWithError:TOKEN_ERROR_CODE
+                                             message:message
+                                              result:result
+                                               error:error];
+                   }
+                 }];
+}
+
+#if TARGET_OS_IOS
+- (BOOL)application:(UIApplication *)application
+            openURL:(NSURL *)url
+            options:
+                (NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
+  if ([_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:url]) {
+    _currentAuthorizationFlow = nil;
+    return YES;
+  }
+
+  return NO;
+}
+
+- (BOOL)application:(UIApplication *)application
+              openURL:(NSURL *)url
+    sourceApplication:(NSString *)sourceApplication
+           annotation:(id)annotation {
+  return [self application:application openURL:url options:@{}];
+}
+#endif
+
+#if TARGET_OS_OSX
+- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event
+           withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
+  NSString *URLString =
+      [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
+  NSURL *URL = [NSURL URLWithString:URLString];
+  [_currentAuthorizationFlow resumeExternalUserAgentFlowWithURL:URL];
+  _currentAuthorizationFlow = nil;
+}
+#endif
+
+@end
diff --git a/flutter_appauth/macos/Classes/OIDExternalUserAgentMacNoSSO.h b/flutter_appauth/macos/Classes/OIDExternalUserAgentMacNoSSO.h
index 4a17eb47..22f1e1ba 100644
--- a/flutter_appauth/macos/Classes/OIDExternalUserAgentMacNoSSO.h
+++ b/flutter_appauth/macos/Classes/OIDExternalUserAgentMacNoSSO.h
@@ -1,7 +1,9 @@
 /*! @file OIDExternalUserAgentMacNoSSO.h
-    @brief  OIDExternalUserAgentMacNoSSO is custom user agent based on the default user agent in the AppAuth iOS SDK found here:
+    @brief  OIDExternalUserAgentMacNoSSO is custom user agent based on the
+   default user agent in the AppAuth iOS SDK found here:
             https://github.com/openid/AppAuth-iOS/blob/master/Source/AppAuth/macOS/OIDExternalUserAgentMac.h
-            Ths user agent allows setting `prefersEphemeralSession` flag on macOS 10.15 or newer to avoid cookies being shared across the device
+            Ths user agent allows setting `prefersEphemeralSession` flag on
+   macOS 10.15 or newer to avoid cookies being shared across the device
     @copydetails
         Licensed under the Apache License, Version 2.0 (the "License");
         you may not use this file except in compliance with the License.
@@ -16,22 +18,25 @@
         limitations under the License.
  */
 
-#import <AppKit/AppKit.h>
 #import <AppAuth/AppAuth.h>
+#import <AppKit/AppKit.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
-/*! @brief A Mac-specific external user-agent UI Coordinator that uses the default browser to
-        present an external user-agent request.
+/*! @brief A Mac-specific external user-agent UI Coordinator that uses the
+   default browser to present an external user-agent request.
  */
 @interface OIDExternalUserAgentMacNoSSO : NSObject <OIDExternalUserAgent>
 
 /*! @brief The designated initializer.
-    @param presentingWindow The window from which to present the ASWebAuthenticationSession.
+    @param presentingWindow The window from which to present the
+   ASWebAuthenticationSession.
  */
-- (instancetype)initWithPresentingWindow:(NSWindow *)presentingWindow NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithPresentingWindow:(NSWindow *)presentingWindow
+    NS_DESIGNATED_INITIALIZER;
 
-- (instancetype)init __deprecated_msg("Use initWithPresentingWindow for macOS 10.15 and above.");
+- (instancetype)init __deprecated_msg(
+    "Use initWithPresentingWindow for macOS 10.15 and above.");
 
 @end
 
diff --git a/flutter_appauth/macos/Classes/OIDExternalUserAgentMacNoSSO.m b/flutter_appauth/macos/Classes/OIDExternalUserAgentMacNoSSO.m
index 5a8a1cd6..9af763cb 100644
--- a/flutter_appauth/macos/Classes/OIDExternalUserAgentMacNoSSO.m
+++ b/flutter_appauth/macos/Classes/OIDExternalUserAgentMacNoSSO.m
@@ -1,7 +1,9 @@
 /*! @file OIDExternalUserAgentMacNoSSO.m
-    @brief  OIDExternalUserAgentMacNoSSO is custom user agent based on the default user agent in the AppAuth iOS SDK found here:
+    @brief  OIDExternalUserAgentMacNoSSO is custom user agent based on the
+   default user agent in the AppAuth iOS SDK found here:
             https://github.com/openid/AppAuth-iOS/blob/master/Source/AppAuth/macOS/OIDExternalUserAgentMac.m
-            Ths user agent allows setting `prefersEphemeralSession` flag on macOS 10.15 or newer to avoid cookies being shared across the device
+            Ths user agent allows setting `prefersEphemeralSession` flag on
+   macOS 10.15 or newer to avoid cookies being shared across the device
     @copydetails
         Licensed under the Apache License, Version 2.0 (the "License");
         you may not use this file except in compliance with the License.
@@ -16,16 +18,15 @@
         limitations under the License.
  */
 
-
 #import "OIDExternalUserAgentMacNoSSO.h"
 
-#import <Cocoa/Cocoa.h>
 #import <AuthenticationServices/AuthenticationServices.h>
-
+#import <Cocoa/Cocoa.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
-@interface OIDExternalUserAgentMacNoSSO ()<ASWebAuthenticationPresentationContextProviding>
+@interface OIDExternalUserAgentMacNoSSO () <
+    ASWebAuthenticationPresentationContextProviding>
 @end
 
 @implementation OIDExternalUserAgentMacNoSSO {
@@ -55,7 +56,8 @@ - (instancetype)init {
 }
 
 - (BOOL)presentExternalUserAgentRequest:(id<OIDExternalUserAgentRequest>)request
-                                session:(id<OIDExternalUserAgentSession>)session {
+                                session:
+                                    (id<OIDExternalUserAgentSession>)session {
   if (_externalUserAgentFlowInProgress) {
     // TODO: Handle errors as authorization is already in progress.
     return NO;
@@ -70,25 +72,28 @@ - (BOOL)presentExternalUserAgentRequest:(id<OIDExternalUserAgentRequest>)request
       __weak OIDExternalUserAgentMacNoSSO *weakSelf = self;
       NSString *redirectScheme = request.redirectScheme;
       ASWebAuthenticationSession *authenticationSession =
-        [[ASWebAuthenticationSession alloc] initWithURL:requestURL
-                                      callbackURLScheme:redirectScheme
-                                      completionHandler:^(NSURL * _Nullable callbackURL,
-                                                          NSError * _Nullable error) {
-        __strong OIDExternalUserAgentMacNoSSO *strongSelf = weakSelf;
-        if (!strongSelf) {
-            return;
-        }
-        strongSelf->_webAuthenticationSession = nil;
-        if (callbackURL) {
-          [strongSelf->_session resumeExternalUserAgentFlowWithURL:callbackURL];
-        } else {
-          NSError *safariError =
-              [OIDErrorUtilities errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
-                               underlyingError:error
-                                   description:nil];
-          [strongSelf->_session failExternalUserAgentFlowWithError:safariError];
-        }
-      }];
+          [[ASWebAuthenticationSession alloc]
+                    initWithURL:requestURL
+              callbackURLScheme:redirectScheme
+              completionHandler:^(NSURL *_Nullable callbackURL,
+                                  NSError *_Nullable error) {
+                __strong OIDExternalUserAgentMacNoSSO *strongSelf = weakSelf;
+                if (!strongSelf) {
+                  return;
+                }
+                strongSelf->_webAuthenticationSession = nil;
+                if (callbackURL) {
+                  [strongSelf->_session
+                      resumeExternalUserAgentFlowWithURL:callbackURL];
+                } else {
+                  NSError *safariError = [OIDErrorUtilities
+                        errorWithCode:OIDErrorCodeUserCanceledAuthorizationFlow
+                      underlyingError:error
+                          description:nil];
+                  [strongSelf->_session
+                      failExternalUserAgentFlowWithError:safariError];
+                }
+              }];
 
       authenticationSession.presentationContextProvider = self;
 
@@ -101,33 +106,38 @@ - (BOOL)presentExternalUserAgentRequest:(id<OIDExternalUserAgentRequest>)request
   BOOL openedBrowser = [[NSWorkspace sharedWorkspace] openURL:requestURL];
   if (!openedBrowser) {
     [self cleanUp];
-    NSError *safariError = [OIDErrorUtilities errorWithCode:OIDErrorCodeBrowserOpenError
-                                            underlyingError:nil
-                                                description:@"Unable to open the browser."];
+    NSError *safariError =
+        [OIDErrorUtilities errorWithCode:OIDErrorCodeBrowserOpenError
+                         underlyingError:nil
+                             description:@"Unable to open the browser."];
     [session failExternalUserAgentFlowWithError:safariError];
   }
   return openedBrowser;
 }
 
-- (void)dismissExternalUserAgentAnimated:(BOOL)animated completion:(void (^)(void))completion {
+- (void)dismissExternalUserAgentAnimated:(BOOL)animated
+                              completion:(void (^)(void))completion {
   if (!_externalUserAgentFlowInProgress) {
     // Ignore this call if there is no authorization flow in progress.
-    if (completion) completion();
+    if (completion)
+      completion();
     return;
   }
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wpartial-availability"
-  ASWebAuthenticationSession *webAuthenticationSession = _webAuthenticationSession;
+  ASWebAuthenticationSession *webAuthenticationSession =
+      _webAuthenticationSession;
 #pragma clang diagnostic pop
 
-  // Ideally the browser tab with the URL should be closed here, but the AppAuth library does not
-  // control the browser.
+  // Ideally the browser tab with the URL should be closed here, but the AppAuth
+  // library does not control the browser.
   [self cleanUp];
   if (webAuthenticationSession) {
     // dismiss the ASWebAuthenticationSession
     [webAuthenticationSession cancel];
-    if (completion) completion();
+    if (completion)
+      completion();
   } else if (completion) {
     completion();
   }
@@ -141,8 +151,8 @@ - (void)cleanUp {
 
 #pragma mark - ASWebAuthenticationPresentationContextProviding
 
-- (ASPresentationAnchor)presentationAnchorForWebAuthenticationSession:(ASWebAuthenticationSession *)session
-    API_AVAILABLE(macosx(10.15)) {
+- (ASPresentationAnchor)presentationAnchorForWebAuthenticationSession:
+    (ASWebAuthenticationSession *)session API_AVAILABLE(macosx(10.15)) {
   return _presentingWindow;
 }