web-dev-qa-db-fra.com

Office 365 xoauth2 pour l'authentification IMAP et SMTP échoue

Récemment le Support pour OAuth 2.0 pour IMAP et SMTP dans l'Exchange Online a été annoncé. Suivant le guide J'ai configuré le Autorisations d'application et connexion IMAP et SMTP. L'application est configurée sous forme Accounts in any organizational directory (Any Azure AD directory - Multitenant) et utilise flux de code d'autorisation .

Les URL ci-dessous sont utilisées pour l'autorisation:

Et les scopes de graphes Microsoft Délégués suivants ont été ajoutés:

enter image description here

Les champs, demandes de code:

final List<String> scopes = Arrays.asList(
    "offline_access",
    "email",
    "openid",
    "profile",
    "User.Read",
    "Mail.ReadWrite",
    "https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",
    "https%3A%2F%2Foutlook.office365.com%2FSMTP.Send"
);

J'ai réussi à recevoir les jetons d'accès et actualisés:

{
    "token_type": "Bearer",
    "scope": "email IMAP.AccessAsUser.All Mail.ReadWrite openid profile SMTP.Send User.Read",
    "expires_in": 3599,
    "ext_expires_in": 3599,
    "access_token": "edited",
    "refresh_token": "edited",
    "id_token": "edited"
}

Voici le code, utilisé pour se connecter à IMAP:

Properties props = new Properties();
props.put("mail.imap.ssl.enable", "true");
props.put("mail.imaps.sasl.enable", "true");
props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
props.put("mail.imap.auth.login.disable", "true");
props.put("mail.imap.auth.plain.disable", "true");
props.put("mail.debug", "true");
props.put("mail.debug.auth", "true");

Session session = Session.getInstance(props);
session.setDebug(true);

String userEmail = "[email protected]";
String accessToken = "access_token_received_on_previous_step";

final Store store = session.getStore("imaps");
store.connect("Outlook.office365.com", 993, userEmail, accessToken);

Qui génère la sortie suivante:

DEBUG: JavaMail version 1.6.2
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: setDebug: JavaMail version 1.6.2
DEBUG: getProvider() returning javax.mail.Provider[STORE,imaps,com.Sun.mail.imap.IMAPSSLStore,Oracle]
DEBUG IMAPS: mail.imap.fetchsize: 16384
DEBUG IMAPS: mail.imap.ignorebodystructuresize: false
DEBUG IMAPS: mail.imap.statuscachetimeout: 1000
DEBUG IMAPS: mail.imap.appendbuffersize: -1
DEBUG IMAPS: mail.imap.minidletime: 10
DEBUG IMAPS: enable SASL
DEBUG IMAPS: SASL mechanisms allowed: XOAUTH2
DEBUG IMAPS: closeFoldersOnStoreFailure
DEBUG IMAPS: trying to connect to Host "Outlook.office365.com", port 993, isSSL true
* OK The Microsoft Exchange IMAP4 service is ready. [QQBNADc...]
A0 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS MOVE ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+
A0 OK CAPABILITY completed.
DEBUG IMAPS: AUTH: PLAIN
DEBUG IMAPS: AUTH: XOAUTH2
DEBUG IMAPS: protocolConnect login, Host=Outlook.office365.com, [email protected], password=<non-null>
DEBUG IMAPS: SASL Mechanisms:
DEBUG IMAPS:  XOAUTH2
DEBUG IMAPS: 
DEBUG IMAPS: SASL client XOAUTH2
DEBUG IMAPS: SASL callback length: 2
DEBUG IMAPS: SASL callback 0: javax.security.auth.callback.NameCallback@17046283
DEBUG IMAPS: SASL callback 1: javax.security.auth.callback.PasswordCallback@5bd03f44
A1 AUTHENTICATE XOAUTH2 dXNlcj1o...
A1 NO AUTHENTICATE failed.

Exception in thread "main" javax.mail.AuthenticationFailedException: AUTHENTICATE failed.
    at com.Sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.Java:732)
    at javax.mail.Service.connect(Service.Java:366)

Et le code suivant est utilisé pour la connexion à SMTP:

Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.auth.mechanisms", "XOAUTH2");
props.put("mail.smtp.auth.login.disable","true");
props.put("mail.smtp.auth.plain.disable","true");
props.put("mail.debug.auth", "true");

Session session = Session.getInstance(props);
session.setDebug(true);

String userEmail = "[email protected]";
String accessToken = "access_token_received_on_previous_step";

Transport transport = session.getTransport("smtp");
transport.connect("smtp.office365.com", 587, userEmail, accessToken);

Qui fournit la sortie ci-dessous:

