Personal Access Tokens (PAT) & Key Management

This guide provides a comprehensive overview of Personal Access Tokens (PAT) on the Milesoft Platform. It explains what they are, how to acquire one, how to configure them for secure cloud operations, and how to utilize IntelliJ's native HTTP Client to manage keys directly against your Google Cloud Run deployment.


1. What is a Personal Access Token (PAT)?

On the Milesoft Platform, a Personal Access Token (PAT) is a secure API key utilized for service-to-service, cron, webhook, or administrator authentication. When you bootstrap an application using milesoft init app, the scaffolded project includes a suite of HTTP request templates in src/test/http/requests.http (see our IntelliJ HTTP Client Guide for setup and configuration details) designed to let you interact with, secure, and operate your running microservice.

Unlike interactive user sessions that leverage short-lived JWTs (JSON Web Tokens), PATs are long-lived tokens linked to cryptographic credentials managed by the Milesoft central gateway. To authorize HTTP requests against your Cloud Run service, you supply a PAT in the Authorization header as a Basic auth credential:

Authorization: Basic {{pat}}

Because your microservice has already been deployed to Google Cloud Run (Milestone 3), these requests execute directly against your secure live cloud endpoint, leveraging your environment settings.

🛡️ Why call the live GCP application? When you initialize a key, your deployed application must securely handshake with the central Milesoft gateway. Here is how the security model operates behind the scenes:

  • Secure Key Storage: Generating a production PAT requires your unique, proprietary Milesoft API Key, which is securely loaded into your Google Cloud environment and stored inside GCP Secret Manager. This key is never exposed locally or saved in source control.
  • Automatic Scaffolding Orchestration: The bootstrapped Spring Boot application scaffolding automatically handles the entire cryptographic handshake, Secret Manager retrieval, and signature validation for you out-of-the-box.
  • Nonce Security: The CLI-generated Key Nonce serves as a secure, short-lived, single-use token claim. Utilizing a nonce guarantees that the initialization handshake cannot be intercepted, replayed, or spoofed, protecting your platform credential integrity.

2. Step-by-Step: Acquiring your PAT

Acquiring your Personal Access Token involves a secure two-step exchange: creating a Key Nonce via the Milesoft CLI, and then initializing that nonce on your deployed application to retrieve the active token.

Instead of writing verbose shell scripts, you can perform this entire flow inside of IntelliJ IDEA using the generated src/test/http/requests.http template file (refer to the IntelliJ HTTP Client Guide for detailed environment setup instructions).

Step 1: Create a Key Nonce using the Milesoft CLI

Ensure you are logged in to your Milesoft gateway (milesoft login). Run the following command in your terminal to generate a one-time cryptographic nonce with the desired roles (e.g., ROLE_OPS for developer operations):

milesoft key create --roles ROLE_OPS

The CLI will output the generated nonce:

=========================================================================
             Created Key Nonce
=========================================================================
Nonce:         test-nonce-abc-123
=========================================================================

Alternatively, you can output as JSON for shell automation:

milesoft key create --roles ROLE_OPS --json
{
  "nonce": "test-nonce-abc-123"
}

Note: The generated nonce is a short-lived claim. It cannot be used directly as a PAT; it must be initialized on your microservice.


Step 2: Initialize the Key

With your microservice deployed live on Google Cloud Run, you need to initialize your key. You can do this either via IntelliJ IDEA or via the Terminal using curl.

Option A: Initialize via IntelliJ IDEA

Open your project in IntelliJ and navigate to src/test/http/requests.http.

  1. Select your target environment (e.g., prod) in the top-right of the HTTP editor window. This sets {{baseUrl}} to point to your Cloud Run URL.
  2. Locate the ### Initialize key request:
### Initialize key
POST {{baseUrl}}/api/v1/key/initialize
Accept: application/json
Content-Type: application/json

{
  "name": "your_name",
  "nonce": "test-nonce-abc-123"
}
  1. Replace "test-nonce-abc-123" with your CLI-generated nonce, and replace "your_name" with a descriptive name of your choice (e.g. your name or workstation ID) to easily identify this PAT later.
  2. Click the green "Play/Arrow" icon in the left gutter next to ### Initialize key to run the request!

