3 changed files with 334 additions and 162 deletions
@ -0,0 +1,17 @@ |
|||||
|
function log_init() { |
||||
|
// Nothing to do
|
||||
|
} |
||||
|
|
||||
|
function log_register(types) { |
||||
|
return types; // We register for all types
|
||||
|
} |
||||
|
|
||||
|
function log_handle(action, type, app, next) { |
||||
|
console.log("--> WEBHOOK: action = '%s', type = '%s'", action, type); |
||||
|
console.log(app); |
||||
|
next('SUCCESS'); |
||||
|
} |
||||
|
|
||||
|
exports.handle = log_handle; |
||||
|
exports.register = log_register; |
||||
|
exports.init = log_init; |
||||
@ -0,0 +1,181 @@ |
|||||
|
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)); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
Loading…
Reference in new issue