Oauth2 — как связать access_token с реальным пользователем

Используя symfony2, fosuserbundle, fosoauthserverbundle и gtm-oauth2, после того, как вы получили токен авторизации, как механизм oauth связывает (или связывает) его с пользователем, который ввел свои учетные данные для входа/пароля?

Я не говорю о каком-то Google, Facebook, Twitter или Instagram API, но об одном, который я должен обслуживать на сайте, который я создал, используя symfony2.0.

Я отлично получаю токен доступа, и он у меня есть для всего, что я с ним делаю.

Итак, возникает вопрос. Что мне делать с этим как на стороне клиента, так и на стороне сервера, чтобы все это связывало токен с пользователем. Другими словами, когда у меня есть токен в приложении iOS, мне нужно получить доступ к URL-адресу, который будет отвечать на строку json с определенными элементами, принадлежащими пользователю. Но на данный момент я просто получаю HTML-код формы аутентификации, поскольку он интерпретирует, что пользователь еще не вошел в систему.

Я редактирую, чтобы указать различия между использованием приложения ios и браузера. Действительно по-другому, но я понятия не имею, как действовать или что делать.

Отладка при вызове из приложения iOS:

[2012-09-23 01:30:43] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelRequest". [] []
[2012-09-23 01:30:43] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\FrameworkBundle\EventListener\RouterListener::onEarlyKernelRequest". [] []
[2012-09-23 01:30:43] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\FrameworkBundle\EventListener\SessionListener::onKernelRequest". [] []
[2012-09-23 01:30:43] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\Security\Http\Firewall::onKernelRequest". [] []
[2012-09-23 01:30:43] security.INFO: Populated SecurityContext with an anonymous Token [] []
[2012-09-23 01:30:43] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\FrameworkBundle\EventListener\RouterListener::onKernelRequest". [] []
[2012-09-23 01:30:43] request.INFO: Matched route "_get_carts_api" (parameters: "_controller": "Acme\StoreBundle\Controller\APIController::getCartsApiAction", "_route": "_get_carts_api") [] []
[2012-09-23 01:30:43] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\AsseticBundle\EventListener\RequestListener::onKernelRequest". [] []
[2012-09-23 01:30:44] event.DEBUG: Notified event "kernel.controller" to listener "Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector::onKernelController". [] []
[2012-09-23 01:30:44] event.DEBUG: Notified event "kernel.controller" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\ControllerListener::onKernelController". [] []
[2012-09-23 01:30:44] event.DEBUG: Notified event "kernel.controller" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\ParamConverterListener::onKernelController". [] []
[2012-09-23 01:30:44] event.DEBUG: Notified event "kernel.controller" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener::onKernelController". [] []
[2012-09-23 01:30:44] event.DEBUG: Notified event "kernel.controller" to listener "JMS\SecurityExtraBundle\Controller\ControllerListener::onCoreController". [] []
[2012-09-23 01:30:44] app.INFO: anon. [] [

Отладка при использовании Интернета из браузера:

[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelRequest". [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\FrameworkBundle\EventListener\RouterListener::onEarlyKernelRequest". [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\FrameworkBundle\EventListener\SessionListener::onKernelRequest". [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Component\Security\Http\Firewall::onKernelRequest". [] []
[2012-09-23 01:28:07] security.DEBUG: Read SecurityContext from the session [] []
[2012-09-23 01:28:07] security.DEBUG: Reloading user from user provider. [] []
[2012-09-23 01:28:07] doctrine.DEBUG: SET NAMES UTF8 ([]) [] []
[2012-09-23 01:28:07] doctrine.DEBUG: SELECT t0.username AS username1, t0.username_canonical AS username_canonical2, t0.email AS email3, t0.email_canonical AS email_canonical4, t0.enabled AS enabled5, t0.salt AS salt6, t0.password AS password7, t0.last_login AS last_login8, t0.locked AS locked9, t0.expired AS expired10, t0.expires_at AS expires_at11, t0.confirmation_token AS confirmation_token12, t0.password_requested_at AS password_requested_at13, t0.roles AS roles14, t0.credentials_expired AS credentials_expired15, t0.credentials_expire_at AS credentials_expire_at16, t0.id AS id17, t0.name AS name18, t0.address AS address19, t0.nif AS nif20, t0.phone AS phone21, t0.account_number AS account_number22, t0.zip AS zip23, t0.town AS town24, t0.province AS province25, t0.birth_date AS birth_date26, t0.myTestsHelpActive AS myTestsHelpActive27, t0.myPackagesHelpActive AS myPackagesHelpActive28, t0.historyHelpActive AS historyHelpActive29, t0.shopHelpActive AS shopHelpActive30, t0.sellerPackageHelpActive AS sellerPackageHelpActive31, t0.testHours AS testHours32, t0.testMinutes AS testMinutes33, t0.wrongSubstract AS wrongSubstract34, t0.archivedPackages AS archivedPackages35 FROM usuario t0 WHERE t0.username_canonical = ? (["[email protected]"]) [] []
[2012-09-23 01:28:07] security.DEBUG: Username "[email protected]" was reloaded from user provider. [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\FrameworkBundle\EventListener\RouterListener::onKernelRequest". [] []
[2012-09-23 01:28:07] request.INFO: Matched route "_get_carts" (parameters: "_controller": "Acme\StoreBundle\Controller\ShopController::getCartsAction", "_route": "_get_carts") [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.request" to listener "Symfony\Bundle\AsseticBundle\EventListener\RequestListener::onKernelRequest". [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.controller" to listener "Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector::onKernelController". [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.controller" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\ControllerListener::onKernelController". [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.controller" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\ParamConverterListener::onKernelController". [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.controller" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener::onKernelController". [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.controller" to listener "JMS\SecurityExtraBundle\Controller\ControllerListener::onCoreController". [] []
[2012-09-23 01:28:07] doctrine.DEBUG: SELECT t0.id AS id1, t0.name AS name2, t0.create_date AS create_date3, t0.update_date AS update_date4, t0.user_id AS user_id5 FROM Cart t0 WHERE t0.user_id = ? ([100]) [] []
[2012-09-23 01:28:07] doctrine.DEBUG: SELECT t0.id AS id1, t0.name AS name2, t0.description AS description3, t0.prize AS prize4, t0.update_time AS update_time5, t0.update_comment AS update_comment6, t0.active AS active7, t0.user_id AS user_id8, t0.block_id AS block_id9 FROM package t0 INNER JOIN packages_carts ON t0.id = packages_carts.package_id WHERE packages_carts.cart_id = ? ([11]) [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\Security\Http\Firewall\ContextListener::onKernelResponse". [] []
[2012-09-23 01:28:07] security.DEBUG: Write SecurityContext in the session [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\HttpKernel\EventListener\ResponseListener::onKernelResponse". [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Bundle\SecurityBundle\EventListener\ResponseListener::onKernelResponse". [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Bridge\Monolog\Handler\FirePHPHandler::onKernelResponse". [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.response" to listener "Sensio\Bundle\FrameworkExtraBundle\EventListener\CacheListener::onKernelResponse". [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelResponse". [] []
[2012-09-23 01:28:07] event.DEBUG: Notified event "kernel.response" to listener "Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener::onKernelResponse". [] []]

Отредактировано: это то, что пишут в журналах отладки и Authorize, и Token Requests:

[2012-09-23 13:53:12] request.INFO: Matched route "fos_oauth_server_authorize" (parameters: "_controller": "FOS\OAuthServerBundle\Controller\AuthorizeController::authorizeAction", "_route": "fos_oauth_server_authorize"). Request: GET /~pgbonino/Symfony/web/app_dev.php/oauth/v2/auth?client_id=1_2854cesqrsu8oosk8k40sw0ck4kccgooowc4s80gk4gssc4g00&redirect_uri=http%3A%2F%2F127.0.0.1%2F~pgbonino%2FSymfony%2Fweb%2Fapp_dev.php%2Foauth%2Fv2%2FfalseCallBack&response_type=code HTTP/1.1
Accept:          text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Connection:      keep-alive
Cookie:          PHPSESSID=o6fmhfinrfv7ueht3hmgt91jf6
Host:            127.0.0.1
Origin:          http://127.0.0.1
Referer:         http://127.0.0.1/~pgbonino/Symfony/web/app_dev.php/main/
User-Agent:      Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10A403
X-Php-Ob-Level:  1

[2012-09-23 13:53:13] request.INFO: Matched route "fos_oauth_server_token" (parameters: "_controller": "fos_oauth_server.controller.token:tokenAction", "_route": "fos_oauth_server_token"). Request: POST /~pgbonino/Symfony/web/app_dev.php/oauth/v2/token HTTP/1.1
Accept:          */*
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Connection:      keep-alive
Content-Length:  312
Content-Type:    application/x-www-form-urlencoded
Host:            127.0.0.1
User-Agent:      gtm-oauth2 Gallello.PruebasAPI/1.0
X-Php-Ob-Level:  1

client_id=1_2854cesqrsu8oosk8k40sw0ck4kccgooowc4s80gk4gssc4g00&client_secret=sr93lkss5hc48kg0csw4ksk0goccsc4g00448gc8s0k4s4csk&code=UnNDaUkdl6YAkr53uwctnuZLpota6X-jSBq4gqB1XfE&grant_type=authorization_code&redirect_uri=http%3A%2F%2F127.0.0.1%2F~pgbonino%2FSymfony%2Fweb%2Fapp_dev.php%2Foauth%2Fv2%2FfalseCallBack

[2012-09-23 14:02:47] request.INFO: Matched route "_get_carts_api" (parameters: "_controller": "Acme\StoreBundle\Controller\APIController::getCartsApiAction", "_route": "_get_carts_api"). Request: GET /~pgbonino/Symfony/web/app_dev.php/api/getCarts HTTP/1.1
Accept:          */*
Accept-Encoding: gzip, deflate
Accept-Language: en-us
Connection:      keep-alive
Cookie:          PHPSESSID=6apagmbmr4b7dddf3r44ecgp30
Host:            127.0.0.1
User-Agent:      PruebasAPI/1.0 CFNetwork/609 Darwin/12.2.0
X-Php-Ob-Level:  1

И затем XCode, где я все это сделал:

Во-первых, сначала объявите и подготовьте объект, с которым будет выполняться запрос:

- (GTMOAuth2Authentication * ) authForPreparaTest
{
//This URL is defined by the individual 3rd party APIs, be sure to read their documentation
NSString * url_string = @"http://127.0.0.1/~pgbonino/Symfony/web/app_dev.php/oauth/v2/token";
NSURL * tokenURL = [NSURL URLWithString:url_string];
// We'll make up an arbitrary redirectURI.  The controller will watch for
// the server to redirect the web view to this URI, but this URI will not be
// loaded, so it need not be for any actual web page.
NSString * redirectURI = @"http://127.0.0.1/~pgbonino/Symfony/web/app_dev.php/oauth/v2/falseCallBack";
GTMOAuth2Authentication * myAuth;
myAuth = [GTMOAuth2Authentication authenticationWithServiceProvider:@"PreparaTest"
                                                         tokenURL:tokenURL
                                                      redirectURI:redirectURI
                                                         clientID:kMyClientID
                                                     clientSecret:kMyClientSecret
        ];
[myAuth setTokenType:@"Bearer"];
return myAuth;
}

Во-вторых, нажмите веб-просмотр с помощью моего веб-приложения, запрашивающего у пользователя его учетные данные:

- (void)signInToPreparaTest
{
GTMOAuth2Authentication *myAuth = [self authForPreparaTest];
NSString* auth_string = @"http://127.0.0.1/~pgbonino/Symfony/web/app_dev.php/oauth/v2/auth";
NSURL * authURL = [NSURL URLWithString:auth_string];
// Display the authentication view


GTMOAuth2ViewControllerTouch * viewController;
viewController = [[GTMOAuth2ViewControllerTouch alloc] initWithAuthentication:myAuth
                                                             authorizationURL:authURL
                                                             keychainItemName:nil
                                                                     delegate:self
                                                             finishedSelector:@selector(viewController:finishedWithAuth:error:)];
[viewController setBrowserCookiesURL:[NSURL URLWithString:@"http://127.0.0.1/~pgbonino/Symfony/web/app_dev.php/"]];
[self.navigationController pushViewController:viewController animated:YES];
}

В-третьих, все идет отлично, поэтому обновите объект self.auth с помощью access_token:

- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController
  finishedWithAuth:(GTMOAuth2Authentication *)myAuth
             error:(NSError *)error
{
if (error != nil)
{
    // Authentication failed
    UIAlertView *alertView = [ [UIAlertView alloc] initWithTitle:@"Authorization Failed"
                                                         message:[error localizedDescription]
                                                        delegate:self
                                               cancelButtonTitle:@"Dismiss"
                                               otherButtonTitles:nil];
    [alertView show];
}
else
{
    // Authentication succeeded

    // Assign the access token to the instance property for later use
    self.accessToken = myAuth.accessToken;
    [myAuth setShouldAuthorizeAllRequests:YES];
    [self setAuth:myAuth];

    // Display the access token to the user
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Authorization Succeeded"
                                                         message:[NSString stringWithFormat:@"Access Token: %@", auth.accessToken]
                                                        delegate:self
                                               cancelButtonTitle:@"Dismiss"
                                               otherButtonTitles:nil];
    [alertView show];
}
}

Четвертый и последний (проблемный момент), после аутентификации я иду к своему API (мне нужны все сохраненные тележки для зарегистрированного пользователя):

- (IBAction)getCartsPressed:(id)sender{

NSMutableURLRequest *request = [NSMutableURLRequest new];

NSString * url_string = @"http://127.0.0.1/~pgbonino/Symfony/web/app_dev.php/api/getCarts";
NSURL *getCartsURL = [NSURL URLWithString:url_string];

[request setURL:getCartsURL];

[self.auth authorizeRequest:request
          completionHandler:^(NSError *error) {
              NSString *output = nil;
              if (error) {
                  output = [error description];
              } else {
                  // Synchronous fetches like this are a really bad idea in Cocoa applications
                  //
                  // For a very easy async alternative, we could use GTMHTTPFetcher
                  NSURLResponse *response = nil;
                  NSData *data = [NSURLConnection sendSynchronousRequest:request
                                                       returningResponse:&response
                                                                   error:&error];
                  if (data) {
                      // API fetch succeeded
                      output = [[NSString alloc] initWithData:data
                                                      encoding:NSUTF8StringEncoding];
                  } else {
                      // fetch failed
                      output = [error description];
                  }
              }
          }];
}

заранее спасибо


person ElPiter    schedule 22.09.2012    source источник
comment
$container->get('security.context')->getToken()->getUser(); возвращает пользователя?   -  person AdrienBrault    schedule 23.09.2012
comment
Нет, это не так. Проблема тут же, но только при вызове контроллера API. Остальная часть веб-приложения хорошо работает в браузере, создавая сеанс с учетными данными пользователя традиционным способом, а строка кода, которую вы упомянули, правильно передает пользовательские данные. Из приложения iOS я явно создаю сеанс, получаю токен доступа (я проверяю его в базе данных и делаю это отлично), но когда я снова звоню, как указано в документации GTM-oauth2, $container->get('security.context ')->getToken()->getUser() возвращает неинициализированное значение. :'(   -  person ElPiter    schedule 23.09.2012
comment
Я отредактировал, чтобы вставить следы при вызове из приложения iOS и из веб-браузера. Я надеюсь, вы можете взглянуть   -  person ElPiter    schedule 23.09.2012
comment
Как вы думаете, может ли это иметь какое-либо отношение к тому, как GTM-oauth2 запрашивает URL-адрес? Я предполагаю, что FOSOAuthServerBundle не ожидает токен, так как он отправлен сюда --› // у нас есть вероятный действительный токен доступа NSString *value = [NSString stringWithFormat:@%s %@, GTM_OAUTH2_BEARER, accessToken]; [запрос setValue:значение дляHTTPHeaderField:@Authorization]; }   -  person ElPiter    schedule 23.09.2012
comment
security.INFO: Populated SecurityContext with an anonymous Token Вот в чем проблема. Какую конечную точку с какими параметрами вы используете для получения токена доступа?   -  person AdrienBrault    schedule 23.09.2012
comment
Еще раз спасибо. Я только что написал в конце оригинального поста, что оба запроса Authorize и Token записывают в журналы отладки. Как я уже говорил, обратите внимание, что все это генерируется GTM-oauth2. Там у вас также есть журналы для запроса, который я пытаюсь выполнить после получения токена (я имею в виду... когда я обращаюсь к API)   -  person ElPiter    schedule 23.09.2012
comment
И теперь я разместил в конце исходного вопроса код Objective-C, который пытается (и почти получает) все это. Я знаю, что это долго... но все это имеет смысл. Еще раз спасибо за помощь.   -  person ElPiter    schedule 23.09.2012
comment
Еще одна подсказка: я думаю, что проблема не в том, как я получаю access_token (который, как я уже сказал, я получаю правильно и сохраняю его в БД), а в последнем запросе, где я пытаюсь вызвать свой API для получения всех сохраненных корзин ранее (и предположительно) аутентифицированного пользователя. Если вы видите эту часть трассировки, вы проверите, как выполняется запрос */api/getCarts без параметров. Вам не кажется, что GTM-oauth2 отсутствует, чтобы каким-то образом отправить токен? Я могу попробовать сделать это вручную, какое точное имя параметров ожидается в FOSOAuthServerBundle, куда должен идти токен?   -  person ElPiter    schedule 23.09.2012
comment
Хм... видимо сработало!! Позвольте мне проверить еще немного, но кажется, что установка токена вручную в заголовке http сработала. Я проверю это еще немного и опубликую ответ, если это действительно решение. Спасибо еще раз.   -  person ElPiter    schedule 23.09.2012