Upgrade Guides

Upgrade Your Authentication Flow to OAuth 2.0

This guide helps you upgrade your Kiteworks API integration from a deprecated authentication flow — Signature or User Credentials — to a supported OAuth 2.0 flow. To upgrade, update the client registration in Admin UI and update your token-acquisition code.

Prerequisites

1

Admin access to Kiteworks Admin UI

You must have permission to edit client application settings under Application Setup → Apps and Plugins.

2

Your existing client_id and client_secret

These carry over to the new flow unchanged. You only need to regenerate the secret if it was previously exposed.

3

For JWT Assertion: an RSA key pair (optional)

You can generate a key pair directly in Admin UI or upload your own PEM-encoded public key. Only required if you are upgrading to JWT Assertion.

Who Is Affected

This guide applies to integrations using the Signature flow (HMAC-based) or the User Credentials flow (grant_type=password).

To check which flow your client uses, see Check Your API Version or go to Admin UI → Application Setup → Apps and Plugins → API → [your client], where you can see the registered flow.

Which Flow Should I Use?

Choose your target flow based on how your application operates:

Use Case Recommended Flow Reason
User logs in via browser / user-initiated workflow Authorization Code Flow (shown as Connect (Authorization Code) in Admin UI) User authenticates in browser; your application never handles their credentials
Automated / server-to-server (machine-to-machine) JSON Web Token (JWT) Assertion Requires no user interaction; secure for trusted server environments
JWT Assertion allows impersonation of Kiteworks users. It must only be used by clients operating in secure, trusted server environments. It is not appropriate for publicly accessible clients.

Step 1 — Identify Your Current Flow

Signature Flow

The Signature flow uses a time-based Hash-based Message Authentication Code (HMAC) signature computed from client_id + client_secret + timestamp. No user account is associated; activity does not appear in audit logs. Kiteworks removed the Signature flow from Admin UI registration in version 9.1.

To identify: In Admin UI → Application Setup → Apps and Plugins → API, the client's registered flow shows as "Signature." In your code, look for HMAC signature construction — typically a string like:

python
import hmac, hashlib, time

timestamp = str(int(time.time()))
message   = client_id + client_secret + timestamp
sig       = hmac.new(client_secret.encode(), message.encode(), hashlib.sha256).hexdigest()

User Credentials Flow

The User Credentials flow (OAuth 2.0 Resource Owner Password Credential) submits a username and password directly in the token request body. Kiteworks removed the User Credentials flow from Admin UI in version 9.0.

To identify: Look for grant_type=password in token requests:

bash
curl -s -X POST "https://your-instance.kiteworks.com/oauth/token" \
  -d "grant_type=password&username=user@example.com&password=SECRET&client_id=MY_APP&client_secret=MY_SECRET"

Step 2 — Register the New Flow in Admin UI

Before changing your code, update the client's registered flow in Admin UI. Steps 1–4 apply to both flows; step 5 depends on which flow you're upgrading to.

  1. Open the API clients settings
    Navigate to Admin UI → Application Setup → Apps and Plugins → API.
  2. Select your client application
    Choose the application your integration uses.
  3. Open the Flows tab
    Go to Settings → Flows.
  4. Select the new flow
    Change the flow to Connect (Authorization Code) or JWT Assertion depending on your use case.

If upgrading to Authorization Code Flow:

  1. Configure the Redirect URI
    Set the Redirect URI to the HTTPS callback URL your application handles after login — for example, https://your-app.example.com/callback. Your application must serve an endpoint at this URL to receive the authorization code.

If upgrading to JWT Assertion:

  1. Configure the RSA key pair
    Upload or generate an RSA key pair; note the UID attribute (determines the user to impersonate — typically email).
Flows settings panel in Admin UI showing four checkboxes: Authorization Code, JWT, Signature Authorization, and User Credentials
Flows panel in Admin UI — select Authorization Code or JWT to replace the deprecated flow.

Step 3A — Implement Authorization Code Flow

To implement the Authorization Code Flow (RFC 6749 §4.1), complete the following steps. The user authenticates at the Kiteworks login page; your application exchanges the returned authorization code for an access token.

  1. Redirect the user to the authorization endpoint
    Start the flow with the required client_id, redirect_uri, response_type=code, and state parameters.
  2. Receive the authorization code
    After login, Kiteworks redirects to your redirect_uri with a code and state parameter.
  3. Exchange the code for tokens
    Verify the state parameter matches the value you set when starting the flow (Cross-Site Request Forgery (CSRF) protection), then POST to the token endpoint to exchange the code for tokens.
  4. Attach required headers to all API requests
    Use Authorization: Bearer <access_token> and X-Accellion-Version: 28 on all API requests.
  5. Refresh tokens before expiry
    Use the refresh token to obtain new access tokens before they expire.

Endpoints:

  • Authorization endpoint: GET {KW_BASE_URL}/oauth/authorize
  • Token endpoint: POST {KW_BASE_URL}/oauth/token

Token exchange:

exchange-code.sh
# Exchange authorization code for tokens
curl -s -X POST "https://your-instance.kiteworks.com/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=AUTHORIZATION_CODE" \
  -d "redirect_uri=https://your-app.example.com/callback" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"
exchange_code.py
import requests

