1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package davmail.exchange.auth;
21
22 import davmail.BundleMessage;
23 import davmail.Settings;
24 import davmail.exception.DavMailAuthenticationException;
25 import davmail.exception.DavMailException;
26 import davmail.exchange.ews.BaseShape;
27 import davmail.exchange.ews.DistinguishedFolderId;
28 import davmail.exchange.ews.GetFolderMethod;
29 import davmail.exchange.ews.GetUserConfigurationMethod;
30 import davmail.http.HttpClientAdapter;
31 import org.apache.http.client.methods.CloseableHttpResponse;
32 import org.apache.log4j.Logger;
33
34 import javax.swing.*;
35 import java.awt.*;
36 import java.io.BufferedReader;
37 import java.io.IOException;
38 import java.io.InputStreamReader;
39 import java.lang.reflect.InvocationTargetException;
40 import java.net.URI;
41
42 public class O365ManualAuthenticator implements ExchangeAuthenticator {
43
44 private static final Logger LOGGER = Logger.getLogger(O365ManualAuthenticator.class);
45
46 String errorCode = null;
47 String code = null;
48
49 URI ewsUrl = URI.create(Settings.getO365Url());
50
51 private O365ManualAuthenticatorDialog o365ManualAuthenticatorDialog;
52
53 private String username;
54 private String password;
55 private O365Token token;
56
57 public O365Token getToken() {
58 return token;
59 }
60
61 @Override
62 public URI getExchangeUri() {
63 return ewsUrl;
64 }
65
66 public String getUsername() {
67 return username;
68 }
69
70 public void setUsername(String username) {
71 this.username = username;
72 }
73
74 public void setPassword(String password) {
75 this.password = password;
76 }
77
78
79
80
81
82 @Override
83 public HttpClientAdapter getHttpClientAdapter() {
84 return new HttpClientAdapter(getExchangeUri(), username, password, true);
85 }
86
87 public void authenticate() throws IOException {
88
89 final String clientId = Settings.getProperty("davmail.oauth.clientId", "facd6cff-a294-4415-b59f-c5b01937d7bd");
90
91 final String redirectUri = Settings.getProperty("davmail.oauth.redirectUri", Settings.O365_LOGIN_URL+"common/oauth2/nativeclient");
92
93 String tenantId = Settings.getProperty("davmail.oauth.tenantId", "common");
94
95
96 token = O365Token.load(tenantId, clientId, redirectUri, username, password);
97 if (token != null) {
98 return;
99 }
100
101 final String initUrl = O365Authenticator.buildAuthorizeUrl(tenantId, clientId, redirectUri, username);
102
103 if (Settings.getBooleanProperty("davmail.server") || GraphicsEnvironment.isHeadless()) {
104
105 code = getCodeFromConsole(initUrl);
106 } else {
107 try {
108 SwingUtilities.invokeAndWait(() -> o365ManualAuthenticatorDialog = new O365ManualAuthenticatorDialog(initUrl));
109 } catch (InterruptedException e) {
110 Thread.currentThread().interrupt();
111 } catch (InvocationTargetException e) {
112 throw new IOException(e);
113 }
114 code = o365ManualAuthenticatorDialog.getCode();
115 }
116
117 if (code == null) {
118 LOGGER.error("Authentication failed, code not available");
119 throw new DavMailException("EXCEPTION_AUTHENTICATION_FAILED_REASON", errorCode);
120 }
121
122 token = O365Token.build(tenantId, clientId, redirectUri, code, password);
123
124 LOGGER.debug("Authenticated username: " + token.getUsername());
125 if (username != null && !username.isEmpty() && !username.equalsIgnoreCase(token.getUsername())) {
126 throw new DavMailAuthenticationException("Authenticated username " + token.getUsername() + " does not match " + username);
127 }
128
129 }
130
131 private String getCodeFromConsole(String initUrl) {
132 BufferedReader inReader = new BufferedReader(new InputStreamReader(System.in));
133 StringBuilder buffer = new StringBuilder();
134 buffer.append(BundleMessage.format("UI_0365_AUTHENTICATION_PROMPT_CONSOLE", initUrl)).append("\n")
135 .append(BundleMessage.format("UI_0365_AUTHENTICATION_CODE"));
136 try {
137 System.out.print(buffer.toString());
138 code = inReader.readLine();
139 if (code != null && code.contains("code=") && code.contains("&session_state=")) {
140 code = code.substring(code.indexOf("code=")+5, code.indexOf("&session_state="));
141 }
142 } catch (IOException e) {
143 System.err.println(e + " " + e.getMessage());
144 }
145 return code;
146 }
147
148 public static void main(String[] argv) {
149 try {
150 Settings.setDefaultSettings();
151 Settings.setProperty("davmail.server", "false");
152
153
154 O365ManualAuthenticator authenticator = new O365ManualAuthenticator();
155 authenticator.setUsername("");
156 authenticator.authenticate();
157
158
159 HttpClientAdapter httpClientAdapter = new HttpClientAdapter(authenticator.getExchangeUri(), true);
160
161 GetFolderMethod checkMethod = new GetFolderMethod(BaseShape.ID_ONLY, DistinguishedFolderId.getInstance(null, DistinguishedFolderId.Name.root), null);
162 checkMethod.setHeader("Authorization", "Bearer " + authenticator.getToken().getAccessToken());
163 try (
164 CloseableHttpResponse response = httpClientAdapter.execute(checkMethod)
165 ) {
166 checkMethod.handleResponse(response);
167 checkMethod.checkSuccess();
168 }
169 System.out.println("Retrieved folder id " + checkMethod.getResponseItem().get("FolderId"));
170
171
172 int i = 0;
173 while (i++ < 12 * 60 * 2) {
174 GetUserConfigurationMethod getUserConfigurationMethod = new GetUserConfigurationMethod();
175 getUserConfigurationMethod.setHeader("Authorization", "Bearer " + authenticator.getToken().getAccessToken());
176 try (
177 CloseableHttpResponse response = httpClientAdapter.execute(checkMethod)
178 ) {
179 checkMethod.handleResponse(response);
180
181 checkMethod.checkSuccess();
182 }
183 System.out.println(getUserConfigurationMethod.getResponseItem());
184
185 Thread.sleep(5000);
186 }
187
188 } catch (InterruptedException e) {
189 LOGGER.warn("Thread interrupted", e);
190 Thread.currentThread().interrupt();
191 } catch (Exception e) {
192 LOGGER.error(e + " " + e.getMessage(), e);
193 }
194 System.exit(0);
195 }
196 }