Overview
Cora PPM exposes a REST API secured by an OAuth 2.0 identity server (IdentityServer). Any external tool or platform — such as n8n, Power BI, Microsoft Teams apps, or custom integrations — can connect to the Cora API to read and write project data on behalf of a specific user or a service account, provided the correct OAuth client credentials are configured in Cora by an administrator.
This article explains the two supported authentication patterns, how to configure them for common API client platforms, and what a Cora administrator needs to set up in IdentityServer for each.
Prerequisites
A Cora PPM site URL (e.g.,
https://yoursite.corasystems.com/YourInstance)A Cora PPM user account with appropriate permissions, or a dedicated service account for background/automated access
An API client registered in Cora IdentityServer — ask your Cora administrator
The following details provided by your Cora administrator:
Client ID — identifies your integration
Client Secret — required for the client credentials flow (server-to-server only)
Scope — typically
pvfor Cora PPM access
Understanding the Two Authentication Patterns
Cora's IdentityServer supports two OAuth 2.0 grant types. Which one you use depends on whether a human is signing in or not.
Pattern | OAuth Grant Type | Best For |
|---|---|---|
User-specific (interactive) | Implicit | Tools where a human user signs in (e.g., Power BI, Teams app, browser-based tools) |
Service account (unattended) | Client Credentials | Automated workflows and polling with no user interaction (e.g., n8n automations, backend services) |
Pattern 1: User-Specific Authentication (Implicit Flow)
This pattern prompts the user to sign in to Cora using their own credentials. The resulting token represents that specific user — audit trails, approvals, and record creation will be attributed to them.
How It Works
Your application redirects the user (or opens a popup) to the Cora authorize endpoint:
GET {SiteUrl}_api/identity/connect/authorize ?response_type=token &client_id={your-client-id} &scope=pv &redirect_uri={your-callback-url} &state={random-csrf-token}Cora's IdentityServer displays its login page. The user enters their Cora credentials.
After a successful login, Cora redirects the browser to your redirect URI with the bearer token in the URL fragment (the
#part of the URL):https://yourapp.com/auth-callback.html#access_token=eyJ...&token_type=Bearer&expires_in=3600&state=abc123
Your application extracts
access_tokenfrom the fragment, validates thestatevalue (CSRF check), and stores the token.Include the token in all subsequent API requests:
Authorization: Bearer {access_token}Tokens expire (typically after 3600 seconds / 1 hour). Your application should check the expiry and prompt the user to re-authenticate before the token expires. There are no refresh tokens in the implicit flow.
What is the Redirect URI?
The redirect URI is only relevant to the implicit flow — it has no meaning in client credentials.
When Cora's IdentityServer finishes authenticating a user, it needs to know where to send the token back to. It does this by redirecting the browser to the redirect URI you specified in the authorize request, with the token appended as a URL fragment.
Key rules for the redirect URI:
It must be registered in advance by a Cora administrator against your API client in IdentityServer. If the URI in your request doesn't exactly match a registered value, Cora will reject the request with a
redirect_uri mismatcherror. This is a security control to prevent token hijacking.It must be a real page your application serves — because the browser will actually navigate to it. That page's only job is to extract the token from the URL fragment and pass it back to your main application.
Why the URL fragment? Browsers do not send URL fragments to the server — they only exist client-side. This means the token is never transmitted to your web server in the redirect request, reducing the risk of it being logged or intercepted server-side.
Example: an application hosted at https://yourapp.com/corateamsapp/ would register its redirect URI as:
https://yourapp.com/corateamsapp/auth-callback.html
Setting This Up in Common Tools
Power BI (custom connector): Build a custom Power BI connector with OAuth support, pointing to the Cora authorize endpoint. Register the Power BI callback URL as the redirect URI in Cora IdentityServer. Alternatively, you can use a static bearer token pasted into a Web connector's custom Authorization header — but this token will expire and need manual replacement.
Microsoft Teams Apps: Use the Teams JS SDK's microsoftTeams.authentication.authenticate() to open the Cora login in a managed popup. After the user authenticates, Cora redirects to your registered callback page, which extracts the token from the URL fragment and passes it back to the app. Store the token in localStorage for the duration of the session.
Browser-based / custom web apps: Open a popup to the Cora authorize URL. Handle the redirect in a lightweight callback page that parses the URL fragment and posts the token back to the main window via window.postMessage().
Pattern 2: Service Account Authentication (Client Credentials Flow)
This pattern is used when there is no interactive user — for example, automated workflows, scheduled jobs, or background polling. A pre-configured service account credential is used to obtain a token on behalf of the integration itself.
Important: This token represents the service account, not any specific user. Actions taken with it will appear under that service account in Cora's audit trail. Use a dedicated service account rather than a personal user account.
How It Works
Your application sends a POST request directly to the Cora token endpoint — no browser, no login page:
POST {SiteUrl}_api/identity/connect/token Content-Type: application/x-www-form-urlencoded grant_type=client_credentials &client_id={your-client-id} &client_secret={your-client-secret} &scope=pvCora responds with a bearer token:
{ "access_token": "eyJ...", "token_type": "Bearer", "expires_in": 3600 }Include the token in all API requests:
Authorization: Bearer {access_token}Cache the token and refresh it before it expires (recommended: refresh ~60 seconds before expiry). Do not request a new token for every API call.
No redirect URI is involved — this is a direct server-to-server call.
Setting This Up in Common Tools
n8n: Configure an OAuth2 Credential in n8n with Grant Type = Client Credentials, Token URL = {SiteUrl}_api/identity/connect/token, Client ID, Client Secret, and Scope = pv. n8n will automatically acquire and refresh the token. Alternatively, use an HTTP Request node to POST to the token endpoint and store the result in a variable for subsequent nodes.
Power Automate / Logic Apps: Use an HTTP action to POST to the token endpoint. Parse the JSON response to extract access_token. Pass the token as an Authorization header in subsequent HTTP actions. Store credentials securely in Azure Key Vault or as Power Platform environment variables — never hardcoded.
Custom scripts / Azure Functions / backend services: Implement a token cache (in-memory or distributed). On startup and before each batch of requests, check whether the cached token is still valid and re-request when approaching expiry.
Administrator Setup: Registering an API Client in Cora IdentityServer
Before any external tool can connect, a Cora administrator must register an OAuth client in IdentityServer. The required configuration differs by flow:
Setting | Implicit Flow (Interactive) | Client Credentials (Service Account) |
|---|---|---|
Client ID | Any unique identifier (e.g., | Any unique identifier (e.g., |
Client Secret | Not used | Required — must be kept secret and stored securely |
Grant Type |
|
|
Allowed Scopes |
|
|
Redirect URI(s) | Must exactly match the callback URL(s) the application will send | Not applicable |
Associated User | N/A — token represents the signed-in user | A dedicated Cora service account |
API Base URL and Key Endpoints
All Cora API calls use the following base URL pattern — note the underscore before api:
{SiteUrl}_api
For example: https://yoursite.corasystems.com/YourInstance_api
Method | Endpoint | Description |
|---|---|---|
|
| List all project registers |
|
| Get register schema and fields |
|
| Get paginated records |
|
| Create a record |
|
| Update records |
|
| List projects |
|
| List users |
|
| Get the current user's profile (name, email, ID) |
Tips & Best Practices
Never expose client secrets in browser or frontend code. Client secrets must only be used in server-side or backend code. Use the implicit flow for user-facing tools.
Cache tokens. Request a new token only when the current one is near expiry — not on every API call. Repeatedly hitting the token endpoint may be rate-limited.
Validate the OAuth
stateparameter when using the implicit flow to prevent CSRF attacks.Use a dedicated service account for automated integrations rather than a personal user account, so access doesn't break if an employee leaves.
Store secrets securely — use Azure Key Vault, environment variables, or your platform's secret management (e.g., n8n credentials vault, Power Platform environment variables). Never hardcode secrets in scripts or configuration files.
Handle 401 responses gracefully. A
401 Unauthorizedmeans the token has expired. Re-authenticate rather than failing silently.Refresh proactively. Refresh the token ~60 seconds before expiry rather than waiting for a 401 to avoid failed requests mid-operation.
Troubleshooting
Symptom | Likely Cause | Resolution |
|---|---|---|
| Token expired or missing | Re-authenticate or refresh the token; confirm |
| Wrong Client ID or Secret | Verify credentials with your Cora administrator |
| Scope not permitted for this client | Ask your Cora administrator to grant the |
| Callback URL not registered in IdentityServer | Ask your Cora administrator to register your exact redirect URI against the OAuth client |
OAuth popup blocked | Browser blocked the popup window | Ensure your browser allows popups from the application's origin |
Token obtained but API returns | User or service account lacks permissions in Cora | Check the account's Cora role and project access with your administrator |
Sign-in popup closes but nothing happens | Redirect URI page failed to communicate back to the main window | Ensure the callback page is correctly implemented and that the redirect URI exactly matches the registered value |
Related Articles
Cora PPM REST API Reference
Managing OAuth Clients in Cora IdentityServer
Cora PPM Permissions and Roles
Setting Up the Cora Teams App
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article