DEBUG: setDebug: JavaMail version 1.6.2
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.Sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to Host "smtp.office365.com", port 587, isSSL false
220 AM5PR0701CA0005.Outlook.office365.com Microsoft ESMTP MAIL Service ready at Mon, 4 May 2020 15:52:28 +0000
DEBUG SMTP: connected to Host "smtp.office365.com", port: 587
EHLO ubuntu-B450-AORUS-M
250-AM5PR0701CA0005.Outlook.office365.com Hello [my ip here]
250-SIZE 157286400
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-STARTTLS
250-8BITMIME
250-BINARYMIME
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "157286400"
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "DSN", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "STARTTLS", arg ""
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "BINARYMIME", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
STARTTLS
220 2.0.0 SMTP server ready
EHLO ubuntu-B450-AORUS-M
250-AM5PR0701CA0005.Outlook.office365.com Hello [my ip here]
250-SIZE 157286400
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-AUTH LOGIN XOAUTH2
250-8BITMIME
250-BINARYMIME
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "157286400"
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "DSN", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN XOAUTH2"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "BINARYMIME", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
DEBUG SMTP: protocolConnect login, Host=smtp.office365.com, [email protected], password=<non-null>
DEBUG SMTP: Attempt to authenticate using mechanisms: XOAUTH2
DEBUG SMTP: Using mechanism XOAUTH2
AUTH XOAUTH2 dXNlcj1obW9kaUB...
535 5.7.3 Authentication unsuccessful [AM5PR0701CA0005.eurprd07.prod.Outlook.com]

Exception in thread "main" javax.mail.AuthenticationFailedException: 535 5.7.3 Authentication unsuccessful [AM5PR0701CA0005.eurprd07.prod.Outlook.com]
    at com.Sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.Java:965)
    at com.Sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.Java:876)
    at com.Sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.Java:780)
    at javax.mail.Service.connect(Service.Java:366)

Ce que j'ai aussi essayé:

  • spécifier les champs comme https://graph.Microsoft.com/SMTP.Send et juste SMTP.Send
  • en utilisant https://login.microsoftonline.com/common/ URL pour l'authentification

Le résultat est toujours le même.

Est-ce quelque chose que je fais mal ou il y a un bogue quelque part dans le support pour cela du côté Microsoft?

Mise à jour 1:

Essayé de la ligne de commande, mais le même résultat:

$ openssl s_client -crlf -connect Outlook.office365.com:993
... connection part omitted
* OK The Microsoft Exchange IMAP4 service is ready. [QQBNADYAUAAxADkAMgBDAEEAMAAwADkAMQAuAEUAVQBSAFAAMQA5ADIALgBQAFIATwBEAC4ATwBVAFQATABPAE8ASwAuAEMATwBNAA==]
C01 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+
C01 OK CAPABILITY completed.
A01 AUTHENTICATE XOAUTH2 dXNlcj1obW9kaUBjb...
A01 NO AUTHENTICATE failed.
* BYE Connection is closed. 13
read:errno=0

Mise à jour 2:

J'ai essayé de créer une nouvelle application dans le portail Azure avec les autorisations suivantes:

enter image description here

Et recevoir l'écran suivant, lorsque vous essayez de donner son consentement pour les étanches:

enter image description here

C'est impair, car les autorisations de Azure Portal ne spécifient pas que le consentement de l'administrateur est requis et que mon enregistrement de l'application précédente n'affiche pas de cet écran lorsque des champs d'IMAP et de SMTP sont demandés.

Mise à jour 3:

Grâce aux commentaires à ce message, j'ai essayé les scopes suivants:

public static final List<String> SCOPES = Arrays.asList(
    "offline_access",
    "https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",
    "https%3A%2F%2Foutlook.office365.com%2FSMTP.Send"
);

Ce qui m'a donné le jeton ci-dessous:

{
    "token_type": "Bearer",
    "scope": "https://Outlook.office365.com/IMAP.AccessAsUser.All https://Outlook.office365.com/SMTP.Send",
    "expires_in": 3599,
    "ext_expires_in": 3599,
    "access_token": "eyJ0eXAiOiJKV1....",
    "refresh_token": "OAQABAAAAAAAm...."
}

IMAP/SMTP Auth a été réussi et j'ai pu lire la boîte de réception + envoyer un email!

