Мне удалось получить токен доступа, но не удалось установить соединение.< /p>
Ниже приведены выполненные действия и приведен код для справки.
Код: Выделить всё
1. Created client_id and client_secret
2. Created onetime auth code using (https://accounts.google.com/o/oauth2/auth?client_id=&redirect_uri=http://localhost&response_type=code&scope=https://www.googleapis.com/auth/drive&access_type=offline)
3. Using code got access token and refresh token
4. Passed access token as oauthToken in the code (session properties)
включена двухфакторная аутентификация.
пароль приложения создан.
Код: Выделить всё
public class OAuth2SaslClientFactory implements SaslClientFactory {
private static final Logger logger =
Logger.getLogger(OAuth2SaslClientFactory.class.getName());
public static final String OAUTH_TOKEN_PROP =
"mail.imaps.sasl.mechanisms.oauth2.oauthToken";
public SaslClient createSaslClient(String[] mechanisms,
String authorizationId,
String protocol,
String serverName,
Map props,
CallbackHandler callbackHandler) {
boolean matchedMechanism = false;
for (int i = 0; i < mechanisms.length; ++i) {
if ("XOAUTH2".equalsIgnoreCase(mechanisms[i])) {
matchedMechanism = true;
break;
}
}
if (!matchedMechanism) {
logger.info("Failed to match any mechanisms");
return null;
}
return new OAuth2SaslClient((String) props.get(OAUTH_TOKEN_PROP),
callbackHandler);
}
public String[] getMechanismNames(Map props) {
return new String[] {"XOAUTH2"};
}
}
class OAuth2SaslClient implements SaslClient {
private static final Logger logger =
Logger.getLogger(OAuth2SaslClient.class.getName());
private final String oauthToken;
private final CallbackHandler callbackHandler;
private boolean isComplete = false;
public OAuth2SaslClient(String oauthToken, CallbackHandler callbackHandler) {
this.oauthToken = oauthToken;
this.callbackHandler = callbackHandler;
}
public String getMechanismName() {
return "XOAUTH2";
}
public boolean hasInitialResponse() {
return true;
}
public byte[] evaluateChallenge(byte[] challenge) throws SaslException {
if (isComplete) {
// Empty final response from server, just ignore it.
return new byte[] {};
}
NameCallback nameCallback = new NameCallback("email");
PasswordCallback passwordCallback = new PasswordCallback("password",
false);
Callback[] callbacks = new Callback[] { nameCallback, passwordCallback
};
try {
callbackHandler.handle(callbacks);
} catch (UnsupportedCallbackException e) {
throw new SaslException("Unsupported callback: " + e);
} catch (IOException e) {
throw new SaslException("Failed to execute callback: " + e);
}
String email = nameCallback.getName();
byte[] response = String.format("user=%s\1auth=Bearer %s\1\1", email,
oauthToken).getBytes();
isComplete = true;
return response;
}
public boolean isComplete() {
return isComplete;
}
public byte[] unwrap(byte[] incoming, int offset, int len) throws
SaslException {
throw new IllegalStateException();
}
public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException
{
throw new IllegalStateException();
}
public Object getNegotiatedProperty(String propName) {
if (!isComplete()) {
throw new IllegalStateException();
}
return null;
}
public void dispose() throws SaslException {
}
}
public static final class OAuth2Provider extends Provider {
private static final long serialVersionUID = 1L;
public OAuth2Provider() {
super("Google OAuth2 Provider", 1.0, "Provides the XOAUTH2
SASL Mechanism");
put("SaslClientFactory.XOAUTH2",
"com.email.oauth.OAuth2SaslClientFactory");
}
}
public void authenticate(String args[]) throws Exception {
if (args.length != 2) {
System.err.println("Usage: OAuth2Authenticator
");
return;
}
String email = args[0];
String oauthToken = args[1];
Security.addProvider(new OAuth2Provider());
System.out.println(oauthToken);
IMAPStore imapStore = connectToImap("imap.gmail.com", 993, email,
oauthToken, true);
Folder[] folders = imapStore.getPersonalNamespaces();
System.out.println(folders);
System.out.println("Successfully authenticated to IMAP.\n");
}
Properties props = new Properties();
props.put("mail.imaps.sasl.enable", "true");
props.put("mail.debug.auth", "true");
props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
props.put(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, oauthToken);
Session session = Session.getInstance(props);
session.setDebug(debug);
final URLName unusedUrlName = null;
IMAPSSLStore store = new IMAPSSLStore(session, unusedUrlName);
final String emptyPassword = "app passowrd";
store.connect(host, port, userEmail, emptyPassword);
ОТЛАДКА IMAPS: длина обратного вызова SASL: 2
ОТЛАДКА IMAPS: обратный вызов SASL 0: javax. Security.auth.callback.NameCallback@2c5be2fe
ОТЛАДКА IMAPS: обратный вызов SASL 1: javax.security.auth.callback.PasswordCallback@285fa04b
B1 АУТЕНТИФИКАЦИЯ XOAUTH2
ОТЛАДКА IMAPS: SASL нет ответа
B1 НЕТ [ AUTHENTICATIONFAILED] Неверные учетные данные (сбой)
jakarta.mail.AuthenticationFailedException: [AUTHENTICATIONFAILED] Неверные учетные данные (сбой)
в com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:708)
в jakarta.mail.Service. Connect(Service.java:345)
в com.email.Application.connectToImap(Application.java:101)
на com.email.Application.authonticate(Application.java:54)
на com.email. Application.main(Application.java:37)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
в org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
Подробнее здесь: https://stackoverflow.com/questions/793 ... ing-oauth2
Мобильная версия