Perte de session sur WebService Rails depuis iOS 7

muqaddarmuqaddar Administrateur
septembre 2013 modifié dans API UIKit #1

Salut,


 


Quelques utilisateurs m'ont signalé un problème de connexion au serveur depuis qu'ils ont mis à  jour leur iPhone ou iPad en iOS 7. L'application est encore compilée pour iOS 6 en plus...


 


Pour ma part, tout baigne, je n'ai pas réussi à  reproduire le problème.


 


Je suis absolument sûr que le problème est lié au nouvel OS.


 


Je suis allé voir les logs du serveur Rails (3.0.20). Au départ, je pensais à  un problème serveur mais l'origine du problème semble bien être iOS 7.


Donc en analysant les logs du serveur, j'ai découvert que la session serveur n'était pas toujours conservée, pour certains utilisateurs.


Je suis allé plus loin, et en faisant des tests avec un utilisateur, sur 4 heures d'intervalle, il y a eu 10 échecs puis 1 réussite à  la fin, suivie d'autres réussites. C'est très dur à  débuguer car je n'arrive pas à  reproduire le problème.


 


Voilà  ce qu'il se passe en gros:


 


Sous iOS 6, la session est bien conservée sur le serveur, à  coup sûr:


 


 




Started POST "/users/login" for 91.45.167.111 at Fri Sep 27 13:47:34 +0000 2013

  Processing by UsersController#login as JSON

  Parameters: {"password"=>"[FILTERED]", "username"=>"Horst", "bundle"=>"VinoCellar"}

USER_AGENT vinocellar/2.1.1 (ipad; ios 6.1.3; scale/1.00)

Completed 200 OK in 137ms (Views: 0.3ms | ActiveRecord: 26.2ms)

 

Started GET "/services/pull" for 91.45.167.111 at Fri Sep 27 13:47:35 +0000 2013

  Processing by Vinocloud::ServicesController#pull as JSON

  Parameters: {"locale"=>"ws"}

USER_AGENT vinocellar/2.1.1 (ipad; ios 6.1.3; scale/1.00)

SESSION user_id 5454 la session est bien là  !

Completed 200 OK in 8262ms (Views: 1256.6ms | ActiveRecord: 6438.8ms)



 


Sous iOS 7, la session est perdue (pas toujours, je le répète):


 


 



Started POST "/users/login" for 91.45.139.190 at Sat Sep 28 13:09:08 +0000 2013

  Processing by UsersController#login as JSON

  Parameters: {"password"=>"[FILTERED]", "username"=>"Horst", "bundle"=>"VinoCellar"}

USER_AGENT: vinocellar/2.1.1 (iphone; ios 7.0.2; scale/2.00)

Completed 200 OK in 133ms (Views: 0.3ms | ActiveRecord: 12.4ms)

 

Started GET "/services/pull" for 91.45.139.190 at Sat Sep 28 13:09:09 +0000 2013

  Processing by ServicesController#pull as JSON

  Parameters: {"locale"=>"ws"}

USER_AGENT: vinocellar/2.1.1 (iphone; ios 7.0.2; scale/2.00)

SESSION Le user_id dans la session est perdu ici !!! Donc redirection vers le login.


Completed 302 Found in 1ms

 



 




 


Là , où je perds la boule, c'est que ça marche pour certains utilisateurs même sous iOS 7 !


 


 




Started POST "/users/login" for 93.133.25.65 at Thu Sep 26 19:32:09 +0000 2013

  Processing by UsersController#login as JSON

  Parameters: {"password"=>"[FILTERED]", "username"=>"Hut", "bundle"=>"VinoCellar"}

USER_AGENT vinocellar/2.1.1 (iphone; ios 7.0; scale/2.00)

Completed 200 OK in 125ms (Views: 0.3ms | ActiveRecord: 6.0ms)

 

Started GET "/services/pull" for 93.133.25.65 at Thu Sep 26 19:32:12 +0000 2013

  Processing by ServicesController#pull as JSON

  Parameters: {"locale"=>"ws"}

USER_AGENT vinocellar/2.1.1 (iphone; ios 7.0; scale/2.00)

SESSION user_id 1675 la session est bien conservée !!

Completed 200 OK in 6292ms (Views: 1129.8ms | ActiveRecord: 5390.4ms)

 



 



Par contre, jamais de problème de session sous iOS 6.1.3...


J'utilise AFNetworking pour envoyer les requêtes JSON.


 


Savez-vous si Apple changé quelque chose au niveau des requêtes sur iOS 7 ? OU autre ?


Quelque chose qui ne plairait pas à  la mémorisation de la session sur mon serveur Rails ?


«1

Réponses

  • Salut,


     




    Savez-vous si Apple changé quelque chose au niveau des requêtes sur iOS 7 ? OU autre ?




    Oui ils ont introduit NSURLSession qui remplace NSURLConnection ( mais qui n'est pas deprecated pour l'instant).


    Moi je créerai une autre branche et je migrerai sur AFNewtworking 2.0 ( qui se base sur NSURLSession sous iOS 7 et garde la comptabilité pour iOS 6.. avec l'utilisation de NSURLConnection) et je testerai avec ça.


  • AliGatorAliGator Membre, Modérateur
    Ouais enfin NSURLSession est une nouvelle façon de faire, qui permet de nouvelles possibilités (en particulier si je ne m'abuse faire les requêtes en arrière plan en avance de phase quand l'OS propose à  l'appli de faire du prefetch de données), mais NSURLConnection a encore de beaux jours devant lui et peut encore être largement utilisé.
  • muqaddarmuqaddar Administrateur

    Dans tous les cas (NSURLSession ou NSURLConnection), ça n'explique pas pourquoi la session n'est pas conservée sur le serveur.


    Vous allez me dire que c'est un problème lié au serveur mais alors pourquoi jamais ce problème sous iOS 6 ou même iOS 5 ?


     


    Encore un test ou j'ai ajouté des logs:


     




    Started POST "/users/login" for 91.45.143.225 at Sun Sep 29 13:50:04 +0000 2013

      Processing by UsersController#login as JSON

      Parameters: {"username"=>"Horst", "password"=>"[FILTERED]", "bundle"=>"VinoCellar", "locale"=>"ws"}

    USER_AGENT

    vinocellar/2.1.1 (iphone; ios 7.0.2; scale/2.00)

    USER_AUTHENTICATED

    SESSION CREATED

    5454

    Completed 200 OK in 132ms (Views: 0.3ms | ActiveRecord: 13.2ms)

     

    Started GET "/services/pull" for 91.45.143.225 at Sun Sep 29 13:50:05 +0000 2013

      Processing by ServicesController#pull as JSON

      Parameters: {"locale"=>"ws"}

    USER_AGENT

    vinocellar/2.1.1 (iphone; ios 7.0.2; scale/2.00)

    SESSION

     


    Completed 302 Found in 1ms

     



     



    On voit clairement que une seconde après, la session est vide.


  • muqaddarmuqaddar Administrateur
    septembre 2013 modifié #5

    Bon, alors je continue mon enquête.


     


    Avec les logs et les heures, je suis allé fouiller ma table de sessions.


     


    Il s'avère que les sessions qui sont vides lors de la deuxième requête ont l'air tronquées en base.


     


    Le contenu d'une session normale ressemble à  ça:


     




    BAh7ByIMdXNlcl9pZGkCZiwiEF9jc3JmX3Rva2VuIjFPKzdReDd3bHpWcjl6

    SGRNNW1NMk4wNjZOYTJEU0R6MmlxdGxDMWRXM25BPQ==

     



     



    Le contenu d'une session qui "échoue" ressemble à  ça:

     


    BAh7BjoMdXNlcl9pZGkCThU== 

     


    On dirait qu'il manque plein d'infos... (même si dans ce cas, l'utilisateur est bien identifié, cf logs plus hauts)


     


    Pourtant, elles sont toutes créées de la même manière évidemment.

  • AliGatorAliGator Membre, Modérateur
    Et si tu dé-base64 le contenu de ta session pour voir ce qu'il y a vraiment dedans ça te donne + d'infos ?


    Sinon tu es sûr (surtout vu le côté aléatoire de la chose) que ce n'est pas une fausse analyse que de mettre ça sur iOS7 ?

    Peut-être que le problème était là  avant mais vient d'un autre fait, et le fait qu'il surgisse au moment où tout le monde passe à  iOS7 est peut-être un hasard ? (Genre tu as plus d'utilisateurs qui se connectent en même temps car tu viens de mettre à  jour ton appli donc ça l'a remise au goût du jour et leur a rappelé qu'elle existe, mais ça n'a rien à  voir avec leur passage à  iOS7?)


    Je veux dire fais gaffe à  pas partir sur une mauvaise piste en supposant une cause qui n'est peut-être pas la bonne quoi ;)
  • muqaddarmuqaddar Administrateur


    Et si tu dé-base64 le contenu de ta session pour voir ce qu'il y a vraiment dedans ça te donne + d'infos ?




     


     


    Bein je vais aller essayer de faire ça... (jamais fait).


     




    Je veux dire fais gaffe à  pas partir sur une mauvaise piste en supposant une cause qui n'est peut-être pas la bonne quoi ;)




     


    C'est sûr que c'est p-e une mauvaise piste.


    Pourtant, je viens d'analyser 80 Mo de logs et je n'ai pas vu le problème sur iOS 6...

  • muqaddarmuqaddar Administrateur
    septembre 2013 modifié #8

    Oh ça va vite, y'a même des sites pour ça (pour décoder) !


    Je savais même pas.


     


    Le _csrf_token n'est pas créé quand il y a problème.


    Reste à  savoir pourquoi.


     


    Mais le user_id est bien en session.


     


    En même temps, la requête pull qui suit est GET et ne doit pas utiliser le _csrf_token...


     


    EDIT: je suis allé voir une autre Rails app que j'ai et toutes mes sessions sont parfaites dans ma table session.


  • AliGatorAliGator Membre, Modérateur
    Vitesse de réseau différent (ou iPhones anciens qui une fois passés sous iOS7 sont plus lents ?) qui fait que tes requêtes qui partent dans un certain ordre ne reçoivent pas leur réponse dans le même ordre maintenant que le device est + lent ?
    (C'est des idées en vrac, je sais pas du tout si c'est lié je capte pas trop ton histoire de csrf_token machin)
  • muqaddarmuqaddar Administrateur

    Non, je ne pense pas.


    Il n'y a qu'une requête pour la création d'une session: /login


     


    Dès que le user est logué, il crée la session. Cette dernière semble être erratique. Il manque des infos dans les sessions qui posent problème. Le _csrf_token est très important en Rails pour la vérification des requêtes, il vérifie que les tokens envoyés sont les bons... sauf que là , il n'y a rien à  vérifier puisqu'il n'a pas été créé en session apparemment.


  • Peux être que tu utilise le même login sur plusieurs devices ( tu te connecte avec le même login alors que ya déjas une session ouverte comme c'est déjas connecté ) et que ton API serveur gère mal  ça ? 


  • Problème d'encoding des strings ? Normalement ton base64 est composé de quoi ?


  • muqaddarmuqaddar Administrateur


    Peux être que tu utilise le même login sur plusieurs devices ( tu te connecte avec le même login alors que ya déjas une session ouverte comme c'est déjas connecté ) et que ton API serveur gère mal  ça ? 




     


    Non, aucun problème avec ça, je peux le faire moi-même.

  • muqaddarmuqaddar Administrateur


    Problème d'encoding des strings ? Normalement ton base64 est composé de quoi ?




     


    Je sais pas.


    Je sais que Rails génère les token comme ça:


     


    session[:_csrf_token] ||= SecureRandom.base64(32)

  • muqaddarmuqaddar Administrateur
    septembre 2013 modifié #15

    Bon, je viens de regarder tous les logs de la nuit.


     


    1) Tous les problèmes sont sous iOS 7.


    2) Sur iOS 7, ça concerne 1 utilisateur sur 10.


     


    ça va pas être évident à  résoudre !


  • FKDEVFKDEV Membre
    septembre 2013 modifié #16

    1 sur 10, cela veut dire que cela peut-être une combinaison entre l'os et le contenu des données transmises (ou de la spécificité connexion (IPV6 ?)).


     


    En ce qui concerne les données, utilises-tu les nouvelles API pour encoder en Base64 sur iOS 7 ?


    Il faut savoir qu'il y a plusieurs variantes d'encodage en Base64 qui ne portent que sur quelques caractères (/, :, .).


    Il se pourrait que ton appli Rail n'arrive pas à  décoder tout le message quand les données (login, mdp) contiennent ces caractères.


     


    En ce qui concerne des paramètres de connexions, les sessions incluent parfois l'IP pour améliorer la sécurité mais je ne sais pas si iOS 7 peut avoir changé quelque chose à  ce sujet.


     


     


    Après il y a la méthode systématique :


    Si on écarte un problème de timing ou d'ordre de requête.


    Le problème ne peut venir que du contenu de la requête HTTP ou des informations sur la connexion (adresse IP, autre?) qui passe du serveur à  l'appli.


    Tu n'as qu'à  dumper le contenu complet de ta requête (headers+body) au départ de iOS, à  l'arrivée sur le serveur et à  l'arrivée dans l'appli Rail.


    Si tu peux faire ça pour un même jeu de donnée au départ de l'appli (Login+mdp+ip, etc) en ios6 et 7, tu trouveras forcément la différence.


  • LeChatNoirLeChatNoir Membre, Modérateur

    pb uniquement sur 5s car proc 64 bits ?


  • muqaddarmuqaddar Administrateur


    1 sur 10, cela veut dire que cela peut-être une combinaison entre l'os et le contenu des données transmises (ou de la spécificité connexion (IPV6 ?)).




     


    Les erreurs sont sur IPV4.


     




    En ce qui concerne les données, utilises-tu les nouvelles API pour encoder en Base64 sur iOS 7 ?

     


     


    Non. L'appli est encore iOS 6 SDK même si elle tourne sur iOS 7...


     



    Il faut savoir qu'il y a plusieurs variantes d'encodage en Base64 qui ne portent que sur quelques caractères (/, :, .).


    Il se pourrait que ton appli Rail n'arrive pas à  décoder tout le message quand les données (login, mdp) contiennent ces caractères.



     


    On parlait de Base64 car Rails encode le token en Base64.


     


    En ce qui concerne des paramètres de connexions, les sessions incluent parfois l'IP pour améliorer la sécurité mais je ne sais pas si iOS 7 peut avoir changé quelque chose à  ce sujet.

     



     


    Il n'y a pas l'IP dans les sessions Rails (par défaut). Mais je pourrais les rajouter, ça ne servirait à  rien.


     



    Après il y a la méthode systématique :


    Si on écarte un problème de timing ou d'ordre de requête.



     


    Je confirme, car les 2 requêtes sont bien à  la suite.


     



    Le problème ne peut venir que du contenu de la requête HTTP ou des informations sur la connexion (adresse IP, autre?) qui passe du serveur à  l'appli.


    Tu n'as qu'à  dumper le contenu complet de ta requête (headers+body) au départ de iOS, à  l'arrivée sur le serveur et à  l'arrivée dans l'appli Rail.


    Si tu peux faire ça pour un même jeu de donnée au départ de l'appli (Login+mdp+ip, etc) en ios6 et 7, tu trouveras forcément la différence.




     


    Oui, c'est une piste.


     


    Ce matin, j'ai forcé la durée de la session Rails à  30 minutes.


    Et ajouté d'autres logs.


     


    J'attends les tests de mes utilisateurs.



  •  



    On parlait de Base64 car Rails encode le token en Base64.


     





     


    Ok. Mais n'encodes-tu pas le login et mot de passe ? (De toutes façons si tu restes sur les même méthodes de calculs ça ne peut pas être ça).


     


    Il y a eu des problèmes avec le réglage des cookies (par exemple : https://discussions.apple.com/message/23067423#23067423), mais tu sembles dire que le problème se produit lors du stockage de la session côté serveur...

  • muqaddarmuqaddar Administrateur


    Il y a eu des problèmes avec le réglage des cookies (par exemple : https://discussions.apple.com/message/23067423#23067423), mais tu sembles dire que le problème se produit lors du stockage de la session côté serveur...




     


    Oui, un utilisateur vient de me dire que l'activation des cookies dans safari changerait la donne !


     


    Pourtant, je n'utilise pas les cookies mais uniquement les sessions stockées en base...


    Je continue mon enquête...

  • FKDEVFKDEV Membre
    septembre 2013 modifié #21

    bah en général tu as quand même au moins le numéro de session stocké sous forme de cookie, sinon ça passe dans l'URL mais tu le saurais dans ce cas-là .


  • muqaddarmuqaddar Administrateur
    septembre 2013 modifié #22

    Je confirme.


    Je n'arrive plus à  synchroniser si mes cookies sont désactivés.


     


    Quel rapport avec iOS 7, ils ont changé les réglages par défaut ?


     


    J'espère que la seule solution n'est pas de faire passer le session_id dans l'URL ?


    Sinon, je vais avoir l'impression de faire un site sous PHP 3 en l'an 2000...


  • AliGatorAliGator Membre, Modérateur

    Pourtant, je n'utilise pas les cookies mais uniquement les sessions stockées en base...

    Heu aux dernières nouvelles, les sessionIDs (genre phpsessionid ou jsessionid etc), ça fait une éternité qu'ils utilisent les cookies et les headers pour être passés de page en page, non ? (Et si pas de cookies, via l'URL). Donc si, tu les utilises (sans le savoir, sans doute, mais même).
    Après c'est sensé être transparent...
  • muqaddarmuqaddar Administrateur
    septembre 2013 modifié #24


    Heu aux dernières nouvelles, les sessionIDs (genre phpsessionid ou jsessionid etc), ça fait une éternité qu'ils utilisent les cookies et les headers pour être passés de page en page, non ? (Et si pas de cookies, via l'URL). Donc si, tu les utilises (sans le savoir, sans doute, mais même).

    Après c'est sensé être transparent...




     


    Tout à  fait.


    Je suis entièrement d'accord.


     


    Par contre, j'ai poussé les tests.


    J'ai désactivé les cookies sous iOS 6.1.3... et bang, ça marche quand-même !


    Le problème n'est donc QUE quand les cookies sont désactivés sous iOS 7, mais pas sous iOS 6.


  • AliGatorAliGator Membre, Modérateur
    As-tu pensé à  regarder les CHANGELOG de iOS7 ?

    Ils ont peut-être corrigé un bug sous iOS7 qui faisait qu'avant sous iOS6 certains cookies passaient même quand l'option était désactivée, alors que maintenant c'est corrigé et du coup ça passe plus ?
  • <troll>


    Si tu travaillais en mode stateless, avec un WS qui authentifie en DIGEST ça ne serait pas arrivé tout ça ^^


     


    REST FTW !


    </troll>


  • muqaddarmuqaddar Administrateur


    As-tu pensé à  regarder les CHANGELOG de iOS7 ?




     


    Impossible de mettre la main sur le vrai changelog de iOS 7 (en tout cas, je le vois pas sur l'ADC)

  • C'est le moment de dumper tes headers HTTP pour confirmer le problème des cookies mais c'est surement ça.


     


    Ton test sur iOS6 ne prouve sans doute pas grand chose car la gestion des cookies semblent assez complexe et il semble qu'il faut réinstaller l'app pour être sur des paramètres qu'elle utilise.


     


    Voir ce post qui semble faire un tour assez complet de l'état actuel : http://www.inmite.eu/en/blog/20130928-cookies-on-ios7-can-not-login.


     


    La solution : 


     


    The solution is pretty simple. You have to apply your own policy. Just put following piece of code to your application's star­tup and force policy to pre-iOS7 default value:


    [[NSHTTPCooki­eStorage sharedHTTPCoo­kieStorage] setCookieAccep­tPolicy:NSHTTPCo­okieAcceptPoli­cyAlways] 


  • AliGatorAliGator Membre, Modérateur
    septembre 2013 modifié #29

    Impossible de mettre la main sur le vrai changelog de iOS 7 (en tout cas, je le vois pas sur l'ADC)

    Tu veux dire ça et ça ?
  • muqaddarmuqaddar Administrateur
    septembre 2013 modifié #30


    C'est le moment de dumper tes headers HTTP pour confirmer le problème des cookies mais c'est surement ça.


     


    Ton test sur iOS6 ne prouve sans doute pas grand chose car la gestion des cookies semblent assez complexe et il semble qu'il faut réinstaller l'app pour être sur des paramètres qu'elle utilise.


     


    Voir ce post qui semble faire un tour assez complet de l'état actuel : http://www.inmite.eu/en/blog/20130928-cookies-on-ios7-can-not-login.


     


    La solution : 


     


    The solution is pretty simple. You have to apply your own policy. Just put following piece of code to your application's star­tup and force policy to pre-iOS7 default value:


    [[NSHTTPCooki­eStorage sharedHTTPCoo­kieStorage] setCookieAccep­tPolicy:NSHTTPCo­okieAcceptPoli­cyAlways] 




     


     


    Et au même moment, Céroce m'a envoyé ce lien:


    https://devforums.apple.com/message/898034#898034


     


    Je teste ça et je reviens vers vous.


  • muqaddarmuqaddar Administrateur
    septembre 2013 modifié #31


    Tu veux dire ça et ça ?




     


    Oui, ça je l'avais trouvé. Je cherchais un vrai changelog plus complet et plus technique, et pas un "what's new".


Connectez-vous ou Inscrivez-vous pour répondre.