User Tools

Site Tools


api:carddav:authentication

API : CardDAV : Authentication

Introduction

Every request below /carddav/ - except /carddav/notify - is authenticated with HTTP Basic authentication (RFC 7617), because that is all a contacts app can do. There is no login endpoint and no session; the client sends the credentials on every single request.

Realm TelecomX CardDAV
User name The employees e-mail address.
Password The employees password, or one of the employees own persistent tokens used as an app specific password.

A missing or unusable Authorization header answers 401 with WWW-Authenticate: Basic realm=“TelecomX CardDAV”, which is what makes the client show its credentials dialog.

How a request is authenticated

  1. Cached token. An MD5 hash of <email>:<password> is looked up in Redis (key carddav-token:<md5-hash>). On a hit the cached Telecom X token is validated and the request continues without touching bcrypt. If the employee has since been switched to passkey-only, the cache entry is deleted and the request falls through to the steps below.
  2. Persistent token as password. If the password is one of the tokens in the employees own persistentTokens list, and that token still validates, the request continues. This is the app specific password described below.
  3. Password. The password is bcrypt-compared against the employee record. On success a persistent token is created for the employee and stored in the Redis cache, so the following requests take path 1.

Whichever path is taken, the resulting token is the one embedded in the photo URLs of the served vCards, so the device can download contact pictures from the image server.

Passkey-only employees

An employee with webauthnOnly set has no usable password - a contacts app cannot perform a WebAuthn ceremony. The password step is therefore refused with 401 webauthn_only, and such an employee must instead use an app specific password:

  1. Create a persistent token for the employee with POST /employee/{id}/token. Only the employee herself gets to see the token value.
  2. Enter the token as the password in the contacts app. The user name stays the employees e-mail address.
  3. Revoke it again with DELETE /employee/{id}/token/{token} - the client is then refused at the next poll.

The token is only accepted when it is found in that employees own token list, so a token belonging to somebody else is useless even though it is a valid token. Turning webauthnOnly on for an employee that already syncs with a password also invalidates the cached credentials, so their client stops at the next poll and must be given a token.

Restrictions

Restriction Behaviour
IP restriction Not enforced. Token validation is deliberately given no IP address on this transport, so an employees ipRestriction (country or CIDR allow list) does not apply to CardDAV - a phone has to keep syncing while it roams abroad or moves onto mobile data. The token is still created with the IP the client authenticated from.
Rate limiting Every authenticated request is counted in the token scope, keyed by a SHA-256 hash of the token. CardDAV clients poll aggressively, so this is the limit that protects the API. Exceeding it answers 429.
Brute force A failed authentication registers a brute force attempt for the client IP, exactly as a failed login does. Enough failures block the IP for all API access - a phone left with an old password will do this on its own.
Access level None. Any employee that can log in can sync, and only ever within their own customer.

Errors

Error code Message Description
401 Authentication required No Authorization: Basic header.
401 Invalid credentials Malformed header, unknown e-mail, wrong password, or a passkey-only employee using a password.
429 too_many_requests Rate limit for the token exceeded.
403 access_denied Authenticated, but the resource belongs to another customer.
api/carddav/authentication.txt · Last modified: by Per Møller

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki