Skip to content

Fix token auth inconsistency and add native Bearer token support#508

Open
ulbi wants to merge 4 commits intospacemanspiff2007:masterfrom
ulbi:master
Open

Fix token auth inconsistency and add native Bearer token support#508
ulbi wants to merge 4 commits intospacemanspiff2007:masterfrom
ulbi:master

Conversation

@ulbi
Copy link
Copy Markdown

@ulbi ulbi commented Mar 21, 2026

Motivation

This PR addresses two related authentication issues that made it difficult to use openHAB API tokens with HABApp.

Issue – Bug: Token authentication failed when the token was placed in the password field. The detection logic (oh. prefix) was correct, but aiohttp.BasicAuth expects the token as the username with a blank password — not the other way around. The result: REST calls returned 401, while the WebSocket stack (with its own _build_token) worked fine.

Issue – Feature: For new deployments and security-conscious setups (token rotation, fine-grained access control), native support for the Authorization: Bearer <token> header was missing — even though the openHAB REST API and WebSocket interface officially support it.


What changed

New config field token

openhab:
  connection:
    token: ''   # openHAB API token → uses "Authorization: Bearer <token>"

The field was added to the Pydantic model (config/models/openhab.py) and the generated default config snapshot was updated accordingly.

Handler (handler.py) — two layers

  1. Explicit Bearer path: If token is set, on_setup builds the aiohttp.ClientSession with headers={'Authorization': 'Bearer <token>'} instead of BasicAuth. REST and WebSocket then share the same token channel.

  2. Automatic migration of legacy configs: If token is empty but user or password contain an oh. token, HABApp automatically promotes it to Bearer auth and emits a deprecation warning:

    Found openHAB API token in the "user" config field. Please move it to the "token" config field. Using a token in "user" or "password" is deprecated and will be removed in a future version.

    This fully resolves Issue Dev #1 — without any breaking change for existing configurations.

WebSocket plugin (websockets.py)

The token is now derived directly from the Authorization header of the active session, rather than being read separately from the config. This eliminates the inconsistency between session state and configuration.

Tests (tests/test_openhab/test_plugins/test_handler_auth.py)

The test file was restructured from scratch:

Class Coverage
TestBuildToken Regression tests for WebsocketPlugin._build_token: token in login, token in password, BasicAuth fallback
TestTokenResolution Tests for the migration logic in on_setup: explicit token takes precedence, migration from user field, migration from password field, plain credentials without token

Behaviour overview

Configuration Behaviour
token: oh.xyz Bearer auth for REST + WebSocket
token empty, user: oh.xyz Auto-migration → Bearer + warning
token empty, password: oh.xyz Auto-migration → Bearer + warning (Issue #1 fixed)
token: oh.xyz + user/password set Bearer wins + warning
user: admin, password: secret BasicAuth as before

Checklist

  • Bug Dev #1 (token in password field) fixed
  • Feature Dev #2 (native Bearer token support) implemented
  • No breaking change for existing configurations (migration with warning)
  • Tests cover all relevant paths
  • Default config snapshot updated

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