Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Expert éminent sénior
    Adoption de Microsoft Graph avec Auth Azure AD en remplacement de IMAP4 Basic Auth
    Bonjour,

    En prévision de l’arrêt du Basic Auth en POP3 et IMAP4 et l’obligation de passer par un chiffrement TLS1.2
    Si vous avez des infos à ce sujet ?
    ou plutôt ces sujets, c'est deux éléments différents
    - Identification : Basic Auth en OAuth2 (Beared Auth avec son petit token JWT)
    - Sécurité : TLS 1.2 ( c'est mieux que SSL à ce qu'ils en disent, suivons donc le mouvement )

    Au bureau, il y a aurait des rumeurs comme quoi l'ensemble des protocoles POP3 et IMAP4 seraient plus supporté par Office 365 ( à différencier de boite Outlook simple )
    Je serais plus modéré en pensant que c'est uniquement la Basic Authentication (Login + PWD encodé en Base 64 par exemple en HTTP) qui ne sera plus supporté
    Ma source : https://developer.microsoft.com/en-u...365-customers/

    Que pensez-vous de cet article ?
    https://docs.microsoft.com/en-us/off...-in-office-365
    Idem est-ce l'ensemble des protocoles POP3/IMAP4 qui ne sera plus supporté ou juste TLS 1.0/1.1 qu'il faut remplacer par tu TLS 1.2
    Il y a même aussi le TLS 1.3 mais c'est très vague
    https://developer.microsoft.com/en-u...365-customers/

    To make it easier to migrate your existing applications to use OAuth 2.0, we are making significant investments to our service that include OAuth 2.0 support for POP, IMAP, and background application support for Remote PowerShell MFA module. We will be sharing more information on these new features over the coming months. For more information on OAuth 2.0 and details on how to make the transition, please refer to the following articles:
    https://docs.microsoft.com/en-us/azu...op/v2-overview
    https://docs.microsoft.com/fr-fr/graph/auth/
    .
    Ce passage signifie-t-il que l'on peut utilisé OAuth 2.0 sur IMAP mais que ce dernier est conservé juste avec une autre méthode d'authentification ?
    J'étudie justement l'authentification par Azure AD via "https://login.microsoftonline.com/.../oauth2/v2.0/token' en HTTP/1.1

    OAuth2 semble gérer un token BEARER, je l'ai codé en XE2 pour l'accès à un WS REST Symfony qui utilisait cette méthode : https://www.developpez.net/forums/d1.../#post10801570
    Cela ne me pose pas de problème de le coder à la main, au pire je regarderais MSAL (nouvel ADAL) qui sera une corvée à traduire depuis un autre langage quoi qu'il arrive ( eh oui, Delphi c'est pas DOT NET, MS ne fournit pas tout clé en main comme en C# où il n'y a aucun effort à faire )

    En XE3+, le token BEARER a été ajouté aux classes REST
    Et cela a été amélioré avec les versions suivantes dont je ne disposais pas à l'époque
    J'ai regardé TRESTClient et TRESTRequest sur
    "https://login.microsoftonline.com/common/oauth2/v2.0/token" retour HTTP/1.1 400 Bad Request
    "https://login.microsoftonline.com/common/oauth2/token" retour HTTP/1.1 401 Unauthorized

    Il semble que la version 1.0 du token JWT, "Azure AD v1.0" versus "Microsoft identity platform (v2.0)"
    Sur Stack Overflow, tout est en "oauth2/token" et jamais en "oauth2/v2.0/token" mais toujours en HTTP/1.1


    Plusieurs pistes sont à explorer pour remplacer IMAP4 Basic Auth
    - IMAP4 ajoutant le support de OAuth2 ( token JWT principe d’une Bearer Auth ) avec un patch pour Indy
    - Microsoft Graph remplacement IMAP avec ADAL, MSAL ou une requête https://login.microsoftonline.com )
    - Toutes autres suggestions


    - IMAP4 ajoutant le support de OAuth2
    ( token JWT principe d’une Bearer Auth ) avec un patch pour Indy : https://github.com/lordcrc/IndySASLO...ASLXOAuth2.pas
    Indy prend en charge le TLS 1.2, la mise à jour du couple de DLL (libeay32, ssleay32) est aussi important
    Cela résoudrait donc les deux sujets : Authentication et Protocole de Sécurité (si c'est bien juste ça qu'il faut changer pour Office 365)


    Microsoft Graph
    remplacement IMAP avec ADAL, MSAL ou une requête https://login.microsoftonline.com )

    Pour le moment, je n’ai pas trouvé la bonne requête (j’ai un BAD REQUEST sur la demande d’un token sur User.Read, le plus basic des droits)
    Je ne vais pas innonder de code pour le moment, je vais attendre de voir si ce sujet intéresse quelqu'un

    Cordialement
    SLT
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  2. #2
    Expert éminent sénior
    Salut,

    oui TLS 1.2 tend à ce généraliser, j'ai eu la blague récemment sur un webservice

    dans mon composant SChannel for Indy ça a consisté à changer un flag c'est aussi le cas sur le composant OpenSSL de Indy à condition d'avoir les bonnes DLL

    https://github.com/tothpaul/Delphi/t.../Indy.SChannel

    au passage TLS et SSL c'est la même chose, enfin SSL c'est l'ancien protocole de Netscape devenu TLS quand il a été normalisé par l'ensemble des acteurs mais on continue à parler de SSL par abus de langage (peut-être à cause de OpenSSL qui fait pourtant du TLS ).

    pour OAuth2 dans IMAP je ne sais pas trop comment ça fonctionne...le principe de OAuth2 est de solliciter une authentification sur un site web qui retourne un token à une URL callback. Il est parfois possible de se passer du site web si on ruse un peu, mais ce n'est pas toujours possible, mais tu peux encore ruser avec une URL callback sur localhost si ton appli embarque un mini serveur web. L'idée est donc d'avoir un service d'authentification centralisé qui permet à chaque ressource de t'identifier...comme quand tu te connectes sur un site web avec ton compte Google ou FaceBook au lieu de créer un compte spécifique au site....à priori je dirais que IMAP doit recevoir le token obtenu pour t'identifier au lieu du couple compte/password
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Expert éminent sénior
    Je n'ai pas encore regarder pour TLS 1.2
    Je n'ai pas encore regarder OAuth2 dans IMAP ( il faut remplacer la classe de Basic Auth par celle de OAuth2 que j'ai vu sur Github )
    J'attends que les admins reseaux de ma boite répondent à mon mail, voir comment on peut être sur que le TLS 1.2 est bien pris en compte
    Merci pour cette explication sur TLS et SSL, je n'avais jamais compris la différence, et effectivement que je continue à utiliser un TIdSSLIOHandlerSocketOpenSSL alors que c'est censé être du TLS
    pour le GET HTTPS j'avais arrête Indy qui me faisait des erreurs de SSL Handshake truc, les API InternetConnect semble gérer cela tellement mieux (couche de sécurité par defaut de windows ? je sais pas mais ça fonctionne à chaque fois que Indy semble plus être à niveau )

    Je suis à fond sur le token pour le moment
    Pour OAuth2, j'en suis justement à ça https://docs.microsoft.com/fr-fr/azu...eds-grant-flow
    J'avance
    Sur v2.0/authorize, j'ai une page web, je n'ai plus d'erreur de champ manquant mais j'avoue que je ne sais pas quoi faire du retour HTML (je m'attendais à un JSON) (s'affiche pas sur TWebBrowser et Edge refuse le fichier me parlant du cookie truc)
    Sur v2.0/token, toujours du 401 via Indy, avec HttpSendRequest il pige pas que je passe un POST et reçoit un GET
    je commence à mieux comprendre le protocole, ce qui est con, microsoft donne des exemples de cURL mais celui que j'ai semble pas aimé les exemples, il parse le contenu, en remplaçant les ' par des " c'est mieux, ça retourne un JSON, cela m'aide carrément ça
    je sais plus le nom mais il y a un outil pour tester des requêtes HTTP, je crois que c'est Postman mais je verrais avec mon expert outil demain qui m'avait justement parlé de cURL

    EDIT Indy est très con, dès qu'il détecte une erreur genre 400, il s'arrête alors qu'en fait, il a un JSON qui explique l'erreur commise comme un paramètre invalid
    Idem pour la 401, pour le client_id incorrecte

    EDIT 2 Du coup, je repasse dans les obscures TRESTClient et TRESTRequest pour lesquels on peut récupérer malgré l'erreur le JSON explicatif (comme avec cURL)


    Pour redirect_uri, j'utilise la valeur par défaut "https://login.microsoftonline.com/common/oauth2/nativeclient" que j'ai coché sur mon portal.azure.com d'entreprise
    Je verrais si vraiment, je devrais jouer la dessus, car c'est prévu pour être intégré dans un service windows et il y a déjà un autre service qui fait serveur web, alors si je dois aller à ces extrèmes, j'irais embêter mon chef pour modifier aussi le serveur web en plus.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  4. #4
    Expert éminent sénior
    Ah quel boulet !
    A force de jouer, j'ai laissé "6731de76-14a6-49ae-97bc-6eba6914391e" comme client id, c'est la valeur en exemple
    J'ai pas encore réussi à lui passer 'User.Read' comme Scope, pour le moment j'avance avec 'https://graph.microsoft.com/.default', j'ai droit sinon à une erreur AADSTS70011

    Bon, j'ai un beau JSON et le token
    Je passe donc à la suite "https://graph.microsoft.com/v1.0/me/messages"



    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    var
      RESTClient: TRESTClient;
      RESTRequest: TRESTRequest;
      OAuth2_Dynamics365: TOAuth2Authenticator;
      Source: TStringStream;
      ReponseContent: TStringStream;
      JSONObject: System.JSON.TJSONObject;
      ATenantID, AClientID, AClientSecret, ARedirection, AResourceURI, AToken, Scope, Params, LoginURL: string;
     
     
    begin
      ATenantID := '... cf Azure ...';
      AClientID := '... cf Azure ...';
      AClientSecret := '... cf Azure ...';
      ARedirection := System.NetEncoding.TURLEncoding.URL.Encode('https://login.microsoftonline.com/common/oauth2/nativeclient');
      AResourceURI := 'https://graph.microsoft.com/v1.0/me/messages';
      Scope := 'https://graph.microsoft.com/.default' ; /// 'User.Read'; // Mail.Read'; //  https://graph.microsoft.com/v1.0/me/messages
      //Scope := 'User.Read'; // Mail.Read'; //  https://graph.microsoft.com/v1.0/me/messages
     
      OAuth2_Dynamics365 := TOAuth2Authenticator.Create(nil);
      OAuth2_Dynamics365.TokenType := TOAuth2TokenType.ttBEARER;
     
      RESTClient := TRESTClient.Create('https://login.microsoftonline.com/');
      RESTClient.ContentType := 'application/x-www-form-urlencoded';
     
      RESTRequest := TRESTRequest.Create(RESTClient);
      RESTRequest.Method := TRESTRequestMethod.rmPOST;
    //  RESTRequest.Resource := '/' + ATenantID + '/oauth2/token';
      RESTRequest.Resource := '/' + ATenantID + '/oauth2/v2.0/token';
     
      // https://login.windows.net/common/oauth2/authorize?response_type=code&resource=https%3A%2F%2Fmanage.office.com&client_id={your_client_id}&redirect_uri={your_redirect_url }
      RESTRequest.Params.AddItem('client_id', AClientID, TRESTRequestParameterKind.pkGETorPOST);
      RESTRequest.Params.AddItem('scope', Scope, TRESTRequestParameterKind.pkGETorPOST);
      RESTRequest.Params.AddItem('client_secret', AClientSecret, TRESTRequestParameterKind.pkGETorPOST);
      RESTRequest.Params.AddItem('grant_type', 'client_credentials', TRESTRequestParameterKind.pkGETorPOST);
      RESTRequest.Client := RESTClient;
     
      try
        RESTRequest.Execute;
        if RESTRequest.Response.StatusCode = 200 then
        begin
     
          if RESTRequest.Response.GetSimpleValue('access_token', AToken) then
            OAuth2_Dynamics365.AccessToken := AToken;
     
          RESTClient.BaseURL := 'https://graph.microsoft.com';
          RESTClient.Authenticator := OAuth2_Dynamics365;
          RESTRequest.Params.Clear();
          RESTRequest.Resource := 'v1.0/me/messages';
          RESTRequest.Execute;
        end;
      except
        on EHTTP: EHTTPProtocolException do
          Memo1.Lines.Text := 'HTTP Error ' +  EHTTP.Message;
        on EREST: ERESTException do
          Memo1.Lines.Text := 'REST Error ' +  EREST.Message;
      end;
     
      Memo1.Lines.Text := RESTRequest.Response.Content;


    Code JSON :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    {
      "error": {
        "code": "NoPermissionsInAccessToken",
        "message": "The token contains no permissions, or permissions can not be understood.",
        "innerError": {
          "request-id": "..."
          "date": "2020-01-27T18:29:02"
        }
      }
    }


    je trouve ça logique puisque c'est un token DEFAULT que j'ai pas réussi à avoir mon token Mail.Read sans cette erreur AADSTS70011
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Expert éminent sénior
    pour OpenSSL et " des erreurs de SSL Handshake truc" c'est probablement les DLL qui ne sont pas à jour ... c'est une des raisons pour laquelle je suis passé à SChannel

    pour TidHTTP tu as des options dans HTTPOptions pour gérer les cas d'erreur, hoNoProtocolErrorException (pour éviter l'exception) et hoWantProtocolErrorContent (pour avoir la réponse JSON)

    pour OAuth2 j'ai souvent rencontré des refus du serveur si l'entête de la requête n'est pas valide
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      HTTP.Request.CharSet := 'utf-8';
      HTTP.Request.ContentType := 'application/json';
      HTTP.Request.Accept := 'application/json';


    mais c'est parfois plus complexe selon le serveur et l'API invoquée..et tu galères avant de trouver ça

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      HTTP.Request.CharSet := 'utf-8';
      HTTP.Request.ContentType := 'application/x-www-form-urlencoded';
      HTTP.Request.Accept := 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';
      HTTP.HTTPOptions := [hoForceEncodeParams, hoNoProtocolErrorException, hoWantProtocolErrorContent];
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  6. #6
    Expert éminent sénior
    Merci pour ces informations !

    Même la version de Delphi Seatle est donc déjà vieillissante, hoWantProtocolErrorContent a été ajouté Debut 2016 par Remy Lebeau

    J'ai arrêté aussi Indy pour le SSL à cause des deux DLL à déployer qui n'était jamais les bonnes.
    Dans une autre boite, l'EXE contenait les DLL en ressources et si les DLL installées n'avait pas la même signature,
    elles étaient écrasées par celui de l'EXE, cela permettait une mise à jour facile (EXE autonome).

    Ensuite ma curiosité m'a poussé sur HttpSendRequest, toujours sympa de connaitre différentes techniques.

    pour le "Accept", j'ai eu un message à un moment qui pourrait ressembler à un problème de ce type
    Je ne l'ai pas encore reproduit,

    mes admins IT qui ont eu un mail équivalent à mon premier message ne semble pas très bien connaitre le Portail Azure, j'ai survolé les applications enregistrées, toutes fonctionnent en autorisation déléguée, c'est à dire que cela propose à l'utilisateur de s'authentifier et c'est ses droits qui sont utilisés alors que je dois faire un bot en service qui n'a évidemment pas cette possibilité
    J'ai même trouvé des autorisations déléguées qui nécessitent une autorisation par les admins demandés depuis le 2018-02-07 pour SalesForce toujours en attente d'accord, je pense que donc que c'est un sujet totalement inconnu.

    En attendant que mes admins IT réagissent, je passe en mode délégué pour aller un peu plus loin sur l'utilisation de Graph
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Expert éminent sénior
    A l'occasion,
    voici une petite encapsulation de la partie Mail de Microsoft Graph, cela ne couvre pas grand chose en fonctionnalité mais le but est juste d'intégrer cela dans une programme robot qui aspire des mails, le code étant tourné sur le TIdMessage, pour éviter de tout modifier dans le projet, j'ai fait un Adpateur Indy qui simule le TIdMessage
    Source pour Delphi 10 Seattle Version 23.0.22248.5795 :
    Un projet démo non fourni :
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs