?uem/p1-90`This document covers authentication and authorization on the consumer side of a TEA service - the discovery and download of software transparency artefacts.
A user of a TEA service may get access to all objects (components, collections) and artefacts or just a subset, depending on the publisher of the data. Authorization is connected to authentication.
The level of authorization is up to the implementer of the TEA implementation and the publisher, whether an identity gets access to all objects in a service or just a subset.
In order to get interoperability between clients and servers implementing the protocol, the specification focuses on the authentication. After successful authentication, the authorization may be implemented in multiple ways - on various levels of the API - depending on what information the user can access.
As an example, one implementation may publish all information about existing artefacts and software versions openly, but restrict access to artefacts to those that match the user's installation. Another implementation can implement a filter that does not show products and versions ("components") that the user has not acquired.
For most Open Source projects, implementing authentication - setting up accounts and managing authorization - does not make much sense, since the information is usually in the open anyway.
This specification does not require a TEA server to authenticate its users.
The requirements of this chapter apply to a TEA server that requires authentication for some or all of its objects, and therefore implements the token endpoint, and to a TEA client that accesses such a server. Such a server implements the baseline below in full; see Servers that protect some objects.
A TEA server that requires no authentication need not implement anything in this chapter, including the token endpoint. The rules such a server follows are in the "Authentication and authorization" section of Discovery; see also Servers without authentication.
Where a service does authenticate, interoperability requires that every TEA client can authenticate against every TEA server without server-specific code. This specification therefore defines a single mandatory baseline and leaves everything above it optional:
POST /token) described below, and shall support the API key credential exchange on it.Two consequences are worth stating explicitly, because they are what make the baseline useful:
The token endpoint is POST /token, relative to the TEA API base URL, and is defined in the TEA
/token appears only in its examples - so TEA fixes the path here rather than requiring clients to discover it. TEA defines no
An API key consists of two parts issued together by the service: an identifier and a secret. The identifier need not be confidential; the secret is.
The client presents them using the HTTP Basic authentication scheme (RFC 7617) - the identifier as the user-id and the secret as the password - with the client_credentials grant type. This is
POST /token HTTP/1.1
Host: tea.example.com
Authorization: Basic <base64 of "key-id:key-secret">
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
Per application/x-www-form-urlencoded encoded before being joined with a colon and Base64 encoded. This only matters when a credential contains a colon or characters outside US-ASCII, but clients and servers shall apply it so that such credentials interoperate.
Servers may additionally accept the credentials as client_id and client_secret form parameters in the request body.
A successful response is the standard
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
{
"access_token": "2YotnFZFEjr1zCsicMWpAA",
"token_type": "Bearer",
"expires_in": 3600
}
Errors are the standard invalid_client for a bad API key or unsupported_grant_type for a grant the server does not implement.
The access token is presented on every other TEA endpoint as an HTTP bearer token (RFC 6750):
GET /product/d4d9f54a-abcf-11ee-ac79-1a52914d44b1 HTTP/1.1
Host: tea.example.com
Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA
The access token is opaque to the client. Clients shall not inspect, parse, or depend on the contents of the token, and shall not assume any particular format. Servers are free to issue a random handle, a signed token such as a
Token lifetime, storage, rotation, and revocation are implementation matters and are deliberately not specified. Two rules keep clients simple in spite of that:
Servers should return expires_in, so that a client can obtain a new token before the current one expires rather than discovering expiry through a failed request.
If a request to a resource endpoint fails with 401 and the WWW-Authenticate challenge header carries error="invalid_token", the client may obtain a new token from the token endpoint and retry the request once, as described in
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="tea", error="invalid_token", error_description="The access token expired"
Between them these cover server-side revocation without the client having to know it happened: invalid_token as covering tokens that are "expired, revoked, malformed, or invalid for other reasons". This specification defines no revocation endpoint, and clients need not implement one.
No refresh tokens. Servers should not issue refresh tokens with the client_credentials grant, following
A server may accept credentials other than an API key at the same token endpoint, selected by the grant_type parameter. In every case the response is the same token response, and the resulting access token is used the same way, so clients that already implement the baseline need only the additional request.
The following are the cases we expect to be common. All are existing
| Use case | Grant type | Specification |
|---|---|---|
| Enterprise SSO where the user's identity provider issues SAML assertions | urn:ietf:params:oauth:grant-type:saml2-bearer |
RFC 7522 |
| OpenID Connect, or any provider issuing signed |
urn:ietf:params:oauth:grant-type:jwt-bearer |
RFC 7523 |
| A client already holding a token from another security domain, exchanged for a TEA token | urn:ietf:params:oauth:grant-type:token-exchange |
RFC 8693 |
| A client authenticated by a TLS client certificate rather than a shared secret | client_credentials with mutual TLS client authentication |
RFC 8705 |
RFC 8693 token exchange (urn:ietf:params:oauth:grant-type:token-exchange) is outside the scope of the TEA 1.0 interoperable authentication profile. TEA 1.0 does not specify the request or response contract for this grant. Implementations may support it as an extension by separate agreement, but clients shall not assume its availability based solely on TEA 1.0 conformance. Such extensions do not remove the requirement for servers requiring authentication to support the client_credentials baseline.
RFC 7521 defines the common framework the two assertion grants share.
Note that a server which delegates identity to an external provider still issues its own TEA access token from its own token endpoint. The external provider authenticates the user; the TEA server decides what that user may see. This keeps authorization with the party that owns the data, and keeps the resource endpoints validating exactly one kind of token.
Mutual TLS is a client authentication method at the token endpoint, not a separate way in. A client authenticated by a certificate presents no Authorization header on its token request; the certificate identifies it.
Client certificates are managed by the service and provided in a service-specific way. Clients should be able to configure a separate client certificate and private key per TEA service, and should not assume that a client certificate for one service is trusted anywhere else.
All of the above assumes TLS. Credentials and bearer tokens are transmitted in the clear at the HTTP layer, so a TEA server shall be reachable only over TLS, and clients shall verify the server certificate, including the server identity check of RFC 9525. This restates
Whether a server requires authentication is discovered by using it, not by configuration and not by probing the token endpoint. In TEA, resource operations may be called with a Bearer token or without one; a 401 with a WWW-Authenticate: Bearer challenge on a given endpoint is the runtime signal that a token is required there. The complete flow for a client that does not know in advance:
200 with the resource. The client is done.401 with a WWW-Authenticate header naming the Bearer scheme, as described in POST /token with its credential - for the baseline, the API key over HTTP Basic - and receives an access token. Unauthenticated client_credentials requests shall not be accepted; an empty /token allows alternate client authentication (for example, mutual TLS, Authorization: Bearer <access_token>, and presents the same token on subsequent requests until it expires or is rejected.401 and error="invalid_token", the client obtains a fresh token and retries that request once, as described above.A client that already holds an API key for a service may skip steps 1 to 3 and call the token endpoint first: being issued a key is itself the signal that the service requires authentication. Trying the resource first is for the case where the client does not know.
Two things the flow deliberately avoids. A client shall not probe /token to find out whether authentication exists; the challenge on the resource is the discovery mechanism, and a 404 from /token means only that the endpoint is not implemented. And a client shall not send its API key to a resource endpoint; the key goes to the token endpoint only, and resource endpoints see bearer tokens only.
The cost of the unknown case is one wasted request per server, once. This is the standard HTTP pattern and is preferred over any configuration or discovery step a client would otherwise need.
A server that requires no authentication on any endpoint (and therefore applies no authorization) follows the rules in the "Authentication and authorization" section of Discovery: it need not implement the token endpoint, it does not answer resource requests with 401, and it ignores an Authorization: Bearer header a client presents anyway.
There is nothing to exchange on such a server: an
A TEA server may make some data available without authentication while requiring authentication and authorization for other objects - for example, listing products and releases without a token while restricting artifact downloads to some users. Such a server requires authentication for the protected objects:
401 with the Bearer challenge when no valid token is presented, which is how a client learns, per endpoint, that a token is needed. They shall not answer a concealing 404 solely because the client is unauthenticated. A client should not assume that a server which served one object without authentication will serve every object without authentication, nor the reverse.Authorization - which of the protected data an authenticated client may see - is the server's decision and is not constrained by this specification; a client with a valid token may still receive a filtered view, 403 Forbidden, or a concealing 404 Not Found for individual objects it is not authorized to see. Clients shall not infer from 404 alone whether the object is absent or withheld.
Servers that delegate identity to an external provider may publish WWW-Authenticate challenge, allowing a client to locate the authorization server automatically. This is optional; it does not replace the token endpoint, which remains the interoperable baseline, and it does not replace the challenge as the way a client discovers that authentication is required.
X-API-KeyThere is no IETF specification for API keys, and no registered HTTP authentication scheme for them. A survey of the IETF datatracker finds only working-group discussion material and an early individual draft, nothing normative. The widespread X-API-Key header is additionally at odds with RFC 6648, a Best Current Practice that deprecates the X- prefix for new header fields.
This specification therefore carries the API key in the standard Authorization header using the Basic scheme, which is registered, specified, supported directly by essentially every HTTP client library, and already the mandatory-to-implement client authentication method for