Project | LXD |
Status | Draft |
Author(s) | @monstermunchkin |
Approver(s) | @stgraber @tomp |
Release | 5.13 |
Internal ID | LX037 |
Abstract
This adds OpenID Connect as a new authentication method.
Rationale
LXD currently supports only tls
and candid
as authentication methods. The former uses certificates for authentication, and the latter requires a candid server which is a macaroon-based authentication service.
OpenID Connect (OIDC) is a simple identity layer on top of the OAuth 2.0 protocol. One of the advantages of OIDC is that it allows authentication without LXD having to store and manage users and passwords.
Specification
Design
The following new server configuration keys will be added:
oidc.issuer
oidc.client.id
oidc.client.secret
The oidc.issuer
key contains the URL of the server issuing the tokens. This for example could point to a Keycloak server.
Clients are applications and services that can request authentication of a user, and communicate with the issuer using the oidc.client.id
and oidc.client.secret
.
OIDC can be enabled by simply setting all of the oidc.*
keys.
If the client wants to communicate with the LXD server using OpenID, it sets the X-LXD-oidc
HTTP header for every request. That way the server knows what kind of authentication to use.
LXD advertises the authentication methods it supports. The oidc
value will be added to this list. oidc
should be favored over candid
which itself is favored over tls
.
Adding a new remote
The user can add a new remote using lxc remote add <foo> --auth-type=oidc
.
Authentication
If the client cannot be authenticated, the LXD server returns an error containing the issuer, client ID, and client secret. It also contains the type of error and can be one of the following:
authentication request
invalid token
The authentication request
error means that the user needs to log in. The invalid token
error most likely means that the token has expired, but it can also have a different reason. This error also contains the reason which can be one of these errors.
Using the issuer, client ID, and client secret, the user will be presented with a login page. On successful login, the client receives an access token, refresh token, and ID token. These are stored on disk.
If invalid token
was returns by the LXD server, and the refresh token is still valid, a new access token will be retrieved without user interaction. Otherwise the login page will be presented again.
Once the tokens have been retrieved, the only one used for authentication by the LXD server is the access token. The others stay with the user and client. The ID token is not used for anything beyond this point, and the refresh token is for refreshing the access token.
The access token will be sent with every request using the Authorization
HTTP header:
Authorization: Bearer <access_token>
Since the access token is a JSON Web Token (JWT), it can be decoded and validated offline (i.e. without having to call the OpenID Provider). The LXD server will do this on every request, and return an error if the validation fails.
Initial flow to get token
- User adds remote with
lxc remote add <remote> --auth-type=oidc
- LXD server returns OIDC information (issuer, client ID, and client secret)
- User is required to log in from the browser, and client uses OIDC information to get tokens
- Client uses access token to access LXD
Valid access token
- Client sets
Authorization
HTTP header with access token to access LXD
Expired access token but valid refresh token
- Client sets
Authorization
HTTP header with access token to access LXD - LXD returns OIDC information together with the
invalid token
error - Client gets a new access token using the refresh token
- Client uses new access token to access LXD
Expired access token and expired refresh token
- Client sets
Authorization
HTTP header with access token to access LXD - LXD returns OIDC information together with the
invalid token
error - Client fails to get a new access token using the expired refresh token
- User is required to log in from the browser, and client uses OIDC information to get new tokens
- Client uses new access token to access LXD
CLI changes
The --auth-type
flag for lxc remote add
accepts oidc
.
Upgrade handling
If there’s a remote configured which uses candid, and the LXD server adds OIDC support, the client will continue using candid. OIDC should only then be used when adding a new remote.