You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
5.5 KiB
181 lines
5.5 KiB
var _ = require("underscore");
|
|
var util = require('util');
|
|
var req = require('request').defaults({
|
|
strictSSL: false
|
|
});
|
|
|
|
var config = {};
|
|
|
|
function sso_init() {
|
|
var failed = false;
|
|
_.each(['SSO_REALM', 'SSO_HOSTNAME', 'SSO_CLIENT_ID', 'SSO_SERVICE_USERNAME', 'SSO_SERVICE_PASSWORD'], (item) => {
|
|
if ((item in process.env) && (process.env[item] != null)) {
|
|
config[item] = process.env[item];
|
|
} else {
|
|
console.log("ERROR: Environment variable '%s' is missing or empty.", item);
|
|
failed = true;
|
|
}
|
|
});
|
|
|
|
if (failed) {
|
|
throw new Error("Missing configuration");
|
|
}
|
|
}
|
|
|
|
function sso_register(types) {
|
|
return [ "application" ];
|
|
}
|
|
|
|
function sso_handle(action, type, app, next) {
|
|
if (type == "application") {
|
|
handle_application(action, type, app, next);
|
|
}
|
|
}
|
|
|
|
exports.handle = sso_handle;
|
|
exports.register = sso_register;
|
|
exports.init = sso_init;
|
|
|
|
|
|
function handle_application(action, type, app, next) {
|
|
var client = {
|
|
clientId: app.application_id,
|
|
clientAuthenticatorType: "client-secret",
|
|
secret: app.keys.key,
|
|
redirectUris: [ app.redirect_url ],
|
|
publicClient: false,
|
|
name: app.name,
|
|
description: app.description
|
|
};
|
|
|
|
authenticate_to_sso(next, (access_token) => {
|
|
get_sso_client(client.clientId, access_token, next, (sso_client) => {
|
|
if (sso_client == null) {
|
|
console.log("Could not find a client, creating it...");
|
|
create_sso_client(access_token, client, (response) => {
|
|
console.log("OK, client created !")
|
|
next('SUCCESS');
|
|
});
|
|
} else {
|
|
console.log("Found an existing client with id = %s", sso_client.id);
|
|
update_sso_client(access_token, client, sso_client.id, next, (response) => {
|
|
console.log("OK, client updated !");
|
|
next('SUCCESS');
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
|
|
function get_sso_client(client_id, access_token, error, next) {
|
|
req.get({
|
|
url: util.format("https://%s/auth/admin/realms/%s/clients", config.SSO_HOSTNAME, config.SSO_REALM),
|
|
headers: {
|
|
"Authorization": "Bearer " + access_token
|
|
},
|
|
qs: {
|
|
clientId: client_id
|
|
}
|
|
}, (err, response, body) => {
|
|
if (err) {
|
|
return error(err);
|
|
}
|
|
console.log("Got a %d response from SSO", response.statusCode);
|
|
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
var json_response = JSON.parse(body);
|
|
var sso_client = null;
|
|
console.log("Found %d clients", json_response.length);
|
|
if (json_response.length == 1) {
|
|
sso_client = json_response[0];
|
|
console.log("Picking the first one : '%s', with id = %s", sso_client.clientId, sso_client.id);
|
|
} else if (json_response.length > 1) {
|
|
console.log("Too many matching clients (%d). Refusing to do anything.", json_response.length);
|
|
return error(util.format("Too many matching clients (%d). Refusing to do anything.", json_response.length));
|
|
}
|
|
next(sso_client);
|
|
} catch (err) {
|
|
return error(err);
|
|
}
|
|
} else {
|
|
return error(util.format("Got a %d response from SSO while trying to check if client exists", response.statusCode));
|
|
}
|
|
});
|
|
}
|
|
|
|
function create_sso_client(access_token, client, error, next) {
|
|
req.post(util.format("https://%s/auth/admin/realms/%s/clients", config.SSO_HOSTNAME, config.SSO_REALM), {
|
|
headers: {
|
|
"Authorization": "Bearer " + access_token
|
|
},
|
|
json: client
|
|
}, (err, response, body) => {
|
|
if (err) {
|
|
return error(err);
|
|
}
|
|
console.log("Got a %d response from SSO", response.statusCode);
|
|
if (response.statusCode == 201) {
|
|
try {
|
|
var client = JSON.parse(body);
|
|
next(client);
|
|
} catch (err) {
|
|
return error(err);
|
|
}
|
|
} else {
|
|
return error(util.format("Got a %d response from SSO while creating client", response.statusCode));
|
|
}
|
|
});
|
|
}
|
|
|
|
function update_sso_client(access_token, client, id, error, next) {
|
|
req.put(util.format("https://%s/auth/admin/realms/%s/clients/%s", config.SSO_HOSTNAME, config.SSO_REALM, id), {
|
|
headers: {
|
|
"Authorization": "Bearer " + access_token
|
|
},
|
|
json: client
|
|
}, (err, response, body) => {
|
|
if (err) {
|
|
return error(err);
|
|
}
|
|
console.log("Got a %d response from SSO", response.statusCode);
|
|
if (response.statusCode == 204) {
|
|
try {
|
|
next();
|
|
} catch (err) {
|
|
return error(err);
|
|
}
|
|
} else {
|
|
return error(util.format("Got a %d response from SSO while updating client", response.statusCode));
|
|
}
|
|
});
|
|
}
|
|
|
|
function authenticate_to_sso(error, next) {
|
|
console.log("Authenticating to SSO (realm = '%s') using the ROPC OAuth flow with %s/%s", config.SSO_REALM, config.SSO_SERVICE_USERNAME, config.SSO_SERVICE_PASSWORD);
|
|
req.post(util.format("https://%s/auth/realms/%s/protocol/openid-connect/token", config.SSO_HOSTNAME, config.SSO_REALM), {
|
|
form: {
|
|
grant_type: "password",
|
|
client_id: config.SSO_CLIENT_ID,
|
|
username: config.SSO_SERVICE_USERNAME,
|
|
password: config.SSO_SERVICE_PASSWORD
|
|
}
|
|
}, (err, response, body) => {
|
|
if (err) {
|
|
return error(err);
|
|
}
|
|
console.log("Got a %d response from SSO", response.statusCode);
|
|
if (response.statusCode == 200) {
|
|
try {
|
|
var json_response = JSON.parse(body);
|
|
console.log("Got an access token from SSO: %s", json_response.access_token);
|
|
next(json_response.access_token);
|
|
} catch (err) {
|
|
return error(err);
|
|
}
|
|
} else {
|
|
return error(util.format("Got a %d response from SSO while authenticating", response.statusCode));
|
|
}
|
|
});
|
|
}
|
|
|