diff --git a/lib/src/app.dart b/lib/src/app.dart
index fbedba3885efb6cbc2ee9f5fc4b948572a12ff32..8253d14fc51e29f06d77c177df9e264c0bc951a9 100644
--- a/lib/src/app.dart
+++ b/lib/src/app.dart
@@ -1,4 +1,6 @@
 // app.dart
+import '../config.dart';
+import 'error-alert.dart';
 import 'screens/splashscreen.dart';
 import 'package:flutter/material.dart';
 import 'screens/home.dart';
@@ -6,6 +8,11 @@ import 'package:flutter/services.dart';
 import 'dart:async';
 import 'dart:developer';
 import 'package:shared_preferences/shared_preferences.dart';
+import 'package:flutter_web_browser/flutter_web_browser.dart';
+import 'dart:convert';
+import 'package:url_launcher/url_launcher.dart';
+import 'package:flutter_app_auth_wrapper/flutter_app_auth_wrapper.dart';
+import 'dart:io';
 
 import 'package:uni_links/uni_links.dart';
 
@@ -52,8 +59,6 @@ class App extends StatelessWidget {
           navigateAfterFuture: initApplication,
         )
     );
-
-
   }
 }
 
@@ -76,9 +81,59 @@ class _MainAppState extends State<MainApp> {
   // Url of the app which invoked OAuth
   String _invokerURL;
 
+  String _host = Config.appFlavor == Flavor.DEVELOPMENT ? Config.HOSTS[0] : Config.DEFAULT_APP_HOST;
+
+  Screen _currentScreen = Screen.App;
+
   @override
   initState() {
     super.initState();
+
+    // Set up app host
+    if (widget.initialHost != null) {
+      setState(() {
+        _host = widget.initialHost;
+      });
+    }
+
+    // Subscribe to authorization events
+    FlutterAppAuthWrapper.eventStream().listen((data) async {
+      var token = json.decode(data.toString())["access_token"];
+      setScreen(Screen.App);
+
+      log("Open $_invokerURL");
+      try {
+        await launch("$_invokerURL?token=$token&host=$_host");
+      } catch (e) {
+        log("Error launching url $_invokerURL");
+      }
+
+    }, onError: (error) {
+      log("Err $error");
+
+      String errorMessage = error.message;
+      String errorDetails  = error.details;
+
+      if (
+        // Handle cancellation for Android
+        errorDetails == '{"type":0,"code":1,"errorDescription":"User cancelled flow"}' ||
+        // Handle cancellation for iOS
+        errorMessage.toLowerCase().contains("the operation couldn")
+      ) {
+        if (Platform.isAndroid) {
+          // Show only for android, because iOS will show the same alert as
+          // was for Auth request
+          openVereign();
+        } else {
+          setScreen(Screen.App);
+        }
+      } else {
+        showErrorAlert(context, Platform.isAndroid ? errorDetails : errorMessage, openVereign);
+        setScreen(Screen.App);
+      }
+    });
+
+
     initUniLinks();
   }
 
@@ -89,37 +144,87 @@ class _MainAppState extends State<MainApp> {
   }
 
   Future<Null> initUniLinks() async {
-    updateAppMode(widget.initialUri);
+    handleLinkChange(widget.initialUri);
 
     _sub = getUriLinksStream().listen((Uri uri) {
-      updateAppMode(uri);
+      handleLinkChange(uri);
     }, onError: (err) {
       log('got err: $err');
     });
   }
 
-  updateAppMode(Uri uri) {
+  handleLinkChange(Uri uri) {
     if (uri?.path == "/authorize") {
       setState(() {
         _appMode = AppMode.Authorization;
         _invokerURL = uri.queryParameters["invokerUrl"];
-
       });
+
+      startOAuth();
     } else {
       setState(() {
         _appMode = AppMode.Default;
       });
+
+      openVereign();
     }
   }
 
+  setScreen(Screen screen) {
+    setState(() {
+      _currentScreen = screen;
+    });
+  }
+
+  openVereign() {
+    setScreen(Screen.Dashboard);
+
+    FlutterWebBrowser.openWebPage(url: _host, androidToolbarColor: Color(0xFFd51d32));
+  }
+
+  startOAuth() {
+    if (_currentScreen == Screen.OAuth) {
+      return;
+    }
+
+    setScreen(Screen.OAuth);
+
+    var params = Config.getOAuthParams(host: _host);
+
+    FlutterAppAuthWrapper.startAuth(
+      AuthConfig(
+        clientId: params["clientId"],
+        clientSecret: params["clientSecret"],
+        redirectUrl: params["redirectUrl"],
+        state: "login",
+        prompt: "consent",
+        endpoint: AuthEndpoint(
+            auth: params["authEndpoint"], token: params["tokenEndpoint"]),
+        scopes: [
+          "user_account_status",
+          "user_territory",
+          "user_profile"
+        ],
+      ),
+    );
+  }
+
+  setHost(String host) {
+    setState(() {
+      _host = host;
+    });
+  }
+
   @override
   Widget build(BuildContext context) {
     return new Scaffold(
       appBar: new AppBar(title: Text("Vereign")),
       body: Home(
         mode: _appMode,
-        invokerURL: _invokerURL,
-        host: widget.initialHost
+        host: _host,
+        setHost: setHost,
+        openDashboardClick: openVereign,
+        authorizeClick: startOAuth,
       )
     );
   }
diff --git a/lib/src/error-alert.dart b/lib/src/error-alert.dart
new file mode 100644
index 0000000000000000000000000000000000000000..a3fd300440bb05e7f45e2219fc518cf05668bb17
--- /dev/null
+++ b/lib/src/error-alert.dart
@@ -0,0 +1,22 @@
+import 'package:flutter/material.dart';
+
+Future<void> showErrorAlert(context, errorString, callback) {
+  return showDialog<void>(
+    context: context,
+    builder: (BuildContext context) {
+      return AlertDialog(
+        title: Text('Authorization error'),
+        content: Text(errorString),
+        actions: <Widget>[
+          FlatButton(
+            child: Text('Open Dashboard'),
+            onPressed: () async {
+              Navigator.of(context).pop();
+              callback();
+            },
+          ),
+        ],
+      );
+    },
+  );
+}
\ No newline at end of file
diff --git a/lib/src/screens/home.dart b/lib/src/screens/home.dart
index 4f3de27332b692f034901bd73ca48b5230a4e94f..6c4f085ac052cbe0c0f2aed44e953332e43af0db 100644
--- a/lib/src/screens/home.dart
+++ b/lib/src/screens/home.dart
@@ -1,9 +1,4 @@
 import 'package:flutter/material.dart';
-import 'package:flutter_web_browser/flutter_web_browser.dart';
-import 'package:flutter_app_auth_wrapper/flutter_app_auth_wrapper.dart';
-import 'package:url_launcher/url_launcher.dart';
-import 'dart:developer';
-import 'dart:convert';
 import 'dart:async';
 import 'package:shared_preferences/shared_preferences.dart';
 
@@ -13,46 +8,29 @@ import '../app.dart';
 class Home extends StatefulWidget {
   Home({
     @required this.mode,
-    @required this.invokerURL,
     @required this.host,
+    @required this.setHost,
+    @required this.authorizeClick,
+    @required this.openDashboardClick,
   });
 
   final AppMode mode;
-  final String invokerURL;
   final String host;
+  final void Function(String) setHost;
+  final void Function() openDashboardClick;
+  final void Function() authorizeClick;
 
   @override
   _HomeState createState() => _HomeState();
 }
 
 class _HomeState extends State<Home> {
-  String _host = Config.appFlavor == Flavor.DEVELOPMENT ? Config.HOSTS[0] : Config.DEFAULT_APP_HOST;
   bool _hidden = true;
 
-  Screen _currentScreen = Screen.App;
-
   @override
   initState() {
     super.initState();
 
-    // Set up initial host
-    if (widget.host != null) {
-      setState(() {
-        _host = widget.host;
-      });
-    }
-
-    setScreenByMode(widget.mode);
-
-    FlutterAppAuthWrapper.eventStream().listen((data) {
-      var token = json.decode(data.toString())["access_token"];
-      _showAlert(token);
-      setScreen(Screen.App);
-    }, onError: (error) {
-      log("Err $error");
-      setScreen(Screen.App);
-    });
-
     Timer(
         Duration(seconds: 3),
         () {
@@ -63,105 +41,6 @@ class _HomeState extends State<Home> {
     );
   }
 
-  setScreen(Screen screen) {
-    if (
-      _currentScreen == screen &&
-      screen != Screen.Dashboard // ATM we can not determine whether dashboard was closed or not, so we avoid this case
-    ) {
-      return;
-    }
-
-    setState(() {
-      _currentScreen = screen;
-    });
-
-    if (_currentScreen == Screen.Dashboard) {
-      openVereign();
-    } else if (_currentScreen == Screen.OAuth) {
-      startOAuth();
-    }
-  }
-
-  Future<void> _showAlert(token) {
-    return showDialog<void>(
-      context: context,
-      builder: (BuildContext context) {
-        return AlertDialog(
-          title: Text('Authorization success'),
-          actions: <Widget>[
-            FlatButton(
-              child: Text('Go back'),
-              onPressed: () async {
-                Navigator.of(context).pop();
-
-                log("Open ${widget.invokerURL}");
-                try {
-                  await launch("${widget.invokerURL}?token=$token&host=$_host");
-                } catch (e) {
-                  log("Error launching url ${widget.invokerURL}");
-                }
-              },
-            ),
-          ],
-        );
-      },
-    );
-  }
-
-  @override
-  void didUpdateWidget(Home oldWidget) {
-    // this method IS called when parent widget passes new "props"
-    // unlike React, this method IS called _before_ the build
-    // unlike React, this method ISN'T called after setState()
-
-    if (widget.host != oldWidget.host && widget.host != null) {
-      setState(() {
-        _host = widget.host;
-      });
-    }
-
-    if (widget.mode != oldWidget.mode) {
-      setScreenByMode(widget.mode);
-    }
-
-    super.didUpdateWidget(oldWidget);
-  }
-
-  setScreenByMode(AppMode mode) {
-    if (mode == AppMode.Authorization) {
-      setScreen(Screen.OAuth);
-    } else if (mode == AppMode.Default) {
-      setScreen(Screen.Dashboard);
-    }
-  }
-
-  openVereign() {
-    FlutterWebBrowser.openWebPage(url: _host, androidToolbarColor: Color(0xFFd51d32));
-  }
-
-  startOAuth() {
-    var params = Config.getOAuthParams(host: _host);
-
-    FlutterAppAuthWrapper.startAuth(
-      AuthConfig(
-        clientId: params["clientId"],
-        clientSecret: params["clientSecret"],
-        redirectUrl: params["redirectUrl"],
-        state: "login",
-        prompt: "consent",
-        endpoint: AuthEndpoint(
-            auth: params["authEndpoint"], token: params["tokenEndpoint"]),
-        scopes: [
-          "user_account_status",
-          "user_territory",
-          "user_profile"
-        ],
-      ),
-    );
-  }
-
-
-
   @override
   Widget build(BuildContext context) {
     if (_hidden) {
@@ -169,23 +48,20 @@ class _HomeState extends State<Home> {
     }
 
     var children = <Widget>[
-      _urlButton(context, "Open Dashboard", () => setScreen(Screen.Dashboard)),
+      _urlButton(context, "Open Dashboard", widget.openDashboardClick),
     ];
 
     if (widget.mode == AppMode.Authorization) {
-      children.add(_urlButton(context, "Authorize with Vereign", () => setScreen(Screen.OAuth)));
+      children.add(_urlButton(context, "Authorize with Vereign", widget.authorizeClick));
     }
 
     if (Config.appFlavor == Flavor.DEVELOPMENT) {
       children.add(
         wrapInContainer(
           DropdownButton<String>(
-            value: _host,
+            value: widget.host,
             onChanged: (String newValue) async {
-              setState(() {
-                _host = newValue;
-              });
-
+              widget.setHost(newValue);
               final prefs = await SharedPreferences.getInstance();
               prefs.setString("host", newValue);
             },