# AUTHORIZATION_CODE comes from the ?code= query parameter in the redirect
# In Flask:  AUTHORIZATION_CODE = request.args.get("code")
# In Django: AUTHORIZATION_CODE = request.GET.get("code")
AUTHORIZATION_CODE = "YOUR_AUTHORIZATION_CODE"  # replace with actual value from redirect

token_url = "https://your-instance.kiteworks.com/oauth/token"
data = {
    "grant_type":    "authorization_code",
    "code":          AUTHORIZATION_CODE,
    "redirect_uri":  "https://your-app.example.com/callback",
    "client_id":     CLIENT_ID,
    "client_secret": CLIENT_SECRET,
}
resp  = requests.post(token_url, data=data)
tokens = resp.json()
access_token  = tokens["access_token"]
refresh_token = tokens["refresh_token"]

Refresh token:

refresh-token.sh
curl -s -X POST "https://your-instance.kiteworks.com/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=REFRESH_TOKEN" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"
refresh_token.py
import requests

token_url = "https://your-instance.kiteworks.com/oauth/token"
data = {
    "grant_type":    "refresh_token",
    "refresh_token": current_refresh_token,   # the token stored from the previous response
    "client_id":     CLIENT_ID,
    "client_secret": CLIENT_SECRET,
}
resp = requests.post(token_url, data=data)
tokens = resp.json()
new_access_token  = tokens["access_token"]
new_refresh_token = tokens["refresh_token"]   # replace stored token with this value

For a complete Python implementation including the browser redirect and callback server, see Authentication → Authorization Code flow.

Step 3B — Implement JWT Assertion Flow

The JWT Assertion flow is the OAuth 2.0 JWT Bearer token grant (RFC 7523). It requires no user interaction — your application constructs a signed JWT and exchanges it for an access token.

Claim Description Example
iss Issuer — your client_id my_app_client_id
sub Subject — email of the Kiteworks user to impersonate user@example.com
aud Audience — the Kiteworks token endpoint URL https://kw.example.com/oauth/token
iat Issued-at time (Unix timestamp) 1712768400
exp Expiration time (max 5 minutes from iat) 1712768700
jti Unique JWT ID (prevents replay attacks) a3f8c1d2-...

Signing algorithm: RS256 (RSA with SHA-256). Token endpoint: POST {KW_BASE_URL}/oauth/token

Construct and exchange JWT:

jwt-assertion.sh
# Generate a signed JWT first (e.g. with step CLI or openssl), then exchange:
curl -s -X POST "https://your-instance.kiteworks.com/oauth/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" \
  -d "assertion=YOUR_SIGNED_JWT" \
  -d "client_id=YOUR_CLIENT_ID"
jwt_assertion.py
# pip install PyJWT requests
import time, uuid, jwt, requests

# Load the RSA private key (PEM format) registered in Admin UI → Apps and Plugins → Flows
PRIVATE_KEY_PEM = open("private_key.pem").read()
CLIENT_ID       = "your_client_id"
KW_BASE_URL     = "https://your-instance.kiteworks.com"
USER_EMAIL      = "user@example.com"

now = int(time.time())
payload = {
    "iss": CLIENT_ID,
    "sub": USER_EMAIL,
    "aud": f"{KW_BASE_URL}/oauth/token",
    "iat": now,
    "exp": now + 300,   # 5 minutes
    "jti": str(uuid.uuid4()),
}
assertion = jwt.encode(payload, PRIVATE_KEY_PEM, algorithm="RS256")

resp = requests.post(
    f"{KW_BASE_URL}/oauth/token",
    data={
        "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
        "assertion":  assertion,
        "client_id":  CLIENT_ID,
    },
)
access_token = resp.json()["access_token"]
JWT Assertion does not return a refresh token. Generate a new JWT and request a new access token as needed.

For a complete implementation guide, see Authentication → JWT Assertion flow.

Step 4 — Update All API Calls

Regardless of which flow you selected, all API requests must include Authorization: Bearer and the API version header:

api-call.sh
curl -s \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "X-Accellion-Version: 28" \
  "https://your-instance.kiteworks.com/rest/folders/top"
api_call.py
session = requests.Session()
session.headers.update({
    "Authorization":       f"Bearer {access_token}",
    "X-Accellion-Version": "28",
})

response = session.get(f"{KW_BASE_URL}/rest/folders/top")
Your existing client secret does not need to change. The same client secret used in the old flow works in the new flow.

Frequently Asked Questions

The following questions address common concerns when upgrading authentication flows.

Kiteworks recommends OAuth 2.0-based authentication. Use Authorization Code Flow (shown as Connect (Authorization Code) in Admin UI) when a user logs in interactively via a browser. Use JWT Assertion for machine-to-machine automation without user interaction. JWT Assertion is only for use in secure, trusted server environments.

Do I need to regenerate my client secret when upgrading authentication flows?

No. The client secret used in old flows continues to work in the new flows. You only need to regenerate it if it was previously exposed.

Does JWT Assertion return a refresh token?

No. JWT Assertion does not return a refresh token. Generate a new signed JWT and request a new access token when the current token expires.

Can I use JWT Assertion in a public-facing web application?

No. JWT Assertion allows impersonation of Kiteworks users and requires access to an RSA private key. It must only be used in secure, trusted server environments — never in client-side or publicly accessible applications.

What happens to my existing API calls during the upgrade?

Your existing API calls continue to work until you update the client registration in Admin UI. After changing the registered flow, update your code to request tokens using the new flow before deploying.

Next Steps

You've upgraded your authentication flow. Here's what to do next: