Skip to content

fix(security): reject unknown and unsupported security schemes (#1563) - #1589

Open
bhushan4work wants to merge 1 commit into
eclipse-thingweb:masterfrom
bhushan4work:fix#1563
Open

bhushan4work wants to merge 1 commit into
eclipse-thingweb:masterfrom
bhushan4work:fix#1563

Conversation

@bhushan4work

Copy link
Copy Markdown
Contributor

What changed and why

  • Explicitly reject unknown or unsupported security schemes in client and server paths instead of silently downgrading to nosec or anonymous authentication.
  • Preserve valid cross-binding behavior and multi-scheme security metadata.
  • Prevent HttpServer.fillSecurityScheme from removing foreign security definitions.
  • Add regression tests for unknown prefixed schemes, TD validation, cross-binding schemes, and exposure behavior.

Checks

  • npm run build passed
  • npm test -w packages/binding-http 92 passing
  • npm test -w packages/binding-opcua 98 passing, 1 pending
  • npm test -w packages/core 145 passing, 1 pending
  • npm run lint passed
  • npx prettier --check passed

…se-thingweb#1563)

- Explicitly fail on unknown or unsupported security schemes in client and server paths rather than downgrading to nosec/anonymous or warning-only behavior
- Preserve valid cross-binding behavior by recognizing and ignoring foreign-binding schemes where appropriate
- Support multi-scheme metadata in HttpClient.setSecurity and prevent HttpServer.fillSecurityScheme from wiping out foreign scheme definitions
- Add regression tests covering unknown prefixed schemes, unprefixed validation behavior, foreign-binding schemes, and exposure behavior
@bhushan4work

Copy link
Copy Markdown
Contributor Author

i investigated the failed checks. the windows/node 22 job failed due to a network timeout. the macos/node 22 job passed installation and build but was cancelled. windows/node 24 and ubuntu/node 22 passed. I think no code changes is necessary atp. could you please rerun the failed checks?

@bhushan4work

Copy link
Copy Markdown
Contributor Author

@danielpeintner is any further fix needed in this pr before the final merge ?

@relu91 relu91 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just an intial comment that would probably imply more changes in the overall proposal. Reading #1563 my initial idea was that it should be solved at TD validation level, The TD schema has two levels of verification:

  • the scheme is one of the standard schemes
  • the scheme is prefixed

Since node-wot currently does not allow any schema extension, we should simply don't accept a TD with a schema prefixed here

Comment on lines +267 to -318
for (const security of metadata) {
switch (security.scheme) {
case "basic": {
const securityBasic: BasicSecurityScheme = <BasicSecurityScheme>security;

if (!hasSetCredential) {
this.credential = new BasicCredential(
credentials as BasicCredentialConfiguration,
securityBasic
);
hasSetCredential = true;
}
break;
}
case "bearer": {
const securityBearer: BearerSecurityScheme = <BearerSecurityScheme>security;

if (!hasSetCredential) {
this.credential = new BearerCredential(
credentials as BearerCredentialConfiguration,
securityBearer
);
hasSetCredential = true;
}
break;
}
case "apikey": {
const securityAPIKey: APIKeySecurityScheme = <APIKeySecurityScheme>security;

if (!hasSetCredential) {
this.credential = new BasicKeyCredential(
credentials as BasicKeyCredentialConfiguration,
securityAPIKey
);
hasSetCredential = true;
}
break;
}
case "oauth2": {
const securityOAuth: OAuth2SecurityScheme = <OAuth2SecurityScheme>security;

if (!hasSetCredential) {
if (securityOAuth.flow === "client") {
securityOAuth.flow = "client_credentials";
this.credential = this.oauth.handleClient(
securityOAuth,
credentials as OAuthClientConfiguration
);
} else if (securityOAuth.flow === "password") {
this.credential = this.oauth.handleResourceOwnerCredential(
securityOAuth,
credentials as OAuthResourceOwnerConfiguration
);
}
hasSetCredential = true;
}
break;
}
case "TuyaCustomBearer": {
if (!hasSetCredential) {
this.credential = new TuyaCustomBearer(
credentials as TuyaCustomBearerCredentialConfiguration,
security as TuyaCustomBearerSecurityScheme
);
hasSetCredential = true;
}
break;
}
case "nosec":
break;
default: {
// Schemes belonging to other bindings must remain ignored where appropriate.
// An unknown or unsupported scheme that is not owned by another binding must fail explicitly.
if (this.isForeignSecurityScheme(security.scheme)) {
break;
}
throw new Error(`HttpClient cannot set security scheme '${security.scheme}'`);
}

break;
}
case "TuyaCustomBearer": {
this.credential = new TuyaCustomBearer(
credentials as TuyaCustomBearerCredentialConfiguration,
security as TuyaCustomBearerSecurityScheme
);
break;
}
case "nosec":
break;
default:
error(`HttpClient cannot set security scheme '${security.scheme}'. ${metadata}`);
return false;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would simplify the logic here. Given the following:

To properly fix #1563 I would say that:

  • client finds a security scheme it supports (this includes no_sec too)
  • or it doesn't -> throw

Moreover, since the metadata array is computed here and given the previously mentioned assertion if the array is longer than one -> it is an unsupported scheme (basically is a ComboScheme).

@danielpeintner and @egekorkan correct me if I'm wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants