public function callback(HTTPRequest $request)
    {
        $session = $request->getSession();

        if (!$this->validateState($request)) {
            $session->clear('oauth2');
            $this->httpError(400, 'Invalid session state.');
            return null;
        }

        $providerName = $session->get('oauth2.provider');
        /** @var ProviderFactory $providerFactory */
        $providerFactory = Injector::inst()->get(ProviderFactory::class);
        $provider = $providerFactory->getProvider($providerName);
        $returnUrl = $this->getReturnUrl();

        try {
            $accessToken = $provider->getAccessToken('authorization_code', [
                'code' => $request->getVar('code')
            ]);

            $handlers = $this->getHandlersForContext($session->get('oauth2.context'));

            // Run handlers to process the token
            $results = [];
            foreach ($handlers as $handlerConfig) {
                $handler = Injector::inst()->create($handlerConfig['class']);
                $results[] = $handler->handleToken($accessToken, $provider);
            }

            // Handlers may return response objects
            foreach ($results as $result) {
                if ($result instanceof HTTPResponse) {
                    $session->clear('oauth2');

                    // If the response is redirecting to the login page (e.g. on Security::permissionFailure()),
                    // update the BackURL so it doesn't point to /oauth/callback/
                    if ($result->isRedirect()) {
                        $location = $result->getHeader('location');
                        $relativeLocation = Director::makeRelative($location);

                        // If the URL begins Security/login and a BackURL parameter is set...
                        if (
                            strpos($relativeLocation, Security::config()->uninherited('login_url')) === 0
                            && strpos($relativeLocation, 'BackURL') !== -1
                        ) {
                            $session->set('BackURL', $returnUrl);
                            $location = HTTP::setGetVar('BackURL', $returnUrl, $location);
                            $result->addHeader('location', $location);
                        }
                    }
                    
                    return $result;
                }
            }
        } catch (IdentityProviderException $e) {
            /** @var LoggerInterface $logger */
            $logger = Injector::inst()->get(LoggerInterface::class . '.oauth');
            $logger->error('OAuth IdentityProviderException: ' . $e->getMessage());
            $this->httpError(400, 'Invalid access token.');
            return null;
        } catch (Exception $e) {
            /** @var LoggerInterface $logger */
            $logger = Injector::inst()->get(LoggerInterface::class . '.oauth');
            $logger->error('OAuth Exception: ' . $e->getMessage());
            $this->httpError(400, $e->getMessage());
            return null;
        } finally {
            $session->clear('oauth2');
        }

        return $this->redirect($returnUrl);
    }