permissions, connection data reader
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@ -20,6 +20,7 @@ interface AccessSettings {
|
||||
redirect_to?: string
|
||||
data?: unknown,
|
||||
leave_open?: boolean
|
||||
permissions?: string[]
|
||||
}
|
||||
|
||||
interface AccessResult {
|
||||
@ -95,7 +96,8 @@ class AuthRequest {
|
||||
refresh_token_expires_in,
|
||||
redirect_to,
|
||||
data,
|
||||
leave_open
|
||||
leave_open,
|
||||
permissions
|
||||
}: AccessSettings): Promise<AccessResult> {
|
||||
const log = logger.extend ('allow_access');
|
||||
log ('allowed access');
|
||||
@ -104,7 +106,7 @@ class AuthRequest {
|
||||
const at = await auth.sign (
|
||||
'access_token',
|
||||
access_token_expires_in,
|
||||
{ data }
|
||||
{ data, permissions }
|
||||
);
|
||||
const result: AccessResult = { access_token_id: at.id };
|
||||
|
||||
|
@ -25,6 +25,7 @@ interface VerificationResult {
|
||||
type: TokenType;
|
||||
id: string;
|
||||
next_module?: string;
|
||||
permissions?: string[];
|
||||
data?: unknown;
|
||||
error?: string;
|
||||
}
|
||||
@ -37,7 +38,8 @@ interface SignatureResult {
|
||||
interface SignatureOptions
|
||||
{
|
||||
data?: unknown
|
||||
next_module?: string
|
||||
next_module?: string,
|
||||
permissions?: string[]
|
||||
}
|
||||
|
||||
class Authority {
|
||||
@ -45,10 +47,11 @@ class Authority {
|
||||
const log = logger.extend ('verify');
|
||||
log ('verifying token');
|
||||
const result: VerificationResult = {
|
||||
authorized: false,
|
||||
valid: false,
|
||||
type: 'none',
|
||||
id: ''
|
||||
authorized: false,
|
||||
valid: false,
|
||||
type: 'none',
|
||||
permissions: [],
|
||||
id: ''
|
||||
};
|
||||
const data = await verify_signature_get_info (
|
||||
key,
|
||||
@ -83,6 +86,7 @@ class Authority {
|
||||
result.valid = true;
|
||||
result.authorized = result.type === 'access_token';
|
||||
result.next_module = data.next_module;
|
||||
result.permissions = data.permissions;
|
||||
result.data = data.obj;
|
||||
|
||||
log (
|
||||
@ -90,6 +94,7 @@ class Authority {
|
||||
result.type,
|
||||
result.next_module
|
||||
);
|
||||
log ('permissions %o', result.permissions);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -111,7 +116,8 @@ class Authority {
|
||||
type,
|
||||
valid_for,
|
||||
valid_until,
|
||||
next_module: options?.next_module
|
||||
next_module: options?.next_module,
|
||||
permissions: options?.permissions
|
||||
};
|
||||
const signature = sign_object (options?.data, key, attributes);
|
||||
log ('created token %s', attributes.id);
|
||||
|
@ -32,6 +32,13 @@ interface GatewayOptions {
|
||||
cookie?: CookieSettings;
|
||||
refresh_cookie?: CookieSettings;
|
||||
refresh_settings?: RefreshSettings;
|
||||
require_permissions?: string[];
|
||||
}
|
||||
|
||||
interface ConnectionInfo {
|
||||
token_id: string
|
||||
token_data: unknown
|
||||
permissions: string[]
|
||||
}
|
||||
|
||||
class GatewayClass {
|
||||
@ -97,7 +104,11 @@ class GatewayClass {
|
||||
|
||||
log ('setting connection info');
|
||||
const con = req.connection as unknown as Record<string, unknown>;
|
||||
con.auth = { token_id: ver.id, token_data: ver.data };
|
||||
con.auth = {
|
||||
token_id: ver.id,
|
||||
token_data: ver.data,
|
||||
permissions: ver.permissions
|
||||
};
|
||||
|
||||
log ('token valid: %s', ver.authorized);
|
||||
return ver.authorized;
|
||||
@ -144,8 +155,9 @@ class GatewayClass {
|
||||
log ('setting connection info');
|
||||
const con = req.connection as unknown as Record<string, unknown>;
|
||||
con.auth = {
|
||||
token_id: refresh_result.access_token_id,
|
||||
token_data: ver.data
|
||||
token_id: refresh_result.access_token_id,
|
||||
token_data: ver.data,
|
||||
permissions: ver.permissions
|
||||
};
|
||||
|
||||
log ('tokens refreshed');
|
||||
@ -175,6 +187,22 @@ class GatewayClass {
|
||||
return false;
|
||||
}
|
||||
|
||||
public check_permissions (
|
||||
req: IncomingMessage,
|
||||
permissions = this._options.require_permissions || []
|
||||
): boolean {
|
||||
for (const perm of permissions) {
|
||||
if (!this.has_permission (req, perm))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public has_permission (req: IncomingMessage, permission: string) {
|
||||
const info = this.get_info (req);
|
||||
return info.permissions.includes (permission);
|
||||
}
|
||||
|
||||
public async process_request (
|
||||
req: IncomingMessage,
|
||||
res: ServerResponse,
|
||||
@ -183,7 +211,13 @@ class GatewayClass {
|
||||
const log = logger.extend ('process_request');
|
||||
log ('processing incoming http request');
|
||||
if (await this.authenticate (req, res)) {
|
||||
log ('authentification successful, calling next handler');
|
||||
log ('authentification successful');
|
||||
log ('checking permissions');
|
||||
|
||||
if (!this.check_permissions (req))
|
||||
return this.redirect (res);
|
||||
|
||||
log ('authorization successful. calling next handler');
|
||||
return next ();
|
||||
}
|
||||
|
||||
@ -216,6 +250,16 @@ class GatewayClass {
|
||||
|
||||
log ('complete');
|
||||
}
|
||||
|
||||
public get_info (req: IncomingMessage): ConnectionInfo {
|
||||
const conn = req.connection as unknown as Record<string, unknown>;
|
||||
const auth = conn.auth as Record<string, unknown>;
|
||||
return {
|
||||
token_id: auth.token_id as string,
|
||||
token_data: auth.token_data,
|
||||
permissions: (auth.permissions as string[]) || []
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default function create_gateway (options: GatewayOptions): Gateway {
|
||||
|
Reference in New Issue
Block a user