In recent times, there has been a requirement to synchronize existing users to Discourse using SSO.
Therefore, based on the official PHP implementation (Sync DiscourseConnect user data with the sync_sso route - developers - Discourse Meta), I have created a Java implementation.
The implementation method is simple, but it requires some additional packages, most importantly Apache Commons Codec and Okhttp.
Apache Commons Codec is used for generating digital signatures, and Okhttp is used for sending Http Post requests.
Setting Related Parameters
There are 4 parameters that need to be obtained in advance.
For information on how to obtain the following 4 parameters, please refer to the article: Discourse Uses DiscourseConnect for User Data Synchronization
const apiKey = '4fe83002bb5fba8c9a61a65e5b4b0a3cf8233b0e4ccafc85ebd6607abab4651a';
const apiUser = 'system';
const connectSecret = 'jdhb19*Xh3!nu(#k';
Setting SSO Parameters
The parameter settings refer to the parameter settings of the URL Get method.
Our Java code is as follows:
URIBuilder builder = new URIBuilder();
builder.addParameter("external_id", "1");
builder.addParameter("email", "info@isharkfly.com");
builder.addParameter("username", "info.visafn.sso");
builder.addParameter("add_groups", "bar");
builder.addParameter("require_activation", "false");
url = StringUtils.removeStart(builder.build().toString(),"?");
System.out.println(StringUtils.removeStart(url, "?"));
Base64 and Digital Signature
Once you have the URL string from above, there are 2 steps to follow.
The first step is to Base64 encode the obtained URL.
The second step is to digitally sign the Base64 string obtained after the first step. The HMAC_SHA_256 algorithm is used for signing.
At the same time, the key obtained in the first step needs to be used as a parameter in the calculation along with the algorithm.
String sso= "admin/users/sync_sso";
String sig= new HmacUtils(HmacAlgorithms.HMAC_SHA_256, "55619458534897").hmacHex(ssoPayload);
After obtaining the above 2 values, reconstruct a JSON data structure.
A data structure similar to the one below should be used as the Post parameter data:
{
"sso": "P2V4dGVybmFsX2lkPTEmZW1haWw9aW5mbyU0MHZpc2Fmbi5jb20mdXNlcm5hbWU9aW5mby52aXNhZm4mcmVxdWlyZV9hY3RpdmF0aW9uPXRydWU=",
"sig": "403a205a004e37ffab2bf77cc12b2eac352d71820983706d86984eec9821a0c4"
}
Sending POST Request
You can use any tool that supports HTTP.
OkHttp is commonly used in Java now, so we will use OkHttp to send the request.
private OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(
MediaType.parse("application/json"), objectMapper.writeValueAsString(syncSSO));
Response response = client.newCall(postRequest(path, body)).execute();
The postRequest above is a method where we construct the request using the existing parameters.
The method is written as follows:
public Request postRequest(String path, RequestBody body) {
HttpUrl.Builder urlBuilder = HttpUrl.parse(site_url + path).newBuilder();
Request request = new Request.Builder().url(urlBuilder.build().toString())
.addHeader("api-username", api_username)
.addHeader("api-key", api_key)
.post(body)
.build();
return request;
}
If there are no issues, the code above should successfully complete the SSO data synchronization call.