diff --git a/client/app.php b/client/app.php
index 73920eeb95a445e43dc8dbe39d303ad161304cb8..0438716f84b3430d44ffae43386c7b9a0dc1cd34 100644
--- a/client/app.php
+++ b/client/app.php
@@ -8,17 +8,17 @@ use Firebase\JWT\JWT;
 require_once __DIR__ . '/vendor/autoload.php';
 
 // Simple app class with a couple of endpoints to simulate an OAuth2 client.
-// Run via `php -S localhost:8080 app.php` from this directory.
+// Run via `php -S localhost:8001 app.php` from this directory.
 // Create the OAuth2 Client from the Symfony console:
-// bin/console league:oauth2-server:create-client "Test Client" testclient testpass --scope=email --scope=profile --scope=blog_read --grant-type=refresh_token --grant_type=authorization_code --redirect-uri=http://localhost:8080/callback
+// bin/console league:oauth2-server:create-client "Test Client" testclient testpass --scope=email --scope=profile --scope=blog_read --grant-type=refresh_token --grant_type=authorization_code --redirect-uri=http://localhost:8001/callback
 class App
 {
     private $htmlTemplate = '';
 
     private $clientId = 'testclient';
     private $clientSecret = 'testpass';
-    private $redirectUri = 'http://localhost:8080/callback';
-    private $authServer = 'http://localhost:8000/consent';
+    private $redirectUri = 'http://localhost:8001/callback';
+    private $authServer = 'http://localhost:8000/authorize';
     private $tokenServer = 'http://localhost:8000/token';
     private $jwksUri = 'http://localhost:8000/.well-known/jwks.json';
     private $apiUri = 'http://localhost:8000/api/test';
@@ -81,7 +81,7 @@ class App
             'scope' => 'blog_read profile email',
         ];
         $url = $this->authServer . '?' . http_build_query($params);
-        header('Location: ' . $url);
+        header('Location: ' . $url); // Send a raw http header
     }
 
     private function indexAction()
diff --git a/config/routes.yaml b/config/routes.yaml
index c3283aa2e33bc813c55504d6c5a7a26653bd3dde..48133ea59e1f0adb208f30cae53aedb306595481 100644
--- a/config/routes.yaml
+++ b/config/routes.yaml
@@ -1,3 +1,6 @@
 #index:
 #    path: /
 #    controller: App\Controller\DefaultController::index
+oauth2:
+    resource: '@LeagueOAuth2ServerBundle/Resources/config/routes.php'
+    type: php
\ No newline at end of file
diff --git a/src/Command/BootstrapCommand.php b/src/Command/BootstrapCommand.php
index edd99afeed58ee4d771710494fb0b0d6fd1c8448..5a13fab6b0bf0334688a188e7e368bc9c36374a4 100644
--- a/src/Command/BootstrapCommand.php
+++ b/src/Command/BootstrapCommand.php
@@ -41,7 +41,7 @@ class BootstrapCommand extends Command
         $this
             ->addOption('email', null, InputOption::VALUE_REQUIRED, 'User email adddress', 'me@davegebler.com')
             ->addOption('password', null, InputOption::VALUE_REQUIRED, 'User password', 'password')
-            ->addOption('redirect-uris', null, InputOption::VALUE_REQUIRED, 'Redirect URIs', 'http://localhost:8080/callback')
+            ->addOption('redirect-uris', null, InputOption::VALUE_REQUIRED, 'Redirect URIs', 'http://localhost:8001/callback')
         ;
     }
 
diff --git a/src/Controller/IndexController.php b/src/Controller/IndexController.php
index 547ca1a255f1b430c1487736dd0d4a1ca3538702..a67e653f056a41965478873405325c2d49f241b3 100644
--- a/src/Controller/IndexController.php
+++ b/src/Controller/IndexController.php
@@ -12,7 +12,7 @@ class IndexController extends AbstractController
     /**
      * @Route("/", name="app_index")
      */