Option B: Initialize via Terminal (curl)

If you are using VS Code, Neovim, or a terminal-only workflow, you can initialize your key by executing a standard POST request using curl.

Replace https://your-app-url.a.run.app with your deployed Cloud Run service URL, "test-nonce-abc-123" with your CLI-generated nonce, and "your_name" with any descriptive name you would like to call this PAT for easy identification later:

curl -X POST https://your-app-url.a.run.app/api/v1/key/initialize \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "your_name",
    "nonce": "test-nonce-abc-123"
  }'

Response Payload (FreshKey):

{
  "id": "key_01jh986abcdfeg",
  "name": "your_name",
  "roles": [
    "ROLE_OPS"
  ],
  "token": "ms_pat_live_7f84b5c689d2e140a370e5178fc9b0",
  "lastUsed": null
}

The "token" field in the response (e.g. ms_pat_live_7f84b5c689d2e140a370e5178fc9b0) is your active Personal Access Token (PAT). This is the only time it will be shown!


Step 3: Configure Your Client Environment

To authorize all subsequent HTTP calls against your Cloud Run service, configure your environment with your retrieved PAT.

Option A: IntelliJ Environment Setup

To authorize requests within src/test/http/requests.http:

  1. Open src/test/http/http-client.private.env.json (this file is pre-configured and git-ignored by default for security).
  2. Save your retrieved PAT under the "pat" variable:
{
  "prod": {
    "pat": "ms_pat_live_7f84b5c689d2e140a370e5178fc9b0"
  }
}

Once saved, any request containing Authorization: Basic {{pat}} can be executed by clicking its green play button. It will authenticate automatically!

Option B: Terminal / Shell Environment Setup

If you are operating from the terminal, export your PAT as an environment variable:

export MILESOFT_PAT="ms_pat_live_7f84b5c689d2e140a370e5178fc9b0"

You can then reference this environment variable in your terminal curl commands.

Security & Authentication Note: The Milesoft Platform parses the Authorization: Basic <token> header by extracting the raw token value directly after the prefix (without standard base64-decoding). When writing custom scripts or using curl, pass your token as a raw string directly after Basic (e.g. -H "Authorization: Basic $MILESOFT_PAT"), rather than using standard curl -u credentials which automatically base64-encode the payload.


3. Understanding Roles & Cloud Endpoint Security

Your microservice secures endpoints using Spring Security via SecurityConfig.java. When verifying an incoming PAT, the Milesoft platform token resolver extracts the authorities/roles associated with that key.

3.1 Developer & Operations Roles (ROLE_OPS)

The ROLE_OPS role represents high-privileged administrative and developer operations.

As defined in SecurityConfig.java, endpoints that manage keys, trigger migrations, or perform cache invalidation require the ROLE_OPS authority:

customizer
    .requestMatchers("/api/v1/key/initialize").permitAll() // Exchange nonce (public)
    .requestMatchers("/api/v1/key/**").hasAuthority(OPS)   // Key creation, deletion, listing
    .requestMatchers("/api/v1/dataMigration/**").hasAuthority(OPS) // Data migration routines

Only trusted developers, administrators, or deployment scripts should possess keys with ROLE_OPS capability.

Option A: List keys in IntelliJ

Execute the ### List keys request in src/test/http/requests.http using the green play arrow:

### List keys
GET {{baseUrl}}/api/v1/key/list
Authorization: Basic {{pat}}
Accept: application/json

Option B: List keys via Terminal (curl)