Mais pour ma demande, j'ai également besoin de quelques autres étendues pour utiliser des points d'extrémité des API de graphique MS (Lire le profil d'utilisateur, la suppression des messages des messages et des messages).

J'ai donc essayé différentes étendues:

public static final List<String> SCOPES = Arrays.asList(
        "offline_access",
        "User.Read",
        "Mail.ReadWrite",
        "https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",
        "https%3A%2F%2Foutlook.office365.com%2FSMTP.Send"
);

Cela a donné le jeton (note que la valeur de portée diffère du jeton qui a effectivement travaillé, les autorisations n'ont pas d'Outlook URL):

{
    "token_type": "Bearer",
    "scope": "IMAP.AccessAsUser.All Mail.ReadWrite SMTP.Send User.Read profile openid email",
    "expires_in": 3599,
    "ext_expires_in": 3599,
    "access_token": "eyJ0eXAiOiJKV1Q...",
    "refresh_token": "OAQABAAAAAAAm..."
}

Qui a conduit au résultat que j'ai déjà fait:

A1 NO AUTHENTICATE failed.

Essayer toutes les étanches d'être comme URL:

public static final List<String> SCOPES = Arrays.asList(
        "offline_access", // or "https%3A%2F%2Fgraph.Microsoft.com%2Foffline_access"
        "https%3A%2F%2Fgraph.Microsoft.com%2FUser.Read",
        "https%3A%2F%2Fgraph.Microsoft.com%2FMail.ReadWrite",
        "https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",
        "https%3A%2F%2Foutlook.office365.com%2FSMTP.Send"
);

Conduit à l'erreur suivante lors de l'obtention du jeton (l'étape de consentement passée avec succès):

{
    "error": "invalid_request",
    "error_description": "AADSTS28000: Provided value for the input parameter scope is not valid because it contains more than one resource. Scope offline_access https://graph.Microsoft.com/user.read https://graph.Microsoft.com/mail.readwrite https://Outlook.office365.com/imap.accessasuser.all https://Outlook.office365.com/smtp.send is not valid.\r\nTrace ID: c3282396-6231-4e11-8300-77bc2ca57f00\r\nCorrelation ID: 5f5145bf-7114-4e6c-ab11-30e7ff84a056\r\nTimestamp: 2020-05-06 08:08:48Z",
    "error_codes": [
        28000
    ],
    "timestamp": "2020-05-06 08:08:48Z",
    "trace_id": "c3282396-6231-4e11-8300-77bc2ca57f00",
    "correlation_id": "5f5145bf-7114-4e6c-ab11-30e7ff84a056"
}

Et lorsque vous essayez toutes les étanches d'avoir Microsoft Graph (comme copié du portail Azure)

public static final List<String> SCOPES = Arrays.asList(
    "https%3A%2F%2Fgraph.Microsoft.com%2Foffline_access",
    "https%3A%2F%2Fgraph.Microsoft.com%2FUser.Read",
    "https%3A%2F%2Fgraph.Microsoft.com%2FMail.ReadWrite",
    "https%3A%2F%2Fgraph.Microsoft.com%2FIMAP.AccessAsUser.All",
    "https%3A%2F%2Fgraph.Microsoft.com%2FSMTP.Send"
);

Renvoie le jeton suivant (sans rafraîchir le jeton d'actualisation ALTHOUT Offline_Access a été demandé)

{
    "token_type": "Bearer",
    "scope": "profile openid email https://graph.Microsoft.com/IMAP.AccessAsUser.All https://graph.Microsoft.com/Mail.ReadWrite https://graph.Microsoft.com/SMTP.Send https://graph.Microsoft.com/User.Read",
    "expires_in": 3599,
    "ext_expires_in": 3599,
    "access_token": "eyJ0eXAiOiJKV1..."
}

Sans succès:

A1 NO AUTHENTICATE failed.

Il semble donc que si vous ne spécifiez pas l'URL Outlook pour une portée, elle est probablement présumée sous forme de graphique qui n'autorise pas l'autorisation via IMAP et SMTP.

Mise à jour 4:

En demandant à toutes les étanches dont j'ai besoin lors de l'étape de consentement, puis obtenez le premier jeton d'accès avec uniquement des étendues graphiques et la seconde à l'aide de l'enceinte de jeton de rafraîchissement spécifiant Outlook Slopes - cela a fonctionné. Actualiser la méthode de jeton pour obtenir un deuxième jeton d'accès est utilisé car si vous essayez d'obtenir un jeton d'accès par le code d'authentification, vous obtiendrez l'erreur suivante:

{
    "error": "invalid_grant",
    "error_description": "AADSTS54005: OAuth2 Authorization code was already redeemed, please retry with a new valid code or use an existing refresh token.\r\nTrace ID: 09fc80f4-f5fd-4e52-938f-d56b71dd0900\r\nCorrelation ID: 4f35e05c-23c8-4fdc-a5a7-2fcde5a73b44\r\nTimestamp: 2020-05-08 12:13:30Z",
    "error_codes": [
        54005
    ],
    "timestamp": "2020-05-08 12:13:30Z",
    "trace_id": "09fc80f4-f5fd-4e52-938f-d56b71dd0900",
    "correlation_id": "4f35e05c-23c8-4fdc-a5a7-2fcde5a73b44"
}

Donc, non, je devrai utiliser deux jetons distincts en fonction de la ressource dont je vais devoir gérer.

Mise à jour 5:

Si cela ne fonctionne toujours pas - Vérifiez si votre organisation est activée par défaut de sécurité - ils désactivent les comptes POP/IMAP/SMTP pour les comptes - https://techcommunity.microsoft.com/t5/exchange-team-blog/ Annonce-Oauth-2-0-Soutien-Soutenir-for-IMAP-and-SMTP-Auth-Protocols-in/BC-P/1544725/Highlight/TRUE # M28589

4
ledniov

exemple javax.mail Envoi de courrier électronique à l'aide de Xoauth et O365 SMTP

Je ne demandais que ces scopes nécessaires pour envoyer un courrier électronique ... (pas utiliser le graphique). J'ai probablement configuré certaines autorisations non nécessaires.

0
Eino Mäkitalo