Sur la route d'Oxiane digressions diverses

LeBlog OXiane

29 sept
2014

DroidCon 2014 – Death to passwords

Encore une conférence à laquelle nous avons assisté à OXiane lors de ce droidcon 2014.
L’enjeu ici : parler de sa stratégie d’authentification au sein d’une application mobile. Pas de notion précise de sécurité applicative mais surtout un talk autour de trois notions :

  • Approche de sécurité développeur / utilisateur
  • Expérience utilisateur (UX le mot à la mode depuis 2 ans)
  • Différences entre authentification et autorisations

Sécurité

Tout d’abord, quelques réflexions générales de sécurité : 91% des gens ont un des 1000 mots de passe les plus répandus.
Ce qui ouvre pas mal de possibilités aux hackers, avec en tête les derniers piratages de masses de comptes consultables sur le site https://haveibeenpwned.com/. Quel type de mot de passe choisir, le mieux serait un mélange de mots aléatoire, en évitant les remplacements évidents, comme un 3 pour un E.
Ajoutons un autre site : heartbleed

Expérience utilisateur

De ce côté, une pratique répandue, en particulier quand on saisit une clé wi-fi, laisser l’utilisateur voir le mot qu’il tape, particulièrement utile pour de longs mots de passe. En commun, savoir afficher le niveau de sécurité approximatif est un plus.
En fonction de la popularité de son application, il peut être bon de donner accès à celle-ci avant de restreindre l’accès par login, il sera décevant de ne rien voir d’une appli inconnue, surtout si le seul login proposé est lié à un compte social type facebook.

Le développement

Que faire des informations reçues ? Le stockage est essentiel pour assurer une connexion aux services transparente, mais quelle stratégie adopter ?
Stocker le mot de passe sur le device : utiliser sqlcypher pour Android, un moyen simple. On peut citer également l’utilisation d’un librairie pour sécuriser les Préférences, ainsi que l’utilisation encore assez peu répandue de l’API Android KeyChain.

Les alternatives aux passwords

Que faire pour offrir une authentification simple dans son app :

  • Le combo email/password, un lien généré et un token de sécurité valable « un certain temps » !
  • La techno oAuth2, qui apporte un confort de développement important par rapport à la version 1, et que l’on peut utiliser avec une librairie comme Scribe, qui simplifie beaucoup les appels et la gestion des requêtes.
  • La stratégie de plus en plus répandue : un ou plusieurs réseaux sociaux. Après la mort de OpenID en 2012 suite à un hack, il n’y a pas vraiment aujourd’hui de standard, mais les plus grand réseaux offrent leurs API simplement : Google+, Facebook, Twitter, Yahoo et autres.

Note :
Pour l’authentification au sein de son application, la génération des clés est l’étape la plus simple. En revanche, être capable de réaliser les requêtes correctement peut vite devenir un casse tête, surtout si on veut offrir le choix de 3 ou 4 réseaux sociaux. Pour simplifier ces appels, nous utilisons, aussi bien en natif qu’en hybride, les librairies FireBase pour Android. Pour assurer un accès sécurisé aux données qu’ils hébergent dans le cloud et exposent en REST, ils ont inclut tout le nécessaire pour faciliter l’authentification sur ces grands réseaux.

Au final un talk intéressant de Tim Messerschmidt sur un sujet qui continuera à prendre de l’importance avec la montée en puissance des services « cloud ».

Alain Boudard

aboudard

24 sept
2014

Droidcon 2014 – Android Wear

Une superbe conférence de Mario Viviani, simple et efficace pour comprendre rapidement comment utiliser l’API Wear de Google.
Lorsqu’on veut faire communiquer un smartphone et un « wearable », c’est à dire une montre, un bandeau de mesure du pouls etc, il y’a deux classes essentielles:

DataItem

Comme son nom l’indique, cette classe peut contenir des données (jusqu’à 100kb)et fonctionne sur le principe très simple de la réplication. On crée un objet sur le smartphone et il se synchronise sur le wearable. Le tout avec un simple listener, qui permet de savoir quand le nouveau contenu est disponible.
En quelques lignes…
Il faut tout d’abord initialiser le GoogleApiClient, qui va se connecter à Google Services pour faire la connexion:

mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(Wearable.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

Il est important de bien faire attention à appeler mGoogleApiClient.start() et mGoogleApiClient.stop() dans les méthodes onStart() et onStop() de nos contextes.

Puis, d’écrire, côté émetteur:

    //On crée une requête basée sur un path et une valeur
    PutDataMapRequest dataMap = PutDataMapRequest.create("/count");
    dataMap.getDataMap().putInt(COUNT_KEY, count++);
    PutDataRequest request = dataMap.asPutDataRequest();
    // On indique à l'API Wear que notre DataItem que l'on a wrappé
    // dans une PutDataMapRequest est prêt à être synchronisé
    PendingResult<DataApi.DataItemResult> pendingResult =
        Wearable.DataApi.putDataItem(mGoogleApiClient, request);

Côté récepteur:

@Override
public void onDataChanged(DataEventBuffer dataEvents) {
    //On écoute simplement les événements "onDataChanged"
    for (DataEvent event : dataEvents) {
        //selon le type d'événement reçu, on traite
        if (event.getType() == DataEvent.TYPE_DELETED) {
            Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
        } else if (event.getType() == DataEvent.TYPE_CHANGED) {
             Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());
        }
    }
}

Les Messages

De la même façon, pour envoyer un message, on a besoin d’initialiser le GoogleApiClient. Généralement, on veut envoyer le message à une Node, c’est à dire un wearable. Pour récupérer la liste des objets connectés, on peut appeler cette méthode utilitaire:

private Collection<String> getNodes() {
    HashSet <String>results= new HashSet<String>();
    NodeApi.GetConnectedNodesResult nodes =
        Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
    for (Node node : nodes.getNodes()) {
        results.add(node.getId());
    }
    return results;
}

Puis il suffit d’envoyer le message!

...
byte[] message = new String("Hello Oxiane!").getBytes();

SendMessageResult result = Wearable.MessageApi
    .sendMessage(mGoogleApiClient, node, "path_defini_pour_mon_message", message).await();

if (!result.getStatus().isSuccess()) {
    Log.e(TAG, "ERROR: failed to send Message: " + result.getStatus());
}
...

Une petite précision pour compliqué ce qui semble un peu trop facile: la méthode sendMessage est synchrone! Elle ne retourne pas avant d’avoir envoyé le message.

Côté récepteur, on n’a plus qu’à implémenter la méthode onMessageReceived:

@Override
public void onMessageReceived(MessageEvent messageEvent) {
    if (messageEvent.getPath().equals("path_defini_pour_mon_message")) {
       //j'ai reçu mon message!
    }
}

Pour terminer, Mario nous a présenté une petite librairie de sa conception qui facilite encore plus l’utilisation de l’API wear. Sans avoir pu la tester moi-même,

Johann Hilbold

jhilbold

22 sept
2014

DroidCon Paris 2014 – Support multi-écran dans Android

Première journée du DroidCon Paris 2014 !

Et première présentation sur le support du pulti-écran sur Android.

L’objectif

Qu’est-ce qu’on peut faire avec ce machin ? Pour commencer, le multi écran, c’est pas nouveau, et grâce aux cables HDMI et HML, on peut depuis longtemps diffuser son contenu sur un autre écran – genre j’ai toujours un xperia S alors je sais de quoi je parle quand je dis « depuis longtemps » ;) .
Cette présentation avait pour but de nous montrer l’état de l’art dans deux domaines : les outils physiques (les dongle) et les API.
Propulser son contenu sur un écran déporté, toi aussi développeur tu vas pouvoir le faire, et tu pourras même avoir un affichage sensiblement différent entre ton device et l’écran connecté.

Les moyens techniques du screencast

Aujourd’hui, on parle de deux technologies :

Chromecast, la solution de Google, permet de se connecter via un réseau wi-fi existant, avec comme point fort : pas besoin d’appareils compatibles.

Miracast est intégré aux devices récents, et permet de se connecter sans avoir de réseau wi-fi existant. Au passage, ça permet un temps de latence très bas, pour une technologie sans fil. Problème potentiel : avoir un écran compatible avec la norme. Cette technologie a pour vocation de s’étendre dans les objets connectés, et doit permettre également de gérer des devices secondaires, comme un clavier, via l’USB Input Back Channel.

Les API Android de screencast

