Authentication (AuthN)
The AIStore Authentication Server (AuthN) provides secure access to AIStore by leveraging JSON Web Tokens (JWT).
NOTE: AuthN is under development and has NOT gone through a complete security audit. Please review your deployment carefully and follow our security policy to report any issues.
COMPATIBILITY: Tokens issued with only the ‘username’ and ‘expires’ claims (deprecated in v4.2) will no longer pass AIS authentication in v4.3. New tokens will use ‘sub’ and ‘exp’ claims in place of ‘username’ and ‘expires’, respectively.
For more details:
- Introduction to JWT
- Go implementation of JSON Web Tokens used for AuthN.
Key Features
- Standalone Server: AuthN operates independently, managing users and tokens separately from the AIStore cluster.
- Secure Tokens: AuthN supports two methods for signing issued JWTs:
- RSA asymmetric key pairs with RS256 (Recommended)
- HMAC symmetric key signing with HS256
- Client Workflow: If AuthN is enabled on a cluster, users must log in to receive a token from AuthN. This token must be included in subsequent HTTP requests to the AIS cluster. Requests without a valid token are rejected by AuthN-enabled AIS clusters.
- OIDC Issuer Compliance: When configured with RSA signing, AuthN implements a small subset of the OIDC spec with the capability to serve as a discoverable JWKS provider. See OIDC Issuer below.
Typical Workflow

