[mod] oidc!!!
This commit is contained in:
parent
1087573529
commit
048d7570d1
16 changed files with 979 additions and 75 deletions
|
@ -1,9 +1,26 @@
|
||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"log": [
|
"log": [
|
||||||
{"kind": "stdout", "data": {"threshold": "info"}}
|
{
|
||||||
|
"kind": "stdout",
|
||||||
|
"data": {
|
||||||
|
"threshold": "info"
|
||||||
|
}
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"session_management": {
|
"session_management": {
|
||||||
"in_memory": false
|
"in_memory": false
|
||||||
|
},
|
||||||
|
"authentication": {
|
||||||
|
"kind": "oidc",
|
||||||
|
"data": {
|
||||||
|
"url_authorization": "https://authelia.linke.sx/api/oidc/authorization",
|
||||||
|
"url_token": "https://authelia.linke.sx/api/oidc/token",
|
||||||
|
"url_userinfo": "https://authelia.linke.sx/api/oidc/userinfo",
|
||||||
|
"client_id": "zeitbild",
|
||||||
|
"client_secret": "cee00b08a818db87e17e703273818e5194f83280e1ef3eae9214ff14675d9e6d",
|
||||||
|
"backend_url_base": "https://zeitbild.linke.sx",
|
||||||
|
"label": "linke.sx"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
172
lib/plankton/plankton.d.ts
vendored
172
lib/plankton/plankton.d.ts
vendored
|
@ -3759,17 +3759,17 @@ declare namespace lib_plankton.rest {
|
||||||
*/
|
*/
|
||||||
type type_operation<type_input, type_output> = {
|
type type_operation<type_input, type_output> = {
|
||||||
action_name: string;
|
action_name: string;
|
||||||
query_parameters: Array<{
|
query_parameters: ((version: string) => Array<{
|
||||||
name: string;
|
name: string;
|
||||||
description: (null | string);
|
description: (null | string);
|
||||||
required: boolean;
|
required: boolean;
|
||||||
}>;
|
}>);
|
||||||
|
input_schema: ((version: (null | string)) => type_oas_schema);
|
||||||
|
output_schema: ((version: (null | string)) => type_oas_schema);
|
||||||
request_body_mimetype: string;
|
request_body_mimetype: string;
|
||||||
request_body_decode: ((http_request_body: Buffer, http_request_header_content_type: (null | string)) => any);
|
request_body_decode: ((http_request_body: Buffer, http_request_header_content_type: (null | string)) => any);
|
||||||
response_body_mimetype: string;
|
response_body_mimetype: string;
|
||||||
response_body_encode: ((output: any) => Buffer);
|
response_body_encode: ((output: any) => Buffer);
|
||||||
input_schema: ((version: (null | string)) => type_oas_schema);
|
|
||||||
output_schema: ((version: (null | string)) => type_oas_schema);
|
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
@ -3838,11 +3838,11 @@ declare namespace lib_plankton.rest {
|
||||||
execution?: type_execution<any, any>;
|
execution?: type_execution<any, any>;
|
||||||
title?: (null | string);
|
title?: (null | string);
|
||||||
description?: (null | string);
|
description?: (null | string);
|
||||||
query_parameters?: Array<{
|
query_parameters?: ((version: string) => Array<{
|
||||||
name: string;
|
name: string;
|
||||||
description: (null | string);
|
description: (null | string);
|
||||||
required: boolean;
|
required: boolean;
|
||||||
}>;
|
}>);
|
||||||
input_schema?: ((version: string) => type_oas_schema);
|
input_schema?: ((version: string) => type_oas_schema);
|
||||||
output_schema?: ((version: string) => type_oas_schema);
|
output_schema?: ((version: string) => type_oas_schema);
|
||||||
request_body_mimetype?: string;
|
request_body_mimetype?: string;
|
||||||
|
@ -3860,11 +3860,11 @@ declare namespace lib_plankton.rest {
|
||||||
execution?: type_execution<type_input, type_output>;
|
execution?: type_execution<type_input, type_output>;
|
||||||
title?: (null | string);
|
title?: (null | string);
|
||||||
description?: (null | string);
|
description?: (null | string);
|
||||||
query_parameters?: Array<{
|
query_parameters?: ((version: string) => Array<{
|
||||||
name: string;
|
name: string;
|
||||||
description: (null | string);
|
description: (null | string);
|
||||||
required: boolean;
|
required: boolean;
|
||||||
}>;
|
}>);
|
||||||
input_schema?: ((version: (null | string)) => type_oas_schema);
|
input_schema?: ((version: (null | string)) => type_oas_schema);
|
||||||
output_schema?: ((version: (null | string)) => type_oas_schema);
|
output_schema?: ((version: (null | string)) => type_oas_schema);
|
||||||
request_body_mimetype?: string;
|
request_body_mimetype?: string;
|
||||||
|
@ -4187,3 +4187,159 @@ declare namespace lib_plankton.bcrypt {
|
||||||
*/
|
*/
|
||||||
function compare(password_shall_image: string, password_is: string): Promise<boolean>;
|
function compare(password_shall_image: string, password_is: string): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
declare namespace lib_plankton.base64 {
|
||||||
|
/**
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
type type_source = string;
|
||||||
|
/**
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
type type_target = string;
|
||||||
|
/**
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
export function encode(source: type_source): type_target;
|
||||||
|
/**
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
export function decode(target: type_target): type_source;
|
||||||
|
/**
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
export function implementation_code(): lib_plankton.code.type_code<type_source, type_target>;
|
||||||
|
export {};
|
||||||
|
}
|
||||||
|
declare namespace lib_plankton.base64 {
|
||||||
|
/**
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
class class_base64 implements lib_plankton.code.interface_code<string, string> {
|
||||||
|
/**
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
constructor();
|
||||||
|
/**
|
||||||
|
* @implementation
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
encode(x: string): string;
|
||||||
|
/**
|
||||||
|
* @implementation
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
decode(x: string): string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declare namespace lib_plankton.auth {
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
type type_auth<type_preparation, type_execute_input, type_control_input> = {
|
||||||
|
login_prepare: (() => Promise<type_preparation>);
|
||||||
|
login_execute: ((input: type_execute_input) => Promise<string>);
|
||||||
|
login_control: ((input: type_control_input) => Promise<void>);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
declare namespace lib_plankton.auth {
|
||||||
|
}
|
||||||
|
declare namespace lib_plankton.auth.internal {
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
type type_parameters = {
|
||||||
|
password_image_chest: lib_plankton.storage.type_chest<string, string, void, string, string>;
|
||||||
|
check_password: ((image: string, input: string) => Promise<boolean>);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
type type_preparation = null;
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
type type_execute_input = {
|
||||||
|
name: string;
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
type type_control_input = void;
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export function implementation_auth(parameters: type_parameters): type_auth<type_preparation, type_execute_input, type_control_input>;
|
||||||
|
export {};
|
||||||
|
}
|
||||||
|
declare namespace lib_plankton.auth.oidc {
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
enum enum_state_label {
|
||||||
|
idle = "idle",
|
||||||
|
wait = "wait",
|
||||||
|
ready = "ready"
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export type type_parameters_raw = {
|
||||||
|
url_authorization: string;
|
||||||
|
url_token: string;
|
||||||
|
url_userinfo: string;
|
||||||
|
client_id: string;
|
||||||
|
client_secret: string;
|
||||||
|
url_redirect: string;
|
||||||
|
scopes?: (null | Array<string>);
|
||||||
|
label?: string;
|
||||||
|
login_url_mode?: (null | ("log" | "open"));
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export type type_parameters = {
|
||||||
|
url_authorization: string;
|
||||||
|
url_token: string;
|
||||||
|
url_userinfo: string;
|
||||||
|
client_id: string;
|
||||||
|
client_secret: string;
|
||||||
|
url_redirect: string;
|
||||||
|
scopes: Array<string>;
|
||||||
|
label: string;
|
||||||
|
login_url_mode: ("log" | "open");
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
type type_preparation = {
|
||||||
|
url: string;
|
||||||
|
label: string;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
type type_execute_input = void;
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
type type_control_input = ({
|
||||||
|
kind: "authorization_callback";
|
||||||
|
data: {
|
||||||
|
stuff: Record<string, string>;
|
||||||
|
cookie: string;
|
||||||
|
};
|
||||||
|
} | {
|
||||||
|
kind: "token_callback";
|
||||||
|
data: {
|
||||||
|
http_request: lib_plankton.http.type_request;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export type type_subject = {
|
||||||
|
parameters: type_parameters;
|
||||||
|
state: {
|
||||||
|
id: string;
|
||||||
|
label: enum_state_label;
|
||||||
|
handlers: Array<{
|
||||||
|
resolve: ((result: string) => void);
|
||||||
|
reject: ((reason: Error) => void);
|
||||||
|
}>;
|
||||||
|
token: (null | string);
|
||||||
|
name: (null | string);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export function implementation_auth(parameters_raw: type_parameters_raw): type_auth<type_preparation, type_execute_input, type_control_input>;
|
||||||
|
export {};
|
||||||
|
}
|
||||||
|
|
|
@ -9069,7 +9069,7 @@ var lib_plankton;
|
||||||
// query
|
// query
|
||||||
{
|
{
|
||||||
if (url.query !== null) {
|
if (url.query !== null) {
|
||||||
result += ("?" + encodeURI(url.query));
|
result += ("?" + url.query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// hash
|
// hash
|
||||||
|
@ -12973,11 +12973,11 @@ var lib_plankton;
|
||||||
"active": ((version) => true),
|
"active": ((version) => true),
|
||||||
"execution": ((stuff) => Promise.resolve({ "status_code": 501, "data": null })),
|
"execution": ((stuff) => Promise.resolve({ "status_code": 501, "data": null })),
|
||||||
"restriction": ((stuff) => Promise.resolve(true)),
|
"restriction": ((stuff) => Promise.resolve(true)),
|
||||||
"input_schema": ((version) => ({})),
|
|
||||||
"output_schema": ((version) => ({})),
|
|
||||||
"title": null,
|
"title": null,
|
||||||
"description": null,
|
"description": null,
|
||||||
"query_parameters": [],
|
"query_parameters": ((version) => ([])),
|
||||||
|
"input_schema": ((version) => ({})),
|
||||||
|
"output_schema": ((version) => ({})),
|
||||||
"request_body_mimetype": "application/json",
|
"request_body_mimetype": "application/json",
|
||||||
"request_body_decode": ((http_request_body, http_request_header_content_type) => (((http_request_header_content_type !== null)
|
"request_body_decode": ((http_request_body, http_request_header_content_type) => (((http_request_header_content_type !== null)
|
||||||
&&
|
&&
|
||||||
|
@ -13382,7 +13382,7 @@ var lib_plankton;
|
||||||
})),
|
})),
|
||||||
]),
|
]),
|
||||||
// query parameters
|
// query parameters
|
||||||
operation.query_parameters.map((query_parameter) => ({
|
operation.query_parameters(options.version).map((query_parameter) => ({
|
||||||
"name": query_parameter.name,
|
"name": query_parameter.name,
|
||||||
"in": "query",
|
"in": "query",
|
||||||
"required": query_parameter.required,
|
"required": query_parameter.required,
|
||||||
|
@ -14559,3 +14559,496 @@ var lib_plankton;
|
||||||
bcrypt.compare = compare;
|
bcrypt.compare = compare;
|
||||||
})(bcrypt = lib_plankton.bcrypt || (lib_plankton.bcrypt = {}));
|
})(bcrypt = lib_plankton.bcrypt || (lib_plankton.bcrypt = {}));
|
||||||
})(lib_plankton || (lib_plankton = {}));
|
})(lib_plankton || (lib_plankton = {}));
|
||||||
|
/*
|
||||||
|
This file is part of »bacterio-plankton:base64«.
|
||||||
|
|
||||||
|
Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||||||
|
<info@greenscale.de>
|
||||||
|
|
||||||
|
»bacterio-plankton:base64« is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
»bacterio-plankton:base64« is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with »bacterio-plankton:base64«. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
var lib_plankton;
|
||||||
|
(function (lib_plankton) {
|
||||||
|
var base64;
|
||||||
|
(function (base64) {
|
||||||
|
/**
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
function encode(source) {
|
||||||
|
return Buffer.from(source, "utf-8").toString("base64");
|
||||||
|
}
|
||||||
|
base64.encode = encode;
|
||||||
|
/**
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
function decode(target) {
|
||||||
|
return Buffer.from(target, "base64").toString("utf-8");
|
||||||
|
}
|
||||||
|
base64.decode = decode;
|
||||||
|
/**
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
function implementation_code() {
|
||||||
|
return {
|
||||||
|
"encode": encode,
|
||||||
|
"decode": decode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
base64.implementation_code = implementation_code;
|
||||||
|
})(base64 = lib_plankton.base64 || (lib_plankton.base64 = {}));
|
||||||
|
})(lib_plankton || (lib_plankton = {}));
|
||||||
|
/*
|
||||||
|
This file is part of »bacterio-plankton:base64«.
|
||||||
|
|
||||||
|
Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||||||
|
<info@greenscale.de>
|
||||||
|
|
||||||
|
»bacterio-plankton:base64« is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
»bacterio-plankton:base64« is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with »bacterio-plankton:base64«. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
var lib_plankton;
|
||||||
|
(function (lib_plankton) {
|
||||||
|
var base64;
|
||||||
|
(function (base64) {
|
||||||
|
/**
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
class class_base64 {
|
||||||
|
/**
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @implementation
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
encode(x) {
|
||||||
|
return base64.encode(x);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @implementation
|
||||||
|
* @author fenris
|
||||||
|
*/
|
||||||
|
decode(x) {
|
||||||
|
return base64.decode(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base64.class_base64 = class_base64;
|
||||||
|
})(base64 = lib_plankton.base64 || (lib_plankton.base64 = {}));
|
||||||
|
})(lib_plankton || (lib_plankton = {}));
|
||||||
|
/*
|
||||||
|
This file is part of »bacterio-plankton:auth«.
|
||||||
|
|
||||||
|
Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||||||
|
<info@greenscale.de>
|
||||||
|
|
||||||
|
»bacterio-plankton:auth« is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
»bacterio-plankton:auth« is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with »bacterio-plankton:auth«. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
This file is part of »bacterio-plankton:auth«.
|
||||||
|
|
||||||
|
Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||||||
|
<info@greenscale.de>
|
||||||
|
|
||||||
|
»bacterio-plankton:auth« is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
»bacterio-plankton:auth« is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with »bacterio-plankton:auth«. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
This file is part of »bacterio-plankton:auth«.
|
||||||
|
|
||||||
|
Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||||||
|
<info@greenscale.de>
|
||||||
|
|
||||||
|
»bacterio-plankton:auth« is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
»bacterio-plankton:auth« is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with »bacterio-plankton:auth«. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
var lib_plankton;
|
||||||
|
(function (lib_plankton) {
|
||||||
|
var auth;
|
||||||
|
(function (auth) {
|
||||||
|
var internal;
|
||||||
|
(function (internal) {
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function make(parameters) {
|
||||||
|
return {
|
||||||
|
"parameters": parameters,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function login_prepare(subject) {
|
||||||
|
return Promise.resolve(null);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
async function login_execute(subject, input) {
|
||||||
|
let password_image;
|
||||||
|
try {
|
||||||
|
password_image = await subject.parameters.password_image_chest.read(input.name);
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
password_image = null;
|
||||||
|
}
|
||||||
|
if (password_image === null) {
|
||||||
|
return Promise.reject(new Error("user not found"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let valid;
|
||||||
|
try {
|
||||||
|
valid = await subject.parameters.check_password(password_image, input.password);
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
valid = null;
|
||||||
|
}
|
||||||
|
if (valid === null) {
|
||||||
|
return Promise.reject(new Error("password check failed"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!valid) {
|
||||||
|
return Promise.reject(new Error("wrong password"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Promise.resolve(input.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function login_control(subject, input) {
|
||||||
|
return Promise.reject(new Error("not available"));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function implementation_auth(parameters) {
|
||||||
|
const subject = make(parameters);
|
||||||
|
return {
|
||||||
|
"login_prepare": () => login_prepare(subject),
|
||||||
|
"login_execute": (input) => login_execute(subject, input),
|
||||||
|
"login_control": (input) => login_control(subject, input),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
internal.implementation_auth = implementation_auth;
|
||||||
|
})(internal = auth.internal || (auth.internal = {}));
|
||||||
|
})(auth = lib_plankton.auth || (lib_plankton.auth = {}));
|
||||||
|
})(lib_plankton || (lib_plankton = {}));
|
||||||
|
/*
|
||||||
|
This file is part of »bacterio-plankton:auth«.
|
||||||
|
|
||||||
|
Copyright 2016-2024 'Christian Fraß, Christian Neubauer, Martin Springwald GbR'
|
||||||
|
<info@greenscale.de>
|
||||||
|
|
||||||
|
»bacterio-plankton:auth« is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
»bacterio-plankton:auth« is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with »bacterio-plankton:auth«. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
var lib_plankton;
|
||||||
|
(function (lib_plankton) {
|
||||||
|
var auth;
|
||||||
|
(function (auth) {
|
||||||
|
var oidc;
|
||||||
|
(function (oidc) {
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
let enum_state_label;
|
||||||
|
(function (enum_state_label) {
|
||||||
|
enum_state_label["idle"] = "idle";
|
||||||
|
enum_state_label["wait"] = "wait";
|
||||||
|
enum_state_label["ready"] = "ready";
|
||||||
|
})(enum_state_label || (enum_state_label = {}));
|
||||||
|
;
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function make(parameters_raw) {
|
||||||
|
return {
|
||||||
|
"parameters": {
|
||||||
|
"url_authorization": parameters_raw.url_authorization,
|
||||||
|
"url_token": parameters_raw.url_token,
|
||||||
|
"url_userinfo": parameters_raw.url_userinfo,
|
||||||
|
"client_id": parameters_raw.client_id,
|
||||||
|
"client_secret": parameters_raw.client_secret,
|
||||||
|
"url_redirect": parameters_raw.url_redirect,
|
||||||
|
"scopes": (parameters_raw.scopes
|
||||||
|
??
|
||||||
|
["openid", "profile"]),
|
||||||
|
"label": (parameters_raw.label
|
||||||
|
??
|
||||||
|
"OIDC"),
|
||||||
|
"login_url_mode": (parameters_raw.login_url_mode
|
||||||
|
??
|
||||||
|
"log"),
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"id": lib_plankton.random.generate_guid(),
|
||||||
|
"label": enum_state_label.idle,
|
||||||
|
"handlers": [],
|
||||||
|
"token": null,
|
||||||
|
"name": null,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
|
||||||
|
* @todo save state for different requests/users?
|
||||||
|
*/
|
||||||
|
function login_prepare(subject) {
|
||||||
|
const url = lib_plankton.url.encode(Object.assign(lib_plankton.url.decode(subject.parameters.url_authorization), {
|
||||||
|
"query": lib_plankton.www_form.encode({
|
||||||
|
"response_type": "code",
|
||||||
|
"client_id": subject.parameters.client_id,
|
||||||
|
// "client_secret": subject.parameters.client_secret,
|
||||||
|
"scope": subject.parameters.scopes.join(" "),
|
||||||
|
"state": subject.state.id,
|
||||||
|
"redirect_uri": subject.parameters.url_redirect,
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
/*
|
||||||
|
switch (subject.parameters.login_url_mode) {
|
||||||
|
case "log": {
|
||||||
|
lib_plankton.log.info(
|
||||||
|
"auth_login_url",
|
||||||
|
{
|
||||||
|
"url": url,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "open": {
|
||||||
|
const nm_opn = require("opn");
|
||||||
|
nm_opn(url);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw (new Error("invalid login_url_mode: " + subject.parameters.login_url_mode));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return Promise.resolve({
|
||||||
|
"url": url,
|
||||||
|
"label": subject.parameters.label,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
|
||||||
|
*/
|
||||||
|
function login_execute(subject, input) {
|
||||||
|
switch (subject.state.label) {
|
||||||
|
case enum_state_label.idle: {
|
||||||
|
return (new Promise((resolve, reject) => {
|
||||||
|
subject.state = {
|
||||||
|
"id": subject.state.id,
|
||||||
|
"label": enum_state_label.wait,
|
||||||
|
"handlers": subject.state.handlers.concat([{ "resolve": resolve, "reject": reject }]),
|
||||||
|
"token": null,
|
||||||
|
"name": null,
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case enum_state_label.wait: {
|
||||||
|
return (new Promise((resolve, reject) => {
|
||||||
|
subject.state = {
|
||||||
|
"id": subject.state.id,
|
||||||
|
"label": enum_state_label.wait,
|
||||||
|
"handlers": subject.state.handlers.concat([{ "resolve": resolve, "reject": reject }]),
|
||||||
|
"token": null,
|
||||||
|
"name": null,
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case enum_state_label.ready: {
|
||||||
|
return Promise.resolve(subject.state.name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @see https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
|
||||||
|
* @see https://openid.net/specs/openid-connect-core-1_0.html#TokenRequest
|
||||||
|
* @see https://openid.net/specs/openid-connect-core-1_0.html#UserInfoRequest
|
||||||
|
* @todo authentication
|
||||||
|
*/
|
||||||
|
async function login_control(subject, input) {
|
||||||
|
switch (input.kind) {
|
||||||
|
default: {
|
||||||
|
throw (new Error("unhandled login control kind: " + input.kind));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "authorization_callback": {
|
||||||
|
lib_plankton.log.info("auth_authorization_callback_input", {
|
||||||
|
"input": input,
|
||||||
|
});
|
||||||
|
if ("error" in input.data.stuff) {
|
||||||
|
// query_parts["error"]
|
||||||
|
// query_parts["error_description"]
|
||||||
|
const handlers = subject.state.handlers;
|
||||||
|
subject.state = {
|
||||||
|
"id": subject.state.id,
|
||||||
|
"label": enum_state_label.idle,
|
||||||
|
"handlers": [],
|
||||||
|
"token": null,
|
||||||
|
"name": null,
|
||||||
|
};
|
||||||
|
handlers.forEach((handler) => {
|
||||||
|
handler.reject(new Error("failed"));
|
||||||
|
});
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const code = input.data.stuff["code"];
|
||||||
|
const cookie = input.data.cookie;
|
||||||
|
const token_url = lib_plankton.url.decode(subject.parameters.url_token);
|
||||||
|
const token_http_request = {
|
||||||
|
"version": "HTTP/2",
|
||||||
|
"scheme": ((token_url.scheme === "http") ? "http" : "https"),
|
||||||
|
"host": token_url.host,
|
||||||
|
"path": token_url.path,
|
||||||
|
"query": null,
|
||||||
|
"method": lib_plankton.http.enum_method.post,
|
||||||
|
"headers": {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
"Cookie": cookie,
|
||||||
|
"Authorization": lib_plankton.string.coin("Basic {{value}}", {
|
||||||
|
"value": lib_plankton.base64.encode(lib_plankton.string.coin("{{id}}:{{secret}}", {
|
||||||
|
"id": subject.parameters.client_id,
|
||||||
|
"secret": subject.parameters.client_secret,
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
"body": Buffer.from(lib_plankton.www_form.encode({
|
||||||
|
"grant_type": "authorization_code",
|
||||||
|
"code": code,
|
||||||
|
"redirect_uri": subject.parameters.url_redirect,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
lib_plankton.log.info("auth_token_request", {
|
||||||
|
"request": Object.assign(token_http_request, {
|
||||||
|
"body": token_http_request.body.toString(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const token_http_response = await lib_plankton.http.call(token_http_request);
|
||||||
|
lib_plankton.log.info("auth_token_response", {
|
||||||
|
"response": token_http_response,
|
||||||
|
});
|
||||||
|
const token_data = lib_plankton.json.decode(token_http_response.body.toString());
|
||||||
|
const token = token_data["access_token"];
|
||||||
|
const userinfo_url = lib_plankton.url.decode(subject.parameters.url_userinfo);
|
||||||
|
const userinfo_http_request = {
|
||||||
|
"version": "HTTP/2",
|
||||||
|
"scheme": ((userinfo_url.scheme === "http") ? "http" : "https"),
|
||||||
|
"host": userinfo_url.host,
|
||||||
|
"path": userinfo_url.path,
|
||||||
|
"query": null,
|
||||||
|
"method": lib_plankton.http.enum_method.get,
|
||||||
|
"headers": {
|
||||||
|
"Cookie": cookie,
|
||||||
|
"Authorization": ("Bearer " + token),
|
||||||
|
},
|
||||||
|
"body": null
|
||||||
|
};
|
||||||
|
lib_plankton.log.info("auth_userinfo_request", {
|
||||||
|
"request": userinfo_http_request,
|
||||||
|
});
|
||||||
|
const userinfo_http_response = await lib_plankton.http.call(userinfo_http_request);
|
||||||
|
lib_plankton.log.info("auth_userinfo_response", {
|
||||||
|
"response": userinfo_http_response,
|
||||||
|
});
|
||||||
|
const userinfo_data = lib_plankton.json.decode(userinfo_http_response.body.toString());
|
||||||
|
const name = userinfo_data["name"]; // TODO: requires "profile" in "scope"
|
||||||
|
lib_plankton.log.info("auth_oidc_name", { "value": name });
|
||||||
|
const handlers = subject.state.handlers;
|
||||||
|
subject.state = {
|
||||||
|
"id": subject.state.id,
|
||||||
|
"label": enum_state_label.ready,
|
||||||
|
"handlers": [],
|
||||||
|
"token": token,
|
||||||
|
"name": name,
|
||||||
|
};
|
||||||
|
handlers.forEach((handler) => {
|
||||||
|
handler.resolve(subject.state.name);
|
||||||
|
});
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
function implementation_auth(parameters_raw) {
|
||||||
|
const subject = make(parameters_raw);
|
||||||
|
return {
|
||||||
|
"login_prepare": () => login_prepare(subject),
|
||||||
|
"login_execute": (input) => login_execute(subject, input),
|
||||||
|
"login_control": (input) => login_control(subject, input),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
oidc.implementation_auth = implementation_auth;
|
||||||
|
})(oidc = auth.oidc || (auth.oidc = {}));
|
||||||
|
})(auth = lib_plankton.auth || (lib_plankton.auth = {}));
|
||||||
|
})(lib_plankton || (lib_plankton = {}));
|
||||||
|
|
|
@ -24,8 +24,8 @@ namespace _zeitbild.api
|
||||||
"/calendars",
|
"/calendars",
|
||||||
{
|
{
|
||||||
"description": "listet alle verfügbaren Kalender auf",
|
"description": "listet alle verfügbaren Kalender auf",
|
||||||
"query_parameters": [
|
"query_parameters": () => ([
|
||||||
],
|
]),
|
||||||
"output_schema": () => ({
|
"output_schema": () => ({
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace _zeitbild.api
|
||||||
"/events",
|
"/events",
|
||||||
{
|
{
|
||||||
"description": "stellt Veranstaltungen aus verschiedenen Kalendern zusammen",
|
"description": "stellt Veranstaltungen aus verschiedenen Kalendern zusammen",
|
||||||
"query_parameters": [
|
"query_parameters": () => ([
|
||||||
{
|
{
|
||||||
"name": "from",
|
"name": "from",
|
||||||
"required": true,
|
"required": true,
|
||||||
|
@ -47,7 +47,7 @@ namespace _zeitbild.api
|
||||||
"required": false,
|
"required": false,
|
||||||
"description": "comma separated",
|
"description": "comma separated",
|
||||||
},
|
},
|
||||||
],
|
]),
|
||||||
"output_schema": () => ({
|
"output_schema": () => ({
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
|
|
|
@ -8,33 +8,82 @@ namespace _zeitbild.api
|
||||||
rest_subject : lib_plankton.rest.type_rest
|
rest_subject : lib_plankton.rest.type_rest
|
||||||
) : void
|
) : void
|
||||||
{
|
{
|
||||||
register<null, null>(
|
register<
|
||||||
|
null,
|
||||||
|
string
|
||||||
|
>(
|
||||||
rest_subject,
|
rest_subject,
|
||||||
lib_plankton.http.enum_method.delete,
|
lib_plankton.http.enum_method.get,
|
||||||
"/session/oidc",
|
"/session/oidc",
|
||||||
{
|
{
|
||||||
"description": "verarbeitet einen OIDC login callback",
|
"description": "verarbeitet einen OIDC login callback",
|
||||||
|
"query_parameters": () => ([
|
||||||
|
{
|
||||||
|
"name": "code",
|
||||||
|
"required": true,
|
||||||
|
"description": null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "iss",
|
||||||
|
"required": true,
|
||||||
|
"description": null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "scope",
|
||||||
|
"required": true,
|
||||||
|
"description": null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "state",
|
||||||
|
"required": true,
|
||||||
|
"description": null,
|
||||||
|
},
|
||||||
|
]),
|
||||||
"input_schema": () => ({
|
"input_schema": () => ({
|
||||||
"type": "null",
|
"type": "null",
|
||||||
}),
|
}),
|
||||||
"output_schema": () => ({
|
"output_schema": () => ({
|
||||||
"type": "null",
|
"nullable": false,
|
||||||
|
"type": "string",
|
||||||
}),
|
}),
|
||||||
"restriction": restriction_logged_in,
|
"response_body_mimetype": "text/html",
|
||||||
|
"response_body_encode": (output => Buffer.from(output)),
|
||||||
|
"restriction": restriction_none,
|
||||||
"execution": async (stuff) => {
|
"execution": async (stuff) => {
|
||||||
// do NOT wait
|
|
||||||
_zeitbild.auth.control(
|
_zeitbild.auth.control(
|
||||||
{
|
{
|
||||||
"kind": "authorization_callback",
|
"kind": "authorization_callback",
|
||||||
"data": {
|
"data": {
|
||||||
"http_request": http_request
|
"stuff": stuff.query_parameters,
|
||||||
|
"cookie": (stuff.headers["Cookie"] ?? stuff.headers["cookie"]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return Promise.resolve({
|
return (
|
||||||
"status_code": 200,
|
_zeitbild.auth.execute(
|
||||||
"data": null,
|
undefined
|
||||||
});
|
)
|
||||||
|
.then(
|
||||||
|
(name) => lib_plankton.session.begin(name)
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(session_key) => Promise.resolve({
|
||||||
|
"status_code": 200,
|
||||||
|
"data": lib_plankton.string.coin(
|
||||||
|
"<html><head><meta http-equiv=\"refresh\" content=\"0; url={{url}}\" /></head><body></body></html>",
|
||||||
|
{
|
||||||
|
// TODO: get url from frontend
|
||||||
|
"url": lib_plankton.string.coin(
|
||||||
|
"http://localhost:8888/#oidc_finish,session_key={{session_key}}",
|
||||||
|
{
|
||||||
|
"session_key": session_key,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -55,13 +55,13 @@ namespace _zeitbild.api
|
||||||
execution ?: lib_plankton.rest.type_execution<type_input, type_output>;
|
execution ?: lib_plankton.rest.type_execution<type_input, type_output>;
|
||||||
title ?: (null | string);
|
title ?: (null | string);
|
||||||
description ?: (null | string);
|
description ?: (null | string);
|
||||||
query_parameters ?: Array<
|
query_parameters ?: ((version : (null | string)) => Array<
|
||||||
{
|
{
|
||||||
name : string;
|
name : string;
|
||||||
description : (null | string);
|
description : (null | string);
|
||||||
required : boolean;
|
required : boolean;
|
||||||
}
|
}
|
||||||
>;
|
>);
|
||||||
input_schema ?: ((version: (null | string)) => lib_plankton.rest.type_oas_schema);
|
input_schema ?: ((version: (null | string)) => lib_plankton.rest.type_oas_schema);
|
||||||
output_schema ?: ((version: (null | string)) => lib_plankton.rest.type_oas_schema);
|
output_schema ?: ((version: (null | string)) => lib_plankton.rest.type_oas_schema);
|
||||||
request_body_mimetype ?: string;
|
request_body_mimetype ?: string;
|
||||||
|
|
|
@ -26,10 +26,10 @@ namespace _zeitbild.api
|
||||||
}
|
}
|
||||||
// session
|
// session
|
||||||
{
|
{
|
||||||
// _zeitbild.api.register_session_prepare(rest_subject);
|
_zeitbild.api.register_session_prepare(rest_subject);
|
||||||
_zeitbild.api.register_session_begin(rest_subject);
|
_zeitbild.api.register_session_begin(rest_subject);
|
||||||
_zeitbild.api.register_session_end(rest_subject);
|
_zeitbild.api.register_session_end(rest_subject);
|
||||||
// _zeitbild.api.register_session_oidc(rest_subject);
|
_zeitbild.api.register_session_oidc(rest_subject);
|
||||||
}
|
}
|
||||||
// calendar
|
// calendar
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,12 +3,12 @@ namespace _zeitbild.auth
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*/
|
||||||
let _subject : (
|
let _subject : (
|
||||||
null
|
null
|
||||||
|
|
|
|
||||||
lib_plankton.auth.type_auth<any, any>
|
lib_plankton.auth.type_auth<any, any, any>
|
||||||
) = null;
|
) = null;
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,78 +16,99 @@ namespace _zeitbild.auth
|
||||||
export function init(
|
export function init(
|
||||||
) : Promise<void>
|
) : Promise<void>
|
||||||
{
|
{
|
||||||
/*
|
switch (_zeitbild.conf.get().authentication.kind) {
|
||||||
switch (_zeitbild.conf.get().auth.kind) {
|
|
||||||
case "internal": {
|
case "internal": {
|
||||||
_subject = lib_plankton.auth.internal.implementation_auth(
|
_subject = lib_plankton.auth.internal.implementation_auth(
|
||||||
{
|
{
|
||||||
// "password_image_chest": password_image_chest,
|
"password_image_chest": {
|
||||||
// "check_password": (image, input) => Promise.resolve<boolean>(image === get_password_image(input)),
|
"setup": (input) => Promise.resolve<void>(undefined),
|
||||||
|
"clear": () => Promise.reject<void>("not implemented"),
|
||||||
|
"write": (key, item) => _zeitbild.repository.auth_internal.write(key, item),
|
||||||
|
"delete": (key) => _zeitbild.repository.auth_internal.delete_(key),
|
||||||
|
"read": (key) => _zeitbild.repository.auth_internal.read(key),
|
||||||
|
"search": (term) => Promise.reject<any>("not implemented"),
|
||||||
|
},
|
||||||
|
"check_password": (image, input) => _zeitbild.service.auth_internal.check_raw(image, input),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case "oidc": {
|
case "oidc": {
|
||||||
_subject = lib_plankton.auth.oidc.implementation_auth(
|
_subject = lib_plankton.auth.oidc.implementation_auth(
|
||||||
{
|
{
|
||||||
"url_authorization": _zeitbild.conf.get().auth.data.url_authorization,
|
"url_authorization": _zeitbild.conf.get().authentication.data.url_authorization,
|
||||||
"url_token": _zeitbild.conf.get().auth.data.url_token,
|
"url_token": _zeitbild.conf.get().authentication.data.url_token,
|
||||||
"url_userinfo": _zeitbild.conf.get().auth.data.url_userinfo,
|
"url_userinfo": _zeitbild.conf.get().authentication.data.url_userinfo,
|
||||||
"client_id": _zeitbild.conf.get().auth.data.client_id,
|
"client_id": _zeitbild.conf.get().authentication.data.client_id,
|
||||||
"client_secret": _zeitbild.conf.get().auth.data.client_secret,
|
"client_secret": _zeitbild.conf.get().authentication.data.client_secret,
|
||||||
"url_redirect": "/session/begin",
|
"url_redirect": (_zeitbild.conf.get().authentication.data.backend_url_base + "/session/oidc"),
|
||||||
"scopes": [
|
"scopes": [
|
||||||
"openid",
|
"openid",
|
||||||
"profile",
|
"profile",
|
||||||
"email",
|
"email",
|
||||||
],
|
],
|
||||||
"login_url_mode": "open",
|
"label": _zeitbild.conf.get().authentication.data.label,
|
||||||
|
"login_url_mode": "log",
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
// do nothing
|
// do nothing
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
return Promise.resolve<void>(undefined);
|
return Promise.resolve<void>(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*/
|
||||||
export function prepare(
|
export function prepare(
|
||||||
) : Promise<{kind : string; data : any;}>
|
) : Promise<{kind : string; data : any;}>
|
||||||
{
|
{
|
||||||
return (
|
if (_subject === null) {
|
||||||
_subject.prepare()
|
return Promise.reject(new Error("not initialized yet"));
|
||||||
.then(
|
}
|
||||||
(data) => ({
|
else {
|
||||||
"kind": _zeitbild.conf.get().auth.kind,
|
return (
|
||||||
"data": data,
|
_subject.login_prepare()
|
||||||
})
|
.then(
|
||||||
)
|
(data : any) => ({
|
||||||
);
|
"kind": _zeitbild.conf.get().authentication.kind,
|
||||||
|
"data": data,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*/
|
||||||
export function execute(
|
export function execute(
|
||||||
input : any
|
input : any
|
||||||
) : Promise<string>
|
) : Promise<string>
|
||||||
{
|
{
|
||||||
return _subject.execute(input);
|
if (_subject === null) {
|
||||||
|
return Promise.reject(new Error("not initialized yet"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return _subject.login_execute(input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
export function control(
|
export function control(
|
||||||
input : any
|
input : any
|
||||||
) : Promise<void>
|
) : Promise<void>
|
||||||
{
|
{
|
||||||
return _subject.control(input);
|
if (_subject === null) {
|
||||||
|
return Promise.reject(new Error("not initialized yet"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return _subject.login_control(input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,6 +185,93 @@ namespace _zeitbild.conf
|
||||||
],
|
],
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"default": {}
|
"default": {}
|
||||||
|
},
|
||||||
|
"authentication": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["internal"]
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
],
|
||||||
|
"default": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"kind": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["oidc"]
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"url_authorization": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"url_token": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"url_userinfo": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"client_id": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"client_secret": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"backend_url_base": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"nullable": false,
|
||||||
|
"type": "string",
|
||||||
|
"default": "OIDC"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"url_authorization",
|
||||||
|
"url_token",
|
||||||
|
"url_userinfo",
|
||||||
|
"client_id",
|
||||||
|
"client_secret"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"kind",
|
||||||
|
"data"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": {
|
||||||
|
"kind": "internal",
|
||||||
|
"data": {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
|
@ -64,14 +64,19 @@ namespace _zeitbild.repository.auth_internal
|
||||||
export function write(
|
export function write(
|
||||||
name : string,
|
name : string,
|
||||||
password_image : string
|
password_image : string
|
||||||
|
) : Promise<boolean>
|
||||||
|
{
|
||||||
|
return get_chest().write([name], {"password_image": password_image});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export function delete_(
|
||||||
|
name : string
|
||||||
) : Promise<void>
|
) : Promise<void>
|
||||||
{
|
{
|
||||||
return (
|
return get_chest().delete([name]);
|
||||||
get_chest().write([name], {"password_image": password_image})
|
|
||||||
.then(
|
|
||||||
() => Promise.resolve<void>(undefined)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,26 @@ namespace _zeitbild.service.auth_internal
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
lib_plankton.bcrypt.compute(password)
|
lib_plankton.bcrypt.compute(password)
|
||||||
.then<void>(
|
.then<boolean>(
|
||||||
(password_image) => _zeitbild.repository.auth_internal.write(name, password_image)
|
(password_image) => _zeitbild.repository.auth_internal.write(name, password_image)
|
||||||
)
|
)
|
||||||
|
.then<void>(
|
||||||
|
() => Promise.resolve<void>(undefined)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
export async function check_raw(
|
||||||
|
password_image : string,
|
||||||
|
password : string
|
||||||
|
) : Promise<boolean>
|
||||||
|
{
|
||||||
|
return lib_plankton.bcrypt.compare(
|
||||||
|
password_image,
|
||||||
|
password
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,14 +44,11 @@ namespace _zeitbild.service.auth_internal
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
const password_image : string = await _zeitbild.repository.auth_internal.read(name);
|
const password_image : string = await _zeitbild.repository.auth_internal.read(name);
|
||||||
return lib_plankton.bcrypt.compare(
|
return check_raw(password_image, password);
|
||||||
password_image,
|
|
||||||
password
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
return Promise.resolve<boolean>(false);
|
return Promise.resolve<boolean>(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
60
tools/deploy
Executable file
60
tools/deploy
Executable file
|
@ -0,0 +1,60 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys as _sys
|
||||||
|
import os as _os
|
||||||
|
import argparse as _argparse
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
## args
|
||||||
|
argument_parser = _argparse.ArgumentParser()
|
||||||
|
argument_parser.add_argument(
|
||||||
|
type = str,
|
||||||
|
dest = "target_system",
|
||||||
|
metavar = "<target-system>",
|
||||||
|
help = "either 'localhost' or SSH handle of the target system",
|
||||||
|
)
|
||||||
|
argument_parser.add_argument(
|
||||||
|
"-t",
|
||||||
|
"--target-directory",
|
||||||
|
type = str,
|
||||||
|
dest = "target_directory",
|
||||||
|
default = "/opt/zeitbild",
|
||||||
|
metavar = "<target-directory>",
|
||||||
|
help = "directory on the target system, where the files shall be put; default: /opt/zeitbild",
|
||||||
|
)
|
||||||
|
argument_parser.add_argument(
|
||||||
|
"-b",
|
||||||
|
"--build-directory",
|
||||||
|
type = str,
|
||||||
|
dest = "build_directory",
|
||||||
|
default = "build",
|
||||||
|
metavar = "<build-directory>",
|
||||||
|
help = "directory to where the build was put",
|
||||||
|
)
|
||||||
|
args = argument_parser.parse_args()
|
||||||
|
|
||||||
|
## exec
|
||||||
|
if (not _os.path.exists(args.build_directory)):
|
||||||
|
_sys.stderr.write("-- build directory not found; probably you need to run /tools/build\n")
|
||||||
|
_sys.exit(1)
|
||||||
|
else:
|
||||||
|
_os.system(
|
||||||
|
" ".join([
|
||||||
|
"rsync",
|
||||||
|
"--recursive",
|
||||||
|
"--update",
|
||||||
|
"--verbose",
|
||||||
|
"--exclude='conf.json'",
|
||||||
|
"--exclude='data.sqlite'",
|
||||||
|
("%s/" % args.build_directory),
|
||||||
|
(
|
||||||
|
("%s" % args.target_directory)
|
||||||
|
if (args.target_system == "localhost") else
|
||||||
|
("%s:%s" % (args.target_system, args.target_directory, ))
|
||||||
|
),
|
||||||
|
])
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
|
@ -48,7 +48,9 @@ ${dir_temp}/zeitbild-unlinked.js: \
|
||||||
${dir_source}/api/base.ts \
|
${dir_source}/api/base.ts \
|
||||||
${dir_source}/api/actions/meta_ping.ts \
|
${dir_source}/api/actions/meta_ping.ts \
|
||||||
${dir_source}/api/actions/meta_spec.ts \
|
${dir_source}/api/actions/meta_spec.ts \
|
||||||
|
${dir_source}/api/actions/session_prepare.ts \
|
||||||
${dir_source}/api/actions/session_begin.ts \
|
${dir_source}/api/actions/session_begin.ts \
|
||||||
|
${dir_source}/api/actions/session_oidc.ts \
|
||||||
${dir_source}/api/actions/session_end.ts \
|
${dir_source}/api/actions/session_end.ts \
|
||||||
${dir_source}/api/actions/calendar_list.ts \
|
${dir_source}/api/actions/calendar_list.ts \
|
||||||
${dir_source}/api/actions/events.ts \
|
${dir_source}/api/actions/events.ts \
|
||||||
|
|
|
@ -23,8 +23,8 @@ modules="${modules} rest"
|
||||||
modules="${modules} rest"
|
modules="${modules} rest"
|
||||||
modules="${modules} server"
|
modules="${modules} server"
|
||||||
modules="${modules} args"
|
modules="${modules} args"
|
||||||
# modules="${modules} auth"
|
|
||||||
modules="${modules} bcrypt"
|
modules="${modules} bcrypt"
|
||||||
|
modules="${modules} auth"
|
||||||
|
|
||||||
|
|
||||||
## exec
|
## exec
|
||||||
|
|
Loading…
Add table
Reference in a new issue