API Authentication

March 3, 2026 ยท View on GitHub

LogisticsX uses OAuth 2.0 / OpenID Connect via Duende IdentityServer.

Identity Server URLs

EnvironmentURL
Developmenthttps://localhost:7001
Productionhttps://id.yourdomain.com

OpenID Configuration

Discovery document:

GET /.well-known/openid-configuration

Authentication Flow

1. Resource Owner Password (Direct Login)

For first-party applications (Office App, Driver App):

POST /connect/token HTTP/1.1
Host: id.yourdomain.com
Content-Type: application/x-www-form-urlencoded

grant_type=password
&client_id=logisticsx.client
&client_secret=client_secret
&username=user@example.com
&password=password123
&scope=openid profile logisticsx.api

Response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "abc123...",
  "scope": "openid profile logisticsx.api"
}

2. Authorization Code (Third-Party)

For external integrations:

GET /connect/authorize?
  response_type=code
  &client_id=third_party_app
  &redirect_uri=https://app.example.com/callback
  &scope=openid profile logisticsx.api
  &state=random_state

3. Refresh Token

POST /connect/token HTTP/1.1
Host: id.yourdomain.com
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&client_id=logisticsx.client
&client_secret=client_secret
&refresh_token=abc123...

Using Access Tokens

Include the token in the Authorization header:

GET /api/loads HTTP/1.1
Host: api.yourdomain.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

Token Claims

Access tokens contain:

ClaimDescription
subUser ID
emailUser email
nameDisplay name
roleUser role(s)
tenantTenant ID

Example decoded token:

{
  "sub": "user-123",
  "email": "dispatcher@company.com",
  "name": "John Doe",
  "role": "Dispatcher",
  "tenant": "default",
  "iat": 1704067200,
  "exp": 1704070800
}

Role-Based Authorization

Endpoints check roles:

[Authorize(Roles = "Owner,Manager")]
[HttpPost("loads")]
public async Task<IActionResult> CreateLoad(...)

Role Hierarchy

RolePermissions
SuperAdminSystem-wide access
OwnerFull tenant access
ManagerOperational access
DispatcherLoad/trip management
DriverView assigned loads

API Configuration

In appsettings.json:

{
  "IdentityServer": {
    "Authority": "https://id.yourdomain.com",
    "Audience": "logisticsx.api",
    "ValidIssuers": [
      "https://id.yourdomain.com",
      "https://localhost:7001"
    ]
  }
}

Client Configuration

Angular (Office App)

// environment.ts
export const environment = {
  identityUrl: 'https://id.yourdomain.com',
  apiUrl: 'https://api.yourdomain.com',
  clientId: 'logisticsx.office'
};

Mobile App

object AuthConfig {
    const val AUTHORITY = "https://id.yourdomain.com"
    const val CLIENT_ID = "logisticsx.mobile"
    const val REDIRECT_URI = "logisticsx://callback"
}

Token Storage

PlatformRecommended Storage
BrowserMemory (not localStorage)
MobileSecure storage (Keychain/Keystore)
ServerEnvironment variables

Troubleshooting

Invalid Token

  • Check token expiration
  • Verify issuer matches configuration
  • Ensure audience is correct

CORS Errors

Verify Identity Server CORS settings include your app's origin.

Clock Skew

Tokens may fail if server clocks are out of sync. Use NTP:

sudo ntpdate -u pool.ntp.org

Next Steps