On entre là dans la partie intéressante, qui frise assez sérieusement avec l’expérimentation, un peu comme quand on cause de développement Android Wear ou Google Glass… la doc existe, mais elle est parfois un peu farfelue.
On note quand même que Miracast est disponible sur Android depuis l’API level 17 (4.2).
En gros comment ça marche, on a une classe qui est très proche de Dialog : la classe Presentation du MediaRouter. Il existe une autre classe, mais cette présentation ne s’étendait pas sur le sujet.
Le MediaRouter ramène une « route » de type video, laquelle expose – si il existe – un Display. Ce Display est injecté en paramètre de la Presentation, la méthode .show() fait le reste.

Au final, quelques lignes de code et on est capable de projeter son contenu !
Tout un ensemble de méthodes de callback permettent de gérer le cycle de vie, en particulier les problèmes de connexion.

Dongle Netgear Miracast

Au final, une présentation simple et claire de Xavier Hallade, avec Intel qui est venu en force à ce DroidCon 2014 !

Alain Boudard

aboudard

22 sept
2014

Droidcon Paris 2014 – Manipulation du byte code sous Android

J’ai eu la chance d’assister à la présentation sur la manipulation du byte code sous Android à la Droidcon 2014.

Deux librairies ont été présentées:

Afterburner

Une librairie qui permet d’éviter le code redondant lors de l’écriture de librairies. On peut ainsi injecter un morceau de code à des endroits bien précis, aussi précisément que « dans telle méthode de telle classe et après l’appel de telle méthode ». Par exemple, avec une classe qui ressemble à ça:

public class A {
  private int foo;
  public void bar() {}
  public void foo() {
     bar();
  }
}

On peut donner une valeur à la variable « int foo », dans la méthode « foo() », après l’appel de la méthode « bar() »:
InsertableMethod.Builder builder = new InsertableMethod.Builder( new AfterBurner() );

CtClass classToInsertInto = ClassPool.getDefaultPool().get(A.class.getName());
builder
  .insertIntoClass(A.class.getName())
  .inMethodIfExists("foo")
  .afterACallTo("bar")
  .withBody("this.foo = 2;")
  .elseCreateMethodIfNotExists("public void foo() { this.foo = 2; }")
  .doIt();

Cela reviendrait à écrire:

public class A {
  private int foo;
  public void bar() {}
  public void foo() {
     bar();
     //ADDED by AfterBurner
     this.foo = 2;
  }
}

Alors bien sûr, à priori, on ne voit pas forcément l’intérêt de la chose. Pourquoi s’embêter à injecter quand on peut écrire soi même « this.foo = 2; » dans le corps de sa méthode? Il s’avère que c’est très pratique!
Un petit projet d’implémentation a été présenté sous Android, il permet d’afficher dans les logs tous les appels aux méthode du cycle de vie des activités. Il s’agit de Loglifecycle. Avec une seule annotation sur les activités que l’on veut observer, on obtient dans les logs tous les appels aux méthodes onCreate, onContentChanged, onResume etc.
On peut imaginer tout un tas d’autres cas d’applications pour cette librairie, peut-être même la modification d’un code dont on n’a pas les sources (mais dont on connaît les classes/méthodes)!

Mimic

Mimic est une librairie qui permet, en quelque sorte, d’accéder à l’héritage multiple sous Java/Android. Le principe est de copier coller tous les attributs, constructeurs et méthodes d’une classe A dans une classe B.
Par exemple,

public class A{
    public void foo() {
    }
}

@Mimic(sourceClass = B.class,
    mimicMethods = {@MimicMethod(methodName="foo",mode=MimicMode.AT_BEGINNING)}
)
public class Aprime extends A{
    @Override
    public void foo() {
        super.foo();
    }
}

public class B{
    public void foo() {
        System.out.println("Hello B !");
    }
}

La méthode foo() de Aprime ne fait qu’appeler la méthode foo() de A. Or, comme on a appelé Mimic sur A et qu’on lui a demandé de remplacer « foo », c’est bien « Hello B! » qui sera appelé!

Johann Hilbold

jhilbold

5 sept
2014

Construire des thèmes facilement sous iOS

Un problème

Récemment j’ai eu besoin de pouvoir changer facilement et rapidement
la couleur de tous mes boutons et de tous mes titres.

Généralement, on a des images pour nos contrôles ou on utilise des couleurs
depuis le code/storyboard.

Si on le fait par image, on change donc l’image et c’est fini.
Si on utilise des couleurs via le code, on change éventuellement une macro :

//#define activeColor [UIColor redColor]
#define activeColor [UIColor blueColor]

Oui mais personnellement, je préfère définir mes couleurs dans Lire la suite du bllet »

Manuel François

tHeFeaTuReDMaN