-    public function authorize(): Response
+    public function index(): Response
     {
         return $this->render('index/index.html.twig', [
             'controller_name' => 'IndexController',
diff --git a/src/Controller/LoginController.php b/src/Controller/LoginController.php
index a2e1aa6af80b381d77fa4db76915c9c2f4497495..85f2296d12b1d49db61fc1cb3753847d0fb23ca6 100644
--- a/src/Controller/LoginController.php
+++ b/src/Controller/LoginController.php
@@ -83,54 +83,58 @@ class LoginController extends AbstractController
                 return $consent->getClient() === $appClient;
             }
         )->first() ?: null;
-        $userScopes = $userConsents->getScopes() ?? [];
-    $hasExistingScopes = count($userScopes) > 0;
+        $userScopes = $userConsents ? $userConsents->getScopes() : [];
+        $hasExistingScopes = count($userScopes) > 0;
 
-    // If user has already consented to the scopes, give consent
-    if (count(array_diff($requestedScopes, $userScopes)) === 0) {
-        $request->getSession()->set('consent_granted', true);
-        return $this->redirectToRoute('oauth2_authorize', $request->query->all());
-    }
+        // If user has already consented to the scopes, give consent
+        if (count(array_diff($requestedScopes, $userScopes)) === 0) {
+            $request->getSession()->set('consent_granted', true);
+            return $this->redirectToRoute('oauth2_authorize', $request->query->all());
+        }
 
-    // Remove the scopes to which the user has already consented
-    $requestedScopes = array_diff($requestedScopes, $userScopes);
+        // Remove the scopes to which the user has already consented
+        $requestedScopes = array_diff($requestedScopes, $userScopes);
 
-    // Map the requested scopes to scope names
-    $scopeNames = [
-        'profile' => 'Your profile',
-        'email' => 'Your email address',
-        'blog_read' => 'Your blog posts (read)',
-        'blog_write' => 'Your blog posts (write)',
-    ];
+        // Map the requested scopes to scope names
+        $scopeNames = [
+            'profile' => 'Your profile',
+            'email' => 'Your email address',
+            'blog_read' => 'Your blog posts (read)',
+            'blog_write' => 'Your blog posts (write)',
+        ];
 
-    // Get all the scope names in the requested scopes.
-    $requestedScopeNames = array_map(function($scope) use ($scopeNames) { return $scopeNames[$scope]; }, $requestedScopes);
-    $existingScopes = array_map(function($scope) use ($scopeNames) { $scopeNames[$scope]; }, $userScopes);
+        // Get all the scope names in the requested scopes.
+        $requestedScopeNames = array_map(function ($scope) use ($scopeNames) {
+            return $scopeNames[$scope];
+        }, $requestedScopes);
+        $existingScopes = array_map(function ($scope) use ($scopeNames) {
+            $scopeNames[$scope];
+        }, $userScopes);
 
-    if ($request->isMethod('POST')) {
-        if ($request->request->get('consent') === 'yes') {
-            $request->getSession()->set('consent_granted', true);
-            // Add the requested scopes to the user's scopes
-            $consents = $userConsents ?? new OAuth2UserConsent();;
-            $consents->setScopes(array_merge($requestedScopes, $userScopes));
-            $consents->setClient($appClient);
-            $consents->setCreated(new \DateTimeImmutable());
-            $consents->setExpires(new \DateTimeImmutable('+30 days'));
-            $consents->setIpAddress($request->getClientIp());
-            $user->addOAuth2UserConsent($consents);
-            $this->em->getManager()->persist($consents);
-            $this->em->getManager()->flush();
-        }
-        if ($request->request->get('consent') === 'no') {
-            $request->getSession()->set('consent_granted', false);
+        if ($request->isMethod('POST')) {
+            if ($request->request->get('consent') === 'yes') {
+                $request->getSession()->set('consent_granted', true);
+                // Add the requested scopes to the user's scopes
+                $consents = $userConsents ?? new OAuth2UserConsent();;
+                $consents->setScopes(array_merge($requestedScopes, $userScopes));
+                $consents->setClient($appClient);
+                $consents->setCreated(new \DateTimeImmutable());
+                $consents->setExpires(new \DateTimeImmutable('+30 days'));
+                $consents->setIpAddress($request->getClientIp());
+                $user->addOAuth2UserConsent($consents);
+                $this->em->getManager()->persist($consents);
+                $this->em->getManager()->flush();
+            }
+            if ($request->request->get('consent') === 'no') {
+                $request->getSession()->set('consent_granted', false);
+            }
+            return $this->redirectToRoute('oauth2_authorize', $request->query->all());
         }
-        return $this->redirectToRoute('oauth2_authorize', $request->query->all());
+        return $this->render('login/consent.html.twig', [
+            'app_name' => $appName,
+            'scopes' => $requestedScopeNames,
+            'has_existing_scopes' => $hasExistingScopes,
+            'existing_scopes' => $existingScopes,
+        ]);
     }
-    return $this->render('login/consent.html.twig', [
-        'app_name' => $appName,
-        'scopes' => $requestedScopeNames,
-        'has_existing_scopes' => $hasExistingScopes,
-        'existing_scopes' => $existingScopes,
-    ]);
-}
 }
diff --git a/src/Entity/OAuth2UserConsent.php b/src/Entity/OAuth2UserConsent.php
index eed90f58207b4472b00a0ec8d2b87724d72a4148..9cb66d31df032f87e667d4278843244bbdff339e 100644
--- a/src/Entity/OAuth2UserConsent.php
+++ b/src/Entity/OAuth2UserConsent.php
@@ -30,6 +30,11 @@ class OAuth2UserConsent
      */
     private $client;
 
+    /**
+     * @ORM\Column(type="string", length=255, nullable=true)
+     */
+    private $ipAddress;
+
     /**
      * @ORM\Column(type="datetime")
      */
@@ -109,4 +114,16 @@ class OAuth2UserConsent
 
         return $this;
     }
+
+    public function getIpAddress(): ?string
+    {
+        return $this->ipAddress;
+    }
+
+    public function setIpAddress(?string $ipAddress): self
+    {
+        $this->ipAddress = $ipAddress;
+
+        return $this;
+    }
 }