Recently, there was a need 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 wrote a Java implementation.
The implementation method is very simple, but it requires some additional packages, most importantly Apache Commons Codec and Okhttp.
Apache Commons Codec is used to generate digital signatures, and Okhttp is used to send Http Post requests.
Setting Related Parameters
There are 4 parameters that need to be obtained in advance.
For how to obtain the following 4 parameters, please refer to the article: Discourse User Data Synchronization Using DiscourseConnect
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:
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
After obtaining the URL string above, we have 2 more steps to do.
The first step is to Base64 encode the obtained URL.
The second step is to digitally sign the obtained Base64 string. 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 to participate 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.
Similar to the data structure below, and then use it as Post parameter data:
{
"sso": "P2V4dGVybmFsX2lkPTEmZW1haWw9aW5mbyU0MHZpc2Fmbi5jb20mdXNlcm5hbWU9aW5mby52aXNhZm4mcmVxdWlyZV9hY3RpdmF0aW9uPXRydWU=",
"sig": "403a205a004e37ffab2bf77cc12b2eac352d71820983706d86984eec9821a0c4"
}
Sending POST Request
Any tool that supports HTTP can be used.
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 problems, the code above can complete the SSO data synchronization call.