[DEV] [NEED TEST] Implement OAuth2 authentification to mail recovery!
This commit is contained in:
parent
48b845b1f5
commit
644ffe954d
@ -28,6 +28,7 @@ import fr.xephi.authme.listener.AuthMePlayerListener16;
|
|||||||
import fr.xephi.authme.listener.AuthMePlayerListener18;
|
import fr.xephi.authme.listener.AuthMePlayerListener18;
|
||||||
import fr.xephi.authme.listener.AuthMeServerListener;
|
import fr.xephi.authme.listener.AuthMeServerListener;
|
||||||
import fr.xephi.authme.listener.AuthMeServerStop;
|
import fr.xephi.authme.listener.AuthMeServerStop;
|
||||||
|
import fr.xephi.authme.mail.SendMailSSL;
|
||||||
import fr.xephi.authme.modules.ModuleManager;
|
import fr.xephi.authme.modules.ModuleManager;
|
||||||
import fr.xephi.authme.output.ConsoleFilter;
|
import fr.xephi.authme.output.ConsoleFilter;
|
||||||
import fr.xephi.authme.output.Log4JFilter;
|
import fr.xephi.authme.output.Log4JFilter;
|
||||||
|
|||||||
@ -479,7 +479,7 @@ public final class CommandInitializer {
|
|||||||
.description("Converter Command")
|
.description("Converter Command")
|
||||||
.detailedDescription("Converter command for AuthMeReloaded.")
|
.detailedDescription("Converter command for AuthMeReloaded.")
|
||||||
.withArgument("job", "Conversion job: flattosql / flattosqlite /| xauth / crazylogin / rakamak / " +
|
.withArgument("job", "Conversion job: flattosql / flattosqlite /| xauth / crazylogin / rakamak / " +
|
||||||
"royalauth / vauth / sqltoflat", false)
|
"royalauth / vauth / sqltoflat / sqlitetosql", false)
|
||||||
.permissions(OP_ONLY, AdminPermission.CONVERTER)
|
.permissions(OP_ONLY, AdminPermission.CONVERTER)
|
||||||
.executableCommand(new ConverterCommand())
|
.executableCommand(new ConverterCommand())
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@ -33,11 +33,7 @@ public class SqliteToSql implements Converter {
|
|||||||
{
|
{
|
||||||
plugin.database.saveAuth(auth);
|
plugin.database.saveAuth(auth);
|
||||||
}
|
}
|
||||||
sender.sendMessage("Convert command has finished !");
|
} catch (Exception e) {
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
sender.sendMessage(plugin.getMessages().retrieve(MessageKey.ERROR));
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
sender.sendMessage(plugin.getMessages().retrieve(MessageKey.ERROR));
|
sender.sendMessage(plugin.getMessages().retrieve(MessageKey.ERROR));
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|||||||
28
src/main/java/fr/xephi/authme/mail/OAuth2Provider.java
Normal file
28
src/main/java/fr/xephi/authme/mail/OAuth2Provider.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package fr.xephi.authme.mail;
|
||||||
|
|
||||||
|
import java.security.Provider;
|
||||||
|
|
||||||
|
/* Copyright 2012 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
public 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",
|
||||||
|
"fr.xephi.authme.mail.OAuth2SaslClientFactory");
|
||||||
|
}
|
||||||
|
}
|
||||||
103
src/main/java/fr/xephi/authme/mail/OAuth2SaslClient.java
Normal file
103
src/main/java/fr/xephi/authme/mail/OAuth2SaslClient.java
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/* Copyright 2012 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package fr.xephi.authme.mail;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.security.auth.callback.Callback;
|
||||||
|
import javax.security.auth.callback.CallbackHandler;
|
||||||
|
import javax.security.auth.callback.NameCallback;
|
||||||
|
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||||
|
import javax.security.sasl.SaslClient;
|
||||||
|
import javax.security.sasl.SaslException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An OAuth2 implementation of SaslClient.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of the OAuth2SaslClient. This will ordinarily only
|
||||||
|
* be called from OAuth2SaslClientFactory.
|
||||||
|
*/
|
||||||
|
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("Enter name");
|
||||||
|
Callback[] callbacks = new Callback[] { nameCallback };
|
||||||
|
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 {
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
/* Copyright 2012 Google Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package fr.xephi.authme.mail;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.security.auth.callback.CallbackHandler;
|
||||||
|
import javax.security.sasl.SaslClient;
|
||||||
|
import javax.security.sasl.SaslClientFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A SaslClientFactory that returns instances of OAuth2SaslClient.
|
||||||
|
*
|
||||||
|
* <p>Only the "XOAUTH2" mechanism is supported. The {@code callbackHandler} is
|
||||||
|
* passed to the OAuth2SaslClient. Other parameters are ignored.
|
||||||
|
*/
|
||||||
|
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<String, ?> 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<String, ?> props) {
|
||||||
|
return new String[] {"XOAUTH2"};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,8 @@
|
|||||||
package fr.xephi.authme;
|
package fr.xephi.authme.mail;
|
||||||
|
|
||||||
|
import fr.xephi.authme.AuthMe;
|
||||||
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
|
import fr.xephi.authme.ImageGenerator;
|
||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
|
||||||
@ -8,10 +11,16 @@ import org.apache.commons.mail.EmailException;
|
|||||||
import org.apache.commons.mail.HtmlEmail;
|
import org.apache.commons.mail.HtmlEmail;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
||||||
|
import com.sun.mail.smtp.SMTPTransport;
|
||||||
|
|
||||||
import javax.activation.DataSource;
|
import javax.activation.DataSource;
|
||||||
import javax.activation.FileDataSource;
|
import javax.activation.FileDataSource;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.mail.Transport;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.security.Provider;
|
||||||
|
import java.security.Security;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Xephi59
|
* @author Xephi59
|
||||||
@ -66,21 +75,36 @@ public class SendMailSSL {
|
|||||||
email.setFrom(acc, sender);
|
email.setFrom(acc, sender);
|
||||||
email.setSubject(subject);
|
email.setSubject(subject);
|
||||||
if (acc != null && !acc.isEmpty() && password != null && !password.isEmpty())
|
if (acc != null && !acc.isEmpty() && password != null && !password.isEmpty())
|
||||||
email.setAuthenticator(new DefaultAuthenticator(acc, password));
|
email.setAuthenticator(new DefaultAuthenticator(acc, !Settings.emailOauth2Token.isEmpty() ? "" : password));
|
||||||
switch (port) {
|
switch (port) {
|
||||||
case 587:
|
case 587:
|
||||||
case 25:
|
email.setStartTLSEnabled(true);
|
||||||
email.setStartTLSEnabled(true);
|
email.setStartTLSRequired(true);
|
||||||
break;
|
if (!Settings.emailOauth2Token.isEmpty())
|
||||||
case 465:
|
{
|
||||||
email.setSSLOnConnect(true);
|
if (Security.getProvider("Google OAuth2 Provider") == null)
|
||||||
break;
|
Security.addProvider(new OAuth2Provider());
|
||||||
default:
|
email.getMailSession().getProperties().setProperty("mail.smtp.starttls.enable", "true");
|
||||||
email.setStartTLSEnabled(true);
|
email.getMailSession().getProperties().setProperty("mail.smtp.starttls.required", "true");
|
||||||
email.setSSLOnConnect(true);
|
email.getMailSession().getProperties().setProperty("mail.smtp.sasl.enable", "true");
|
||||||
break;
|
email.getMailSession().getProperties().setProperty("mail.smtp.sasl.mechanisms", "XOAUTH2");
|
||||||
|
email.getMailSession().getProperties().setProperty(OAuth2SaslClientFactory.OAUTH_TOKEN_PROP, password);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 25:
|
||||||
|
email.setStartTLSEnabled(true);
|
||||||
|
email.setSSLCheckServerIdentity(true);
|
||||||
|
break;
|
||||||
|
case 465:
|
||||||
|
email.setSSLOnConnect(true);
|
||||||
|
email.setSSLCheckServerIdentity(true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
email.setStartTLSEnabled(true);
|
||||||
|
email.setSSLOnConnect(true);
|
||||||
|
email.setSSLCheckServerIdentity(true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
email.setSSLCheckServerIdentity(true);
|
|
||||||
String content = mailText;
|
String content = mailText;
|
||||||
// Generate an image ?
|
// Generate an image ?
|
||||||
File file = null;
|
File file = null;
|
||||||
@ -105,7 +129,12 @@ public class SendMailSSL {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
email.send();
|
if (!Settings.emailOauth2Token.isEmpty())
|
||||||
|
{
|
||||||
|
SMTPTransport.send(email.getMimeMessage(), acc, "");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SMTPTransport.send(email.getMimeMessage());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ConsoleLogger.showError("Fail to send a mail to " + mail + " cause " + e.getLocalizedMessage());
|
ConsoleLogger.showError("Fail to send a mail to " + mail + " cause " + e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
@ -93,7 +93,7 @@ public final class Settings {
|
|||||||
getMailSubject, getMailText, getMySQLlastlocWorld, defaultWorld,
|
getMailSubject, getMailText, getMySQLlastlocWorld, defaultWorld,
|
||||||
getPhpbbPrefix, getWordPressPrefix, getMySQLColumnLogged,
|
getPhpbbPrefix, getWordPressPrefix, getMySQLColumnLogged,
|
||||||
spawnPriority, crazyloginFileName, getPassRegex,
|
spawnPriority, crazyloginFileName, getPassRegex,
|
||||||
getMySQLColumnRealName;
|
getMySQLColumnRealName, emailOauth2Token;
|
||||||
public static int getWarnMessageInterval, getSessionTimeout,
|
public static int getWarnMessageInterval, getSessionTimeout,
|
||||||
getRegistrationTimeout, getMaxNickLength, getMinNickLength,
|
getRegistrationTimeout, getMaxNickLength, getMinNickLength,
|
||||||
getPasswordMinLen, getMovementRadius, getmaxRegPerIp,
|
getPasswordMinLen, getMovementRadius, getmaxRegPerIp,
|
||||||
@ -302,6 +302,7 @@ public final class Settings {
|
|||||||
generateImage = configFile.getBoolean("Email.generateImage", false);
|
generateImage = configFile.getBoolean("Email.generateImage", false);
|
||||||
preventOtherCase = configFile.getBoolean("settings.preventOtherCase", false);
|
preventOtherCase = configFile.getBoolean("settings.preventOtherCase", false);
|
||||||
kickPlayersBeforeStoping = configFile.getBoolean("Security.stop.kickPlayersBeforeStoping", true);
|
kickPlayersBeforeStoping = configFile.getBoolean("Security.stop.kickPlayersBeforeStoping", true);
|
||||||
|
emailOauth2Token = configFile.getString("Email.emailOauth2Token", "");
|
||||||
|
|
||||||
// Load the welcome message
|
// Load the welcome message
|
||||||
getWelcomeMessage();
|
getWelcomeMessage();
|
||||||
@ -734,6 +735,9 @@ public final class Settings {
|
|||||||
changes = true;
|
changes = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!contains("Email.emailOauth2Token"))
|
||||||
|
set("Email.emailOauth2Token", "");
|
||||||
|
|
||||||
if (changes) {
|
if (changes) {
|
||||||
plugin.getLogger().warning("Merged new Config Options - I'm not an error, please don't report me");
|
plugin.getLogger().warning("Merged new Config Options - I'm not an error, please don't report me");
|
||||||
plugin.getLogger().warning("Please check your config.yml file for new configs!");
|
plugin.getLogger().warning("Please check your config.yml file for new configs!");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user