---
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

title: "Using Authentication"
description: "Log in, call APIs, manage tokens, and create Scoped Access Keys."
---
How to log in, make authenticated API calls, manage tokens, and create Scoped Access Keys with the CLI and SDK.

**Prerequisites**: For OIDC login, configure an identity provider first. See [OIDC](/documentation/access-control/authentication/oidc-setup). For local testing without OIDC, use `nemo auth login --unsigned-token --email <email>`. Scoped Access Keys also require the administrator to enable `auth.access_keys.enabled`; see [Authentication Configuration](/documentation/access-control/deployment#scoped-access-keys).

## Log In

The device flow is the recommended login method. It opens your browser to authenticate with your organization's identity provider.

```bash
nemo auth login
```

Expected output:

```text
To sign in, use a web browser to open the page https://microsoft.com/devicelogin
and enter the code ABCD-EFGH to authenticate.
Waiting for authentication...
```

Open the URL, enter the code, and sign in with your IdP credentials. After consent, verify:

```bash
nemo auth status
```

```text
Authentication Status
Cluster             https://nmp.company.com
Context             default
Config File         /home/alice/.config/nmp/config.yaml
Auth Type           oauth
Credential Source   config file
Email               alice@company.com
Scopes              platform:read platform:write
Expires             2026-02-15T14:30:00+00:00 (1h 0m remaining)
Refresh Token       available (run 'nemo auth refresh' to renew)
Token               eyJhbGciOiJSUzI1NiIs...abc1234567
```

All CLI and SDK commands now use the stored token automatically.

### Requesting Specific Scopes

By default, the CLI requests the scopes configured in `auth.oidc.default_scopes` (typically `platform:read platform:write` plus OIDC standard scopes like `openid profile email offline_access`). Restrict the token's access by specifying fewer scopes:

```bash
nemo auth login --scope "platform:read"
```

See [API Scopes](/documentation/access-control/authorization/api-scopes) for the full list of available scopes.

### Non-Interactive Login (CI/CD)

For CI pipelines, use the password grant to obtain a token without a browser: `nemo auth login --username <user> --password <pass>` (or set `NMP_OIDC_USERNAME` / `NMP_OIDC_PASSWORD` environment variables). If your CI system can obtain tokens directly (e.g., workload identity federation), pass the token via `access_token` as shown in [Make API Calls](#make-api-calls) below.

<Warning>

Password grant sends credentials directly to the IdP and **bypasses MFA**. Many production IdPs disable it. Use a dedicated service account with minimal scopes where possible.

</Warning>
## Make API Calls

### Python SDK

The SDK reads credentials from the CLI config automatically — no manual token handling needed:

```python
from nemo_platform import NeMoPlatform

# After `nemo auth login` (OIDC) or `nemo auth login --unsigned-token --email <email>` (quickstart),
# the SDK reads base_url, workspace, and the stored token from the CLI config.
# This is the recommended pattern for interactive / OIDC-authenticated usage.
client = NeMoPlatform()

workspaces = client.workspaces.list()
```

If you need explicit token control (for example, a token from a CI system or environment variable), pass it via `access_token`:

```python
import os
from nemo_platform import NeMoPlatform

client = NeMoPlatform(
    base_url=os.environ.get("NMP_BASE_URL", "http://localhost:8080"),
    workspace="default",
    access_token=os.environ.get("NMP_ACCESS_TOKEN"),
)
```

### HTTP (curl)

```bash
TOKEN=$(nemo auth token)
curl -H "Authorization: Bearer $TOKEN" \
 https://nmp.company.com/apis/entities/v2/workspaces
```

## Scoped Access Keys for Non-SDK Clients

When Scoped Access Keys are enabled by the platform administrator, an
authenticated user can mint a scoped bearer token for automation that cannot use
the SDK's OIDC refresh flow:

```bash
# Create a Scoped Access Key with the platform default expiry and print the token once.
nemo auth access-keys create --name ci-build --description "CI build automation"
```

Scoped Access Key management commands live under the `auth` namespace as
`nemo auth access-keys ...`. The `access-keys` command group is not a top-level CLI
command and is not a separate NeMo Platform plugin.

`create` prints the Scoped Access Key token once. Store it in your secret
manager and send it in the standard `Authorization` header:

```bash
curl -H "Authorization: Bearer $NMP_SCOPED_ACCESS_KEY" \
 https://nmp.company.com/apis/entities/v2/workspaces
```

Scoped Access Keys are signed JWT bearer tokens scoped to the principal and
groups present when the key is created. By default, new keys use the platform's
configured default expiry, which is 30 days unless the administrator changes it.
Pass `--expires-in <seconds>` to request a specific finite lifetime. Pass
`--expires-in none` only for deployments where the administrator has explicitly
allowed unlimited keys.

List keys or revoke one by its stable `jti`:

```bash
nemo auth access-keys list
nemo auth access-keys list --page 2 --page-size 100
nemo auth access-keys revoke ak_0123456789abcdef0123456789abcdef
```

The list includes each key's `ACTIVE`, `EXPIRED`, or `REVOKED` status plus its
description, issuer, audiences, creation time, and expiration time. Revocation takes
effect on subsequent authenticated platform requests. Rotation is not implemented.

### Token Inspection

Retrieve the raw JWT for debugging or use in other clients:

```bash
nemo auth token
```

Decode the token to inspect claims:

```bash
nemo auth token --decode
```

Key claims to check:

- `email` or `upn` — the principal identity
- `scp` or `scope` — granted scopes
- `exp` — expiry timestamp
- `iss` — issuer URL (must match your config)
- `aud` — audience (must match your config)

## Token Management

### How Auto-Refresh Works

You never need to refresh tokens manually — the CLI and SDK handle it transparently:

- **SDK**: Refreshes lazily before each API call when the token is within 60 seconds of expiry. No background threads or timers — the cost is paid only when a refresh is actually needed (typically once per hour). Multiple `NeMoPlatform()` clients in the same Python process share a single token, so only one refresh happens even with many clients.
- **CLI**: Checks the token before every command and refreshes if it expires within 5 minutes. To disable for a specific command: `nemo --no-auto-refresh workspaces list`.

Running multiple scripts or CLI commands simultaneously is safe — file-level locking prevents conflicts when refreshing tokens across processes.

If the refresh token itself has expired (e.g., after days of inactivity), re-login with `nemo auth login`.

### Manual Refresh and Logout

```bash
# Force a token refresh
nemo auth refresh

# Clear stored tokens
nemo auth logout
```


### Config File

Tokens are stored in `~/.config/nmp/config.yaml`:

```yaml
users:
  - name: default
    type: oauth
    token: "<access_token_jwt>"
    refresh_token: "<refresh_token>"
```

The OIDC token endpoint is **not** stored — it is discovered at runtime from your cluster's `/apis/auth/discovery` endpoint. This keeps the config portable across environments.

<Warning>

**Token storage security** — Access and refresh tokens are stored in plaintext. Protect this file:

- **File permissions**: Ensure `0600` (owner read/write only). The CLI sets this by default — verify after manual edits: `chmod 600 ~/.config/nmp/config.yaml`.
- **Shared directories**: Do not store in cloud-synced folders (Dropbox, OneDrive, Google Drive) or shared home directories.
- **Refresh token rotation**: Configure your IdP to rotate refresh tokens on each use. A stolen refresh token becomes invalid after the legitimate client uses it once.
- **Logout when done**: Run `nemo auth logout` on shared or temporary machines.

</Warning>
## Related

- [OIDC](/documentation/access-control/authentication/oidc-setup) — Configure your identity provider.
- [API Scopes](/documentation/access-control/authorization/api-scopes) — Scope model and available scopes.
- [Security Model](/documentation/access-control/security-model) — Trust boundaries and the principal model.
- [Troubleshooting](/documentation/access-control/troubleshooting) — Fix common 401/403 errors and login failures.
