diff --git a/zign/api.py b/zign/api.py
index d98ed9a..065afae 100644
--- a/zign/api.py
+++ b/zign/api.py
@@ -100,6 +100,11 @@ def get_named_token(scope, realm, name, user, password, url=None,
         if existing_token:
             return existing_token
 
+    if name and not realm:
+        access_token = get_service_token(name, scope)
+        if access_token:
+            return {'access_token': access_token}
+
     config = get_config()
 
     url = url or config.get('url')
@@ -153,6 +158,21 @@ def is_user_scope(scope: str):
     return scope in set(['uid', 'cn'])
 
 
+def get_service_token(name: str, scopes: list):
+    '''Get service token (tokens lib) if possible, otherwise return None'''
+    tokens.manage(name, scopes)
+    try:
+        access_token = tokens.get(name)
+    except tokens.ConfigurationError:
+        # will be thrown if configuration is missing (e.g. OAUTH2_ACCESS_TOKEN_URL)
+        access_token = None
+    except tokens.InvalidCredentialsError:
+        # will be thrown if $CREDENTIALS_DIR/*.json cannot be read
+        access_token = None
+
+    return access_token
+
+
 def get_token(name: str, scopes: list):
     '''Get an OAuth token, either from Token Service
     or directly from OAuth provider (using the Python tokens library)'''
@@ -163,14 +183,7 @@ def get_token(name: str, scopes: list):
     if token:
         return token['access_token']
 
-    tokens.manage(name, scopes)
-    try:
-        access_token = tokens.get(name)
-    except tokens.ConfigurationError:
-        access_token = None
-    except tokens.InvalidCredentialsError:
-        access_token = None
-
+    access_token = get_service_token(name, scopes)
     if access_token:
         return access_token
 

Transparently get service tokens via "tokens" library if possible
We already have the `zign.api.get_token` function and we should consider getting service tokens transparently also when using `zign token` directly.
diff --git a/tests/test_api.py b/tests/test_api.py
index ad3cc20..e6e2f6c 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -1,4 +1,5 @@
 import pytest
+import time
 import tokens
 import zign.api
 
@@ -72,3 +73,18 @@ def test_get_token_fallback_success(monkeypatch):
     monkeypatch.setattr('zign.api.get_new_token', lambda *args, **kwargs: {'access_token': 'tt77'})
 
     assert zign.api.get_token('mytok', ['myscope']) == 'tt77'
+
+
+def test_get_named_token_existing(monkeypatch):
+    existing = {'mytok': {'access_token': 'tt77', 'creation_time': time.time() - 10, 'expires_in': 3600}}
+    monkeypatch.setattr('zign.api.get_tokens', lambda: existing)
+    tok = zign.api.get_named_token(scope=['myscope'], realm=None, name='mytok', user='myusr', password='mypw')
+    assert tok['access_token'] == 'tt77'
+
+
+def test_get_named_token_services(monkeypatch):
+    response = MagicMock(status_code=401)
+    monkeypatch.setattr('requests.get', MagicMock(return_value=response))
+    monkeypatch.setattr('tokens.get', lambda x: 'svcmytok123')
+    tok = zign.api.get_named_token(scope=['myscope'], realm=None, name='mytok', user='myusr', password='mypw')
+    assert tok['access_token'] == 'svcmytok123'

pip install -e .
parse_log_pytest
requirements.txt
pytest pytest-cov
apt-get update apt-get install -y gcc
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
backports.tarfile==1.2.0
certifi==2025.1.31
cffi==1.17.1
charset-normalizer==3.4.1
click==8.1.8
clickclick==20.10.2
coverage==7.8.0
cryptography==44.0.2
dnspython==2.7.0
exceptiongroup==1.2.2
idna==3.10
importlib_metadata==8.6.1
iniconfig==2.1.0
jaraco.classes==3.4.0
jaraco.context==6.0.1
jaraco.functools==4.1.0
jeepney==0.9.0
keyring==25.6.0
keyrings.alt==5.0.2
more-itertools==10.6.0
packaging==24.2
pluggy==1.5.0
pycparser==2.22
pytest==8.3.5
pytest-cov==6.0.0
PyYAML==6.0.2
requests==2.32.3
SecretStorage==3.3.3
stups-cli-support==1.1.22
stups-tokens==1.1.19
-e git+https://github.com/zalando-stups/zign.git@46f296b8952b518c9f93d398ef890d5d4001a37a#egg=stups_zign
tomli==2.2.1
urllib3==2.3.0
zipp==3.21.0

name: zign
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - backports-tarfile==1.2.0
      - certifi==2025.1.31
      - cffi==1.17.1
      - charset-normalizer==3.4.1
      - click==8.1.8
      - clickclick==20.10.2
      - coverage==7.8.0
      - cryptography==44.0.2
      - dnspython==2.7.0
      - exceptiongroup==1.2.2
      - idna==3.10
      - importlib-metadata==8.6.1
      - iniconfig==2.1.0
      - jaraco-classes==3.4.0
      - jaraco-context==6.0.1
      - jaraco-functools==4.1.0
      - jeepney==0.9.0
      - keyring==25.6.0
      - keyrings-alt==5.0.2
      - more-itertools==10.6.0
      - packaging==24.2
      - pluggy==1.5.0
      - pycparser==2.22
      - pytest==8.3.5
      - pytest-cov==6.0.0
      - pyyaml==6.0.2
      - requests==2.32.3
      - secretstorage==3.3.3
      - stups-cli-support==1.1.22
      - stups-tokens==1.1.19
      - tomli==2.2.1
      - urllib3==2.3.0
      - zipp==3.21.0
prefix: /opt/conda/envs/zign

tests/test_api.py::test_get_named_token_services
tests/test_api.py::test_get_new_token_auth_fail tests/test_api.py::test_get_new_token_server_error
tests/test_api.py::test_get_new_token_invalid_json tests/test_api.py::test_get_new_token_missing_access_token tests/test_api.py::test_get_token_existing tests/test_api.py::test_get_token_configuration_error tests/test_api.py::test_get_token_service_success tests/test_api.py::test_get_token_fallback_success tests/test_api.py::test_get_named_token_existing
zign/api.py
zign/api.py