- User logs in: The client sends login credentials to AuthN.
- Token Issuance: AuthN issues a token to the client.
- Authenticated Requests: The client includes the token in the request headers (
Authorization: Bearer <token>) for subsequent API requests to the AIStore cluster. - API Response: The cluster processes the request and responds.
Protocols
AuthN supports both HTTP and HTTPS protocols.
By default, AuthN starts as an HTTP server listening on port 52001.
For HTTPS, ensure the configuration file options server_crt and server_key are correctly set to the TLS certificate and key paths.
AuthN generates tokens that are self-sufficient, meaning a proxy does not need to contact AuthN to check permissions. AIStore clusters should be registered with the AuthN server. This allows AuthN to broadcast revoked tokens to all registered clusters for immediate access restriction.
Table of Contents
- Getting Started
- RSA Signing
- OIDC Issuer
- HMAC Deployment Example
- Environment and Configuration
- AuthN Configuration and Log
- Permissions
- How to Enable AuthN Server After Deployment
- REST API
Getting Started
In this section, we use AIStore Local Playground. This is done for demonstration purposes, as it’s easy to use and reproduce.
If you already have an AIS cluster deployed and just want to add AuthN to it for authentication and access control, follow these instructions.
Note: When deploying AIStore with AuthN, an
adminuser is created by default withadminprivileges.The default password for the
adminuser must be set with the environment variableAIS_AUTHN_SU_PASS.For the list of environment variables, refer to the Environment Configuration section below.
Follow these steps to deploy a new local AIS cluster with AuthN enabled and RSA signing:
- Optionally, shut down and clean up any existing Local Playground deployments and rebuild AIS CLI:
make kill clean cli -
Build AuthN and deploy an AuthN server. The following example exports the required admin password. Then it runs AuthN with an auto-generated local config at
$HOME/.config/ais/authn(see the deployment script). See key passphrase to optionally protect the private key on disk.export AIS_AUTHN_SU_PASS="adminpass" make authn-deploy -
Fetch the public key from the AuthN service and export it for the AIS cluster to use:
export AIS_AUTHN_PUBLIC_KEY="$(ais auth show public-key)" - Deploy the cluster with AuthN validation enabled:
AIS_AUTHN_ENABLED=true make deploy
This will start up an AIStore cluster that trusts JWTs issued by the AuthN server.
Initial Setup and Authentication
After deploying the cluster, you won’t be able to access it without authentication:
ais show cluster
Error: token required
- Log in as Admin:
ais auth login admin -p $AIS_AUTHN_SU_PASS Logged in (/root/.config/ais/cli/auth.token) - View Registered Clusters:
ais auth show cluster CLUSTER ID ALIAS URLs - Add Your Cluster:
ais auth add cluster mycluster $AIS_ENDPOINT - Confirm Cluster Registration:
ais auth show cluster CLUSTER ID ALIAS URLs eTdL4YGHN mycluster http://localhost:8080
Default Roles and Permissions
AuthN automatically deploys with a superuser role Admin and a user account admin with that role assigned.
Only users with the Admin role can manage AuthN.
Admins have superuser permissions and can assume all other roles in the cluster.
When a cluster is registered, AuthN creates a set of default roles for that cluster:
ais auth show role
ROLE DESCRIPTION
Admin AuthN administrator
BucketOwner-mycluster Full access to buckets in eTdL4YGHN[mycluster]
ClusterOwner-mycluster Admin access to eTdL4YGHN[mycluster]
Guest-mycluster Read-only access to buckets in eTdL4YGHN[mycluster]
Enable CLI Auto-Completion
Ensure that you have auto-completions enabled for the AIS CLI:
make cli-autocompletions
You can use <TAB-TAB> to view a list of possible options:
$ ais auth add role role_name <TAB-TAB>
ro GET DESTROY-BUCKET PATCH PROMOTE APPEND SET-BUCKET-ACL
rw HEAD-OBJECT MOVE-BUCKET PUT HEAD-BUCKET MOVE-OBJECT LIST-BUCKETS
su LIST-OBJECTS ADMIN DELETE-OBJECT CREATE-BUCKET UPDATE-OBJECT SHOW-CLUSTER
Example Workflow
- Create a Bucket and Add an Object:
ais bucket create ais://nnn "ais://nnn" created ais put README.md ais://nnn PUT "README.md" => ais://nnn/README.md - Create a Role and User:
- Create a role that can only list buckets and objects:
ais auth add role list-perm --cluster mycluster --desc "Users with this role can only list buckets and objects" LIST-OBJECTS LIST-BUCKETSFor a comprehensive list of permissions, see the Permissions section below.
- Add a user named
alicewith this role:ais auth add user alice -p 12345 list-perm
- Create a role that can only list buckets and objects:
- Log in as the New User and Save the Token:
ais auth login alice -p 12345 -f /tmp/alice.token Logged in (/tmp/alice.token) - Perform Operations with Limited Permissions:
- List buckets and objects:
AIS_AUTHN_TOKEN_FILE=/tmp/alice.token ais ls AIS_AUTHN_TOKEN_FILE=/tmp/alice.token ais ls ais://nnn - Attempt restricted actions (which will fail due to permissions):
AIS_AUTHN_TOKEN_FILE=/tmp/alice.token ais get ais://nnn/README.md - Error: http error code 'Forbidden', bucket "ais://nnn"
- List buckets and objects:
Further references:
- See CLI auth subcommand for all supported command line options and usage examples.
RSA Signing
The recommended and default signing method for AuthN-issued JWTs is RS256. This is an asymmetric signing system; the private key is managed solely by AuthN and never shared, while the public key is freely distributed.
The public key can be easily accessed in PEM format by simply running ais auth show public-key.
See auth_validation.md for info on configuring this for AIStore.
For dynamic public key lookup, see the OIDC issuer section below.
Private Key Passphrase
For production use, we recommend storing the generated private key on encrypted storage, e.g. a K8s secret.
The location of generated RSA private keys can be set with AIS_AUTHN_PRIVATE_KEY_FILE.
Otherwise, it defaults to a location in the config directory.
If this is not available or if you want additional protection, you can also protect the private key with a passphrase.
Set AIS_AUTHN_PRIVATE_KEY_PASS to use a passphrase for encrypting the key.
Note that this passphrase cannot be changed without replacing the key on disk.
OIDC Issuer
While AuthN does not implement the full OIDC spec, it provides basic OIDC Discovery and JWKS endpoints. This allows an AIS cluster to trust tokens issued by AuthN without needing any static key details.
When configured with RSA signing, AuthN:
- Embeds a
kid(key ID) header in every issued JWT - Serves an OIDC discovery document at
/.well-known/openid-configuration - Serves the public key set at
/.well-known/jwks.json- The JWKS endpoint returns a standard JSON Web Key Set containing the RSA public key(s).
The diagram below shows the authentication flow:

For details on configuring AIStore for validation based on OIDC lookup, see auth_validation.md.
External URL
AuthN must know its own externally reachable URL so that the OIDC discovery document and issued tokens contain the correct issuer value.
The iss claim in every token is set to this URL, and all endpoints in the discovery document are derived from it.
Set the external URL via the AIS_AUTHN_EXTERNAL_URL environment variable or the net.external_url field in authn.json:
export AIS_AUTHN_EXTERNAL_URL="https://authn.example.com:52001"
If not set, AuthN defaults to http[s]://localhost:<port> (with a warning logged).
NOTE: In these examples we use
localhostas the hostname for the AuthN service. In a production deployment, this must be the hostname for the AuthN service accessible by AIStore. This can be provided by a load balancer, Docker network, K8s service, etc.
The external URL value must match an entry in auth.oidc.allowed_iss on the AIS cluster for OIDC validation to succeed.
OIDC Deployment Example
Deploying with OIDC discovery simplifies the setup, but requires TLS for AuthN itself.
First, set up a self-signed certificate pair for localhost (see Generating self-signed certificates for a more complete example):
openssl req -x509 -newkey rsa:2048 -keyout server.key -out server.crt -days 365 -nodes \
-subj '/CN=localhost' -addext 'subjectAltName=DNS:localhost,IP:127.0.0.1'
Then deploy both AuthN and AIStore locally with AuthN provisioned as a trusted OIDC issuer:
AIS_AUTHN_SU_PASS="adminpass" \
AIS_AUTHN_USE_HTTPS=true \
AIS_SERVER_CRT=server.crt \
AIS_SERVER_KEY=server.key \
AIS_USE_HTTPS=true \
AIS_SKIP_VERIFY_CRT=true \
AIS_AUTHN_ALLOWED_ISS="https://localhost:52001" \
AIS_AUTHN_ENABLED=true \
AIS_AUTHN_DEPLOY=true \
make deploy
AIStore deploys before AuthN in this mode, so you can safely ignore warnings about key pre-caching failing. Once deployment is complete, AIStore will fetch the JWKS from AuthN as needed on the first validation.
Note: In this local deployment, both AuthN and the AIS cluster share the same TLS certificate (
AIS_SERVER_CRT/AIS_SERVER_KEY).AIS_SKIP_VERIFY_CRT=trueis set to accommodate the self-signed certificate. For production deployments, configureauth.oidc.issuer_ca_bundleinstead of skipping verification.
After deployment, configure the CLI to accept the self-signed certificate and set the HTTPS endpoint:
ais config cli set cluster.skip_verify_crt true
export AIS_ENDPOINT=https://localhost:8080
export AIS_AUTHN_URL=https://localhost:52001
From here, follow the same Initial Setup and Authentication steps to log in, register the cluster, and create roles and users.
HMAC Deployment Example
If asymmetric keys are not a requirement for your deployment, AuthN can still be used for basic access control with a single static HMAC secret used for both signing and validation.
Set AIS_AUTHN_SECRET_KEY to configure this for both AuthN signing and AIStore validation.
AIS_AUTHN_ENABLED=true \
AIS_AUTHN_DEPLOY=true \
AIS_AUTHN_SU_PASS="password" \
AIS_AUTHN_SECRET_KEY="keyForSigningTokens" \
make deploy
Note: The secret key used to validate tokens cannot be changed without restarting the cluster.
Environment Configuration
For variables used for AIStore token validation, see environment-vars.md.
Environment variables used by the AuthN server:
| Variable | Default Value | Description |
|---|---|---|
AIS_AUTHN_CONF_DIR |
"" -- CLI option |
Set the directory used for AuthN config. Overrides the CLI config option. |
AIS_AUTHN_LOG_DIR |
AIS_AUTHN_CONF_DIR/logs/ |
Override for log directory set in config |
AIS_AUTHN_LOG_LEVEL |
3 |
Log level, currently only parsed once on config generation and only referenced from config. Supported levels include: 3 (default), 4 (verbose), and 5 (super-verbose) |
AIS_AUTHN_PORT |
52001 |
Port on which AuthN listens for requests |
AIS_AUTHN_TTL |
24h |
Token expiration time. Can be set to 0 for no expiration |
AIS_AUTHN_USE_HTTPS |
false |
Enable HTTPS for AuthN server. If true, requires AIS_SERVER_CRT and AIS_SERVER_KEY to be set |
AIS_SERVER_CRT |
"" |
TLS certificate. Required when AIS_AUTHN_USE_HTTPS is true |
AIS_SERVER_KEY |
"" |
Private key for the TLS certificate (above). |
AIS_AUTHN_SU_NAME |
admin |
Superuser (admin) name for AuthN |
AIS_AUTHN_SU_PASS |
None -- required | Superuser (admin) password for AuthN |
AIS_AUTHN_SECRET_KEY |
"" |
HMAC secret key used to sign tokens. |
AIS_AUTHN_PRIVATE_KEY_FILE |
"" |
RSA private key file path (AuthN server) |
AIS_AUTHN_PRIVATE_KEY_PASS |
"" |
RSA private key passphrase (AuthN server, optional) |
AIS_AUTHN_EXTERNAL_URL |
http[s]://localhost:52001 |
URL for AIS clusters to use when validating AuthN as allowed issuer. See External URL section |
All variables can be set at AIStore cluster deployment and will override values in the config.
- More info on env vars: api/env/authn.go
Separately, configure the following AuthN environment variables for client access:
| Name | Description |
|---|---|
AIS_AUTHN_URL |
Used by CLI to configure and query the authentication server (AuthN). |
AIS_AUTHN_TOKEN_FILE |
Token file pathname; can be used to override the default $HOME/.config/ais/cli/<fname.Token>. |
AIS_AUTHN_TOKEN |
The JWT string itself (excluding the file and JSON) -- replaces need for a token file. |
AuthN Configuration and Log
| File | Location |
|---|---|
| Server configuration | $AIS_AUTHN_CONF_DIR/authn.json |
| User database | $AIS_AUTHN_CONF_DIR/authn.db |
| Log directory | $AIS_LOG_DIR/authn/log/ |
Note: When AuthN is running, execute
ais auth show configto find out the current location of all AuthN files.
Permissions
In AIStore, roles define the level of access by granting permissions to users. The available permissions are listed below:
| Permission | Description |
|---|---|
GET |
Read object contents. |
HEAD-OBJECT |
Read object metadata (properties). |
PUT |
Write object. |
APPEND |
Append to object. |
DELETE-OBJECT |
Delete object. |
MOVE-OBJECT |
Move/rename object. |
PROMOTE |
Promote local files. |
UPDATE-OBJECT |
Update object metadata. |
HEAD-BUCKET |
Read bucket metadata (properties). |
LIST-OBJECTS |
List objects in a bucket. |
PATCH |
Set bucket properties. |
SET-BUCKET-ACL |
Set bucket permissions. |
LIST-BUCKETS |
List all buckets in cluster. |
SHOW-CLUSTER |
View cluster information. |
CREATE-BUCKET |
Create new bucket. |
DESTROY-BUCKET |
Destroy/delete bucket. |
MOVE-BUCKET |
Move/rename bucket. |
ADMIN |
Full administrative access: all cluster operations. |
The following values are provided as convenient aliases for a list of permissions:
| Alias | Permission list |
|---|---|
ro |
Bucket read-only: GET, HEAD-OBJECT, HEAD-BUCKET, LIST-OBJECTS. |
rw |
Bucket read-write: ro + PUT, APPEND, DELETE-OBJECT, MOVE-OBJECT, PROMOTE. |
su |
Super-user: full access to all operations. |
How to Enable AuthN Server After Deployment
By default, the AIStore deployment does not launch the AuthN server. To start the AuthN server manually, follow these steps:
- Build AuthN:
make authn - Create a Configuration File:
- Reference deploy/dev/local/authn_config.sh for current config generation.
- You will need a configuration file similar to the following:
{ "log": { "dir": "/tmp/ais/authn/log", "level": "3" }, "net": { "http": { "port": 52001, "use_https": false, "server_crt": "", "server_key": "" } }, "auth": { "expiration_time": "24h" }, "timeout": { "default_timeout": "30s" } }
- Start the AuthN Server:
Start the AuthN server in a new terminal or screen session. Ensure that
authn.jsonexists in the configuration directory.authn -config=<authn_config_dir> - Configure AIStore Cluster to Enable Token-Based Access:
ais config cluster auth.enabled true - Verify Access:
Now, you cannot access the cluster without a token:
ais ls Error: token required - Log in as Admin:
To continue operations, log in as the admin user:
ais auth login admin -p admin Logged in (/root/.config/ais/cli/auth.token) - Register the Cluster with AuthN:
Register the AIStore cluster with AuthN to receive AuthN messages (e.g., revoked token list):
ais auth add cluster mycluster $AIS_ENDPOINT - Proceed with Cluster Operations: After registering, you can proceed using your cluster with admin privileges. You can add users, set up roles, etc.
Note: This example assumes that AuthN is running on the same host as the AIS cluster. If AuthN is running on a different host, you will need to specify the
AIS_AUTHN_URLvariable. For example, useAIS_AUTHN_URL=http://10.10.1.190:52001 ais auth COMMAND.
REST API
Notation
In this section:
AUTHSRV- denotes a (hostname:port) address of a deployed AuthN server (default: http://localhost:52001)
Authorization
Every request to AuthN (except login) must contain an authentication token in the header:
Authorization: Bearer <token-issued-by-AuthN-after-login>
For curl, pass it as an argument: -H 'Authorization: Bearer token'.
Tokens
See the auth validation doc for JWT claim requirements. In addition to meeting these requirements, tokens must also not be in the cluster’s revoked token collection.
Revoked Tokens
AuthN ensures that all AIS gateways (proxies) are updated with each revoked token. When AuthN registers a new cluster, it sends the cluster the entire list of revoked tokens. Periodically, AuthN will clean up the list and remove expired and invalid tokens.
The example workflow below demonstrates the revocation process:
- An AuthN server is deployed alongside two clusters
AIS Cluster 1is registered with AuthN- When a user revokes a token from AuthN, it is synced with all registered clusters
AIS Cluster 1now rejects the previously valid tokenAIS Cluster 2is not registered, so does not receive any revoked token list- Requests with the revoked token to
AIS Cluster 2will still succeed

Expired Tokens
Generating a token for data access requires users to log in with a username and password.
By default, the token expiration time is set to 24 hours.
Modify expiration_time in the configuration file to change the default expiration time.
To issue a single token with a custom expiration time, pass an optional expiration duration in the request:
ais auth login -p password username -e 5h
Pass a zero value with -e 0 to generate a token with no expiration.
AuthN returns the generated token as JSON. Example: {"token": "issued_token"}.
The revoke token API shown below will forcefully invalidate a token before it expires.
| Operation | HTTP Action | Example |
|---|---|---|
| Generate a token for a user (Log in) | POST /v1/users/<user-name> | curl -X POST $AUTHSRV/v1/users/<user-name> -d '{"password":"<password>"}' |
| Revoke a token | DELETE /v1/tokens | curl -X DELETE $AUTHSRV/v1/tokens -d '{"token":"<issued_token>"}' -H 'Content-Type: application/json' |
Clusters
When a cluster is registered, an arbitrary alias can be assigned to the cluster. The CLI supports both the cluster’s ID and the cluster’s alias in commands. The alias is used to create default roles for a newly registered cluster. If a cluster does not have an alias, the role names contain the cluster ID.
| Operation | HTTP Action | Example |
|---|---|---|
| Get a list of registered clusters | GET /v1/clusters | curl -X GET $AUTHSRV/v1/clusters |
| Get a registered cluster’s info | GET /v1/clusters/cluster-id | curl -X GET $AUTHSRV/v1/clusters/cluster-id |
| Register a cluster | POST /v1/clusters | curl -X POST $AUTHSRV/v1/clusters -d '{"id": "<cluster-id>", "alias": "<cluster-alias>", "urls": ["<http://host:port>"]}' -H 'Content-Type: application/json' -H 'Authorization: Bearer <token>' |
| Update a registered cluster | PUT /v1/clusters/<cluster-id> | curl -X PUT $AUTHSRV/v1/clusters/<cluster-id> -d '{"id": "<cluster-id>", "alias": "<cluster-alias>", "urls": ["http://host:port"]}' -H 'Content-Type: application/json' -H 'Authorization: Bearer <token>' |
| Delete a registered cluster | DELETE /v1/clusters/<cluster-id> | curl -X DELETE $AUTHSRV/v1/clusters/<cluster-id> -H 'Authorization: Bearer <token>' |
Roles
| Operation | HTTP Action | Example |
|---|---|---|
| Get a list of roles | GET /v1/roles | curl -X GET $AUTHSRV/v1/roles |
| Get a role | GET /v1/roles/<role-name> | curl -X GET $AUTHSRV/v1/roles/<role-name> |
| Create a new role | POST /v1/roles/ | curl -X POST $AUTHSRV/v1/roles/ -d '{"name":"<role-name>","desc":"<role-desc>","clusters":[{"id":"<cluster-id>","perm":"<permission-number>"}],"buckets":[{"bck":{"name":"<bck-name>","provider":"<bck-provider>","namespace":{"uuid":"<namespace-id>","name":""}},"perm":"<permission-number>"}],"admin":false}' -H 'Content-Type: application/json' -H 'Authorization: Bearer <token>' |
| Update an existing role | PUT /v1/roles/<role-name> | curl -X PUT $AUTHSRV/v1/roles/<role-name> -d '{"name":"<role-name>","desc":"<role-desc>","clusters":[{"id":"<cluster-id>","perm":"<permission-number>"}],"buckets":[{"bck":{"name":"<bck-name>","provider":"<bck-provider>","namespace":{"uuid":"<namespace-id>","name":""}},"perm":"<permission-number>"}],"admin":false}' -H 'Content-Type: application/json' -H 'Authorization: Bearer <token>' |
| Delete a role | DELETE /v1/roles/<role-name> | curl -X DELETE $AUTHSRV/v1/roles/<role-name> -H 'Content-Type: application/json' -H 'Authorization: Bearer <token>' |
Users
| Operation | HTTP Action | Example |
|---|---|---|
| Get a list of users | GET /v1/users | curl -X GET $AUTHSRV/v1/users -H 'Authorization: Bearer <token>' |
| Get a user | GET /v1/users/<user-id> | curl -X GET $AUTHSRV/v1/users/<user-id> -H 'Authorization: Bearer <token>' |
| Add a user | POST /v1/users | curl -X POST $AUTHSRV/v1/users -d '{"id": "<user-id>", "password": "<password>", "roles": "[{<role-json>}]"' -H 'Authorization: Bearer <token>' |
| Update an existing user | PUT /v1/users/<user-id> | curl -X PUT $AUTHSRV/v1/users/<user-id> -d '{"id": "<user-id>", "password": "<password>", "roles": "[{<role-json>}]"' -H 'Authorization: Bearer <token>' |
| Delete a user | DELETE /v1/users/<user-id> | curl -X DELETE $AUTHSRV/v1/users/<user-id> -H 'Authorization: Bearer <token>' |
Note: A user can update their own password without admin privileges by issuing
PUT /v1/users/<user-id>with only thepasswordfield set, authorized with their own token. A user can also retrieve their own user info viaGET /v1/users/<user-id>using their own token.
Configuration
| Operation | HTTP Action | Example |
|---|---|---|
| Get AuthN configuration | GET /v1/daemon | curl -X GET $AUTHSRV/v1/daemon -H 'Authorization: Bearer <token>' |
| Update AuthN configuration | PUT /v1/daemon | curl -X PUT $AUTHSRV/v1/daemon -d '{"log":{"dir":"<log-dir>","level":"<log-level>"},"net":{"http":{"port":<port>,"use_https":false,"server_crt":"","server_key":""}},"auth":{"secret":"aBitLongSecretKey","expiration_time":"24h0m"},"timeout":{"default_timeout":"30s"}}' -H 'Authorization: Bearer <token>' |