Execute the following curl command using your exported $MILESOFT_PAT env variable (replace https://your-app-url.a.run.app with your Cloud Run URL):

curl -X GET https://your-app-url.a.run.app/api/v1/key/list \
  -H "Authorization: Basic $MILESOFT_PAT" \
  -H "Accept: application/json"

3.2 Third-Party & Integration Roles (ROLE_GUEST)

For external consumers, automated tasks, webhooks, and cron jobs, you should restrict access to prevent privilege escalation. This is accomplished using the ROLE_GUEST role.

Here are generic example endpoints in SecurityConfig.java demonstrating how you can grant limited access to a GUEST-role key:

customizer
    // Example third-party/integration endpoints requiring GUEST role
    .requestMatchers("/api/v1/cron/**").hasAuthority(GUEST)
    .requestMatchers("/api/v1/webhook/**").hasAuthority(GUEST)
    .requestMatchers("/api/v1/integration/**").hasAuthority(GUEST)

To issue a restricted GUEST key to an external partner or cron pipeline, choose one of the options below:

Option A: Create key in IntelliJ

Execute the ### Create third-party GUEST key block in your src/test/http/requests.http file:

### Create third-party GUEST key (restricted access)
POST {{baseUrl}}/api/v1/key/create
Authorization: Basic {{pat}}
Accept: application/json
Content-Type: application/json

{
  "name": "third_party_cron_partner",
  "roles": [
    "ROLE_GUEST"
  ]
}

Option B: Create key via Terminal (curl)

Execute the following curl command using your exported $MILESOFT_PAT env variable (replace https://your-app-url.a.run.app with your Cloud Run URL):

curl -X POST https://your-app-url.a.run.app/api/v1/key/create \
  -H "Authorization: Basic $MILESOFT_PAT" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "name": "third_party_cron_partner",
    "roles": [
      "ROLE_GUEST"
    ]
  }'

This request returns a FreshKey payload with a token that can only invoke endpoints configured with .hasAuthority(GUEST) and cannot manage other keys, list credentials, or execute migrations.


4. Summary of Key Roles

Role Intended Audience Example Endpoints Purpose
ROLE_OPS Developers, DevOps, Admins /api/v1/key/**, /api/v1/dataMigration/** Cloud deployment, key management, database migrations
ROLE_GUEST Automated Crons, Webhooks, Integrations /api/v1/cron/**, /api/v1/webhook/**, /api/v1/integration/** Limited third-party integration, restricted automations

5. Verify Your Deployment

Once you have initialized your PAT and configured it in your http-client.private.env.json (for IntelliJ) or exported it in your terminal, the final step of Milestone 4 is to verify that your deployment works and your credentials authenticate properly.

The best way to verify your connection is to execute the "Data migration - example" request.

Why the Data Migration Endpoint?

  • Proof of Authentication: By default, the /api/v1/dataMigration/** endpoints are protected by ROLE_OPS. Testing this endpoint ensures that your microservice is resolving your PAT and extracting its authorities correctly.
  • Safe Dry Run: In the initial bootstrapped template, this data migration endpoint is a safe, idempotent no-op (no actual data is mutated). It is engineered specifically as an integration checkpoint for onboarding developers.
  • Failure Modes:
    • If your PAT or billing setup is incorrect, you will receive an HTTP 401 Unauthorized error.
    • If the service connects and your credentials are correct, you will receive a successful HTTP 200 OK response.

Option A: Verify via IntelliJ IDEA

Open your project in IntelliJ and navigate to src/test/http/requests.http.

  1. Select your target environment (e.g., prod) in the top-right of the HTTP editor window.
  2. Locate the ### Data migration - example block:
### Data migration - example
POST {{baseUrl}}/api/v1/dataMigration/example
Authorization: Basic {{pat}}
Accept: application/json
  1. Click the green "Play/Arrow" icon in the left gutter next to ### Data migration - example to run the request.
  2. Verify the response pane: You should see a successful HTTP/1.1 200 OK status.

Option B: Verify via Terminal (curl)

If you are operating from the terminal, execute the following curl command using your exported $MILESOFT_PAT env variable (replace https://your-app-url.a.run.app with your Cloud Run URL):

curl -i -X POST https://your-app-url.a.run.app/api/v1/dataMigration/example \
  -H "Authorization: Basic $MILESOFT_PAT" \
  -H "Accept: application/json"

Verify that the output starts with:

HTTP/1.1 200 OK

6. Next Steps: Customizing Your Deployed App

Now that your deployment is verified and authenticating, you have successfully completed the core developer onboarding milestones!

As you transition from a boilerplate scaffolding to writing business logic, the migration endpoints (such as POST /api/v1/dataMigration/example) will become crucial. Later in development, you can use these migration endpoints to safely seed reference tables, trigger schema migrations, or initialize document templates.

To learn how to start defining your own custom database models, creating schemaless documents, and extending your REST boundaries, head over to the Customizing Your App Guide.