-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSharePointClient.java
More file actions
executable file
·223 lines (196 loc) · 9.64 KB
/
Copy pathSharePointClient.java
File metadata and controls
executable file
·223 lines (196 loc) · 9.64 KB
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
package connector;
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @author Carlos Suarez Fontalvo Creating a client for Sharepoint Online.!
* following source: https://github.com/lstak/node-sharepoint following article:
* http://allthatjs.com/2012/03/28/remote-authentication-in-sharepoint-online/
* following article: http://allthatjs.com/2012/03/29/node-js-meet-sharepoint/
* following article: https://gist.github.com/2272889
*/
public class SharePointClient {
//information for signin
private String _tokenSPO;
private String userName;
private String password;
private String SSLendPoint;
//Cookie with final signin information
private String cookieNedToken;
//Location of SAM.xml template
private static final String _samFileLocation;
private static final Logger _log;
static {
_samFileLocation = Path.of(System.getProperty("user.dir"), "src", "META-INF", "SAML.xml").toString();
_log = Logger.getLogger(SharePointClient.class.getName());
_log.log(Level.INFO, "Creating Log Service for {0}", SharePointClient.class.getName());
}
/**
* Default constructor for the SharePoint Client. Uses the Microsoft Online
* STS ({@link _Constants#EXTSTS_SRF_URL}) for claims-based authentication,
* which is the standard endpoint for SharePoint Online (Office 365).
*
* @param userName string with username, [email protected]
* @param password string with the password for the username submitted
* @param endPoint string with the target to prepare de SAML file that is
* going to be sent to the STS (Security Token Service).
*/
public SharePointClient(String userName, String password, String endPoint) throws Exception {
this(userName, password, endPoint, _Constants.EXTSTS_SRF_URL);
}
/**
* Constructor for the SharePoint Client with a custom STS URL. Use this
* overload when connecting to a non-Office 365 environment (e.g. on-premises
* SharePoint with ADFS or a custom Security Token Service).
*
* @param userName string with username
* @param password string with the password for the username submitted
* @param endPoint string with the target SharePoint host (without protocol),
* used to build the login endpoint and the SAML token request.
* @param stsUrl the full URL of the Security Token Service (STS) that will
* validate the SAML request and issue the binary security token.
*/
public SharePointClient(String userName, String password, String endPoint, String stsUrl) throws Exception {
this._tokenSPO = stsUrl;
this.SSLendPoint = _Constants.DEFAULT_SSL_PROTOCOL + endPoint + _Constants.DEFAULT_LOGIN_PATH;
this.userName = userName;
this.password = password;
this.signin();
}
/**
* This method Send SAML Request to STS (Security Token Service) The
* application POSTs an SAML Request Security Token message to the Microsoft
* Online STS, located at the {@link #_tokenSPO}. It uses the already
* formatted SAML.xml file.
*
* @param SAMLFile the content of the XML file with the initial structure
* @return the securiy token, null if SAMLFile is malformed or STS is down.
* @throws MalformedURLException
* @throws IOException
*/
private String firstPartSignin(String samlContent) throws MalformedURLException, IOException {
URLConnection connection = new URL(this._tokenSPO).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Accept-Charset", StandardCharsets.UTF_8.name());
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + StandardCharsets.UTF_8.name());
connection.setRequestProperty("Content-Length", String.valueOf(samlContent.length()));
try (OutputStream output = connection.getOutputStream()) {
output.write(samlContent.getBytes(StandardCharsets.UTF_8));
} catch (IOException ex) {
throw new IOException(ex.getMessage(), ex);
}
//Printing the request generated by the Security Token Service (STS) and
//Getting the token t=...
String tokenT = null;
try (BufferedReader resBuf = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
String oString;
while ((oString = resBuf.readLine()) != null) {
int startTag = oString.indexOf("<wsse:BinarySecurityToken Id=\"Compact0\">");
int endIndex = oString.indexOf("</wsse:BinarySecurityToken>");
if (startTag != -1 && endIndex != -1) {
int beginIndex = startTag + ("<wsse:BinarySecurityToken Id=\"Compact0\">").length();
tokenT = oString.substring(beginIndex, endIndex);
_log.log(Level.CONFIG, tokenT);
}
}
}
return tokenT;
}
/**
* This method sends the generated security token from the STS to the SPO
* (SharePoint Online). {@link #SSLendPoint} Its includes a User-Agent
* header to accomplish this task.
*
* @see connector._Constants.DEFAULT_USER_AGENT_WINDOWS for default
* User-Agent
* @param STSToken the security token previosly generated
* @return connection with the cookies: FedAuth and rtFa
* @throws MalformedURLException
* @throws ProtocolException
* @throws IOException
*/
private HttpURLConnection secondPartSignin(String STSToken) throws MalformedURLException, ProtocolException, IOException {
HttpURLConnection connection = (HttpURLConnection) new URL(this.SSLendPoint).openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("User-Agent", _Constants.DEFAULT_USER_AGENT_WINDOWS);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", STSToken.length() + "");
// Necesary, URLConnection class doesn't support auto-redirect disabling.
// @see: http://stackoverflow.com/questions/2659000/java-how-to-find-the-redirected-url-of-a-url for more information.
// Tnx to Srinivas for pointing me in this direction.
connection.setInstanceFollowRedirects(false);
connection.setDoOutput(true);
try (OutputStream output = connection.getOutputStream()) {
output.write(STSToken.getBytes(StandardCharsets.UTF_8));
} catch (IOException ex) {
throw new IOException(ex.getMessage(), ex);
}
return connection;
}
/**
* This method will generate a String with both FedAuth and rtFa cookie
* values.
*
* @param connection object with cookies embbeded.
* @return string with the both cookies values.
* @throws Exception if connection object has invalid cookies format.
*/
private String getCookieNedToken(HttpURLConnection connection) throws Exception {
String _cookieNedToken = null;
List<String> cookies = connection.getHeaderFields().get("Set-Cookie");
String FedAuthCookie = null;
String rtFaCookie = null;
//Printing Authentication cookies
for (String str : cookies) {
if (str.contains("FedAuth")) {
FedAuthCookie = str.split(" ")[0];
_log.log(Level.CONFIG, FedAuthCookie);
}
if (str.contains("rtFa")) {
rtFaCookie = str.split(" ")[0];
_log.log(Level.CONFIG, rtFaCookie);
}
}
if (FedAuthCookie == null || rtFaCookie == null) {
throw new Exception("Invalid CookieNed Token!!!");
} else {
_cookieNedToken = FedAuthCookie + " " + rtFaCookie;
_log.log(Level.CONFIG, "CookieNed Token {0}: ", _cookieNedToken);
//cookieNedToken.addRequestProperty("Cookie", FedAuthCookie + " " + rtFaCookie);
}
return _cookieNedToken;
}
public String getCookieNedToken() {
return this.cookieNedToken;
}
/**
* This method will sign in the user into (SPO) SharePoint Online using
* Claims-Based authentication.
*
* @throws Exception
*/
private void signin() throws Exception {
_log.log(Level.CONFIG, "SAML Template location at: {0}", _samFileLocation);
try {
//Read the SAML template and substitute placeholders
String samlContent = Files.readString(Path.of(_samFileLocation), StandardCharsets.UTF_8)
.replace("[username]", this.userName)
.replace("[password]", this.password)
.replace("[endpoint]", this.SSLendPoint);
//Executing the first part of the signin process
String tokenT = firstPartSignin(samlContent);
//Executing the second part of the signin process
HttpURLConnection connection = secondPartSignin(tokenT);
//Asigning final Token to variable
this.cookieNedToken = getCookieNedToken(connection);
_log.log(Level.CONFIG, "Username {0} successfully logged in. \nCookieNed value is: {1}", new Object[]{this.userName, this.cookieNedToken});
} catch (IOException ex) {
throw new Exception(ex.getMessage(), ex.getCause());
}
}
}