Пример #1
0
 /**
  * To access private user data, you need his/her authorization. This endpoint is an HTML page that ask the current
  * logged user if (s)he wants to accept your application. If (s)he doesn't, (s)he is redirected to EtuUTT. I f(s)he
  * does, (s)he is redirected to your application URL with the parameter `code`.
  *
  * Let's take a small example:
  *
  * Your application "MyApp" (reidrect URL: http://myapp.com) wants to access private data of the current user.
  * To do so, you need to redirect user to this page:
  *
  * `/api/oauth/authorize?response_type=code&client_id=<your_client_id>&scope=public%20private_user_account&state=xyz`
  *
  * If the user accept the application, he will be redirected to `http://myapp.com/?code=<authorization_code>`.
  *
  * And using this code (in the parameter `code`), you are now able to get an `access_token` using `/api/oauth/token`.
  *
  *
  * If an error occured on the page and the client_id is provided, the user will be redirect to:
  * `http://myapp.com/?error=<error_type>&error_description=<error_description>` so you can handle the problem.
  *
  * @ApiDoc(
  *   section = "OAuth",
  *   description = "Display the authorization page for user to allow a given application",
  *   parameters = {
  *      {
  *          "name" = "client_id",
  *          "required" = true,
  *          "dataType" = "string",
  *          "description" = "Your client ID (given in your developper panel)"
  *      },
  *      {
  *          "name" = "scope",
  *          "required" = false,
  *          "dataType" = "string",
  *          "description" = "List of the scopes you need for the token, separated by spaces, for instance: `public private_user_account`. If not provided, grant only access to public scope."
  *      },
  *      {
  *          "name" = "response_type",
  *          "required" = true,
  *          "dataType" = "string",
  *          "description" = "Must be `code` (only authorization_code is supported for the moment)"
  *      },
  *      {
  *          "name" = "state",
  *          "required" = true,
  *          "dataType" = "string",
  *          "description" = "Must be `xyz` (only authorization_code is supported for the moment)"
  *      }
  *   }
  * )
  *
  * @Route("/authorize", name="oauth_authorize")
  * @Method({"GET", "POST"})
  * @Template()
  */
 public function authorizeAction(Request $request)
 {
     /*
      * Initialize OAuth
      */
     /** @var EntityManager $em */
     $em = $this->getDoctrine()->getManager();
     if (!$request->query->has('client_id')) {
         $this->get('session')->getFlashBag()->set('message', array('type' => 'error', 'message' => 'L\'application externe n\'a pas été trouvée. Vous avez été redirigé vers EtuUTT.'));
         return $this->redirect($this->generateUrl('homepage'));
     }
     // Find the client
     /** @var OauthClient $client */
     $client = $em->getRepository('EtuCoreApiBundle:OauthClient')->findOneBy(['clientId' => $request->query->get('client_id')]);
     if (!$client) {
         $this->get('session')->getFlashBag()->set('message', array('type' => 'error', 'message' => 'L\'application externe n\'a pas été trouvée. Vous avez été redirigé vers EtuUTT.'));
         return $this->redirect($this->generateUrl('homepage'));
     }
     // Not logged in
     if (!$this->getUserLayer()->isConnected()) {
         $this->get('session')->getFlashBag()->set('message', array('type' => 'error', 'message' => $this->get('translator')->trans('user.api_login.login', ['%name%' => $client->getName()])));
         $this->get('session')->set('etu.last_url', $request->getRequestUri());
         return $this->redirect($this->generateUrl('user_connect'));
     }
     // Logged in but as organization
     if ($this->getUserLayer()->isOrga()) {
         $this->get('session')->getFlashBag()->set('message', array('type' => 'error', 'message' => $this->get('translator')->trans('user.api_login.orga')));
         return $this->redirect($this->generateUrl('homepage'));
     }
     $requestedScopes = ['public'];
     if ($request->query->has('scopes')) {
         $requestedScopes = array_unique(array_merge($requestedScopes, explode(' ', $request->query->get('scopes'))));
     }
     // Search if user already approved the app
     $authorization = $em->getRepository('EtuCoreApiBundle:OauthAuthorization')->findOneBy(['client' => $client, 'user' => $this->getUser()]);
     if ($authorization) {
         $authorizationScopes = [];
         foreach ($authorization->getScopes() as $scope) {
             $authorizationScopes[] = $scope->getName();
         }
         // Compare scopes : if more requested, reask authorization, otherwise redirect
         $newScopes = array_diff($requestedScopes, $authorizationScopes);
         if (empty($newScopes)) {
             $authorizationCode = new OauthAuthorizationCode();
             $authorizationCode->setUser($this->getUser());
             $authorizationCode->setClient($client);
             $authorizationCode->generateCode();
             foreach ($authorization->getScopes() as $scope) {
                 $authorizationCode->addScope($scope);
             }
             $em->persist($authorizationCode);
             $em->flush();
             return $this->redirect($client->getRedirectUri() . '?authorization_code=' . $authorizationCode->getCode());
         }
     }
     // Scopes
     $qb = $em->createQueryBuilder();
     /** @var OauthScope[] $scopes */
     $scopes = $qb->select('s')->from('EtuCoreApiBundle:OauthScope', 's')->where($qb->expr()->in('s.name', $requestedScopes))->orderBy('s.weight', 'ASC')->getQuery()->getResult();
     // If the use didn't already approve the app, ask him / her
     $form = $this->createFormBuilder()->add('accept', 'submit', ['label' => 'Oui, accepter', 'attr' => ['class' => 'btn btn-primary', 'value' => '1']])->add('cancel', 'submit', ['label' => 'Non, annuler', 'attr' => ['class' => 'btn btn-default', 'value' => '0']])->getForm();
     if ($request->getMethod() == 'POST' && $form->submit($request)->isValid()) {
         $formData = $request->request->get('form');
         if (isset($formData['accept'])) {
             // Remove old authorizations
             $em->createQueryBuilder()->delete()->from('EtuCoreApiBundle:OauthAuthorization', 'a')->where('a.client = :client')->andWhere('a.user = :user')->setParameter('client', $client->getId())->setParameter('user', $this->getUser()->getId())->getQuery()->execute();
             $authorizationCode = new OauthAuthorizationCode();
             $authorizationCode->setUser($this->getUser());
             $authorizationCode->setClient($client);
             $authorizationCode->generateCode();
             /** @var OauthScope[] $defaultScopes */
             $defaultScopes = $em->getRepository('EtuCoreApiBundle:OauthScope')->findBy(['isDefault' => true]);
             foreach ($defaultScopes as $defaultScope) {
                 $authorizationCode->addScope($defaultScope);
             }
             foreach ($scopes as $scope) {
                 if (!$scope->getIsDefault()) {
                     $authorizationCode->addScope($scope);
                 }
             }
             $em->persist($authorizationCode);
             // Persist authorization to not ask anymore
             $em->persist(OauthAuthorization::createFromAuthorizationCode($authorizationCode));
             $em->flush();
             return $this->redirect($client->getRedirectUri() . '?authorization_code=' . $authorizationCode->getCode());
         } else {
             return $this->redirect($client->getRedirectUri() . '?error=authentification_canceled&error_message=L\'utilisateur a annulé l\'authentification.');
         }
     }
     return ['client' => $client, 'user' => $client->getUser(), 'scopes' => $scopes, 'form' => $form->createView()];
 }
Пример #2
0
 /**
  * @param OauthAuthorizationCode $code
  * @return OauthAuthorization
  */
 public static function createFromAuthorizationCode(OauthAuthorizationCode $code)
 {
     return new self($code->getClient(), $code->getUser(), $code->getScopes());
 }