setStatusCode(302);
      $response->headers->set('Location', '/dashboard');
    } else {
      $response->setContent(view('login', [
        'title' => 'Sign In to Telegraph',
        'return_to' => $request->get('return_to')
      ]));
    }
    return $response;
  }
  public function logout(Request $request, Response $response) {
    session_start();
    if(session('user_id')) {
      $_SESSION['user_id'] = null;
      session_destroy();
    }
    $response->setStatusCode(302);
    $response->headers->set('Location', '/login');
    return $response;
  }
  public function login_start(Request $request, Response $response) {
    if(!$request->get('url') || !($me = IndieAuth\Client::normalizeMeURL($request->get('url')))) {
      $response->setContent(view('login', [
        'title' => 'Sign In to Telegraph',
        'error' => 'Invalid URL',
        'error_description' => 'The URL you entered, "' . htmlspecialchars($request->get('url')) . '" is not valid.'
      ]));
      return $response;
    }
    $state = JWT::encode([
      'me' => $me,
      'return_to' => $request->get('return_to'),
      'time' => time(),
      'exp' => time()+300 // verified by the JWT library
    ], Config::$secretKey);
    $authorizationURL = IndieAuth\Client::buildAuthorizationURL(Config::$defaultAuthorizationEndpoint, $me, self::_buildRedirectURI(), Config::$clientID, $state);
    $response->setStatusCode(302);
    $response->headers->set('Location', $authorizationURL);
    return $response;
  }
  public function login_callback(Request $request, Response $response) {
    if(!$request->get('state') || !$request->get('code')) {
      $response->setContent(view('login', [
        'title' => 'Sign In to Telegraph',
        'error' => 'Missing Parameters',
        'error_description' => 'The auth server did not return the necessary parameters, state and code.'
      ]));
      return $response;
    }
    // Validate the "state" parameter to ensure this request originated at this client
    try {
      $state = JWT::decode($request->get('state'), Config::$secretKey, ['HS256']);
      if(!$state) {
        $response->setContent(view('login', [
          'title' => 'Sign In to Telegraph',
          'error' => 'Invalid State',
          'error_description' => 'The state parameter was not valid.'
        ]));
        return $response;
      }
    } catch(Exception $e) {
      $response->setContent(view('login', [
        'title' => 'Sign In to Telegraph',
        'error' => 'Invalid State',
        'error_description' => 'The state parameter was invalid:
'.htmlspecialchars($e->getMessage())
      ]));
      return $response;
    }
    $authorizationEndpoint = Config::$defaultAuthorizationEndpoint;
    // Verify the code with the auth server
    $token = IndieAuth\Client::verifyIndieAuthCode($authorizationEndpoint, $request->get('code'), $state->me, self::_buildRedirectURI(), Config::$clientID, true);
    if(!array_key_exists('auth', $token) || !array_key_exists('me', $token['auth'])) {
      // The auth server didn't return a "me" URL
      $response->setContent(view('login', [
        'title' => 'Sign In to Telegraph',
        'error' => 'Invalid Auth Server Response',
        'error_description' => 'The authorization server ('.$authorizationEndpoint.') did not return a valid response:
HTTP '.$token['response_code']."\n\n".htmlspecialchars($token['response']).'' ])); return $response; } // Create or load the user $user = ORM::for_table('users')->where('url', $token['auth']['me'])->find_one(); if(!$user) { $user = ORM::for_table('users')->create(); $user->url = $token['auth']['me']; $user->created_at = date('Y-m-d H:i:s'); $user->last_login = date('Y-m-d H:i:s'); $user->save(); // Create a site for them with the default role $site = ORM::for_table('sites')->create(); $site->name = 'My Website'; $site->url = $token['auth']['me']; $site->created_by = $user->id; $site->created_at = date('Y-m-d H:i:s'); $site->save(); $role = ORM::for_table('roles')->create(); $role->site_id = $site->id; $role->user_id = $user->id; $role->role = 'owner'; $role->token = random_string(32); $role->save(); } else { $user->last_login = date('Y-m-d H:i:s'); $user->save(); } q()->queue('Telegraph\ProfileFetcher', 'fetch', [$user->id]); session_start(); $_SESSION['user_id'] = $user->id; $response->setStatusCode(302); $response->headers->set('Location', ($state->return_to ?: '/dashboard')); return $response; } private static function _buildRedirectURI() { return Config::$base . 'login/callback'; } }