Authentication and Authorization
OAuth 2.0 is an open authorization protocol that enables applications to obtain secure, delegated access to user accounts on an HTTP service. It works by authorizing third-party applications to access specific user data without requiring access to a user's private credentials. Your application uses OAuth libraries or endpoints to implement the OAuth 2.0 authorization that allows it to access the data through CORE APIs. This means it can use OAuth 2.0 to obtain permission from a CORE user to access and modify data in the CORE company database. The OAuth 2.0 Authorization Code flow allows your app to access CORE APIs on behalf of a user, after the user grants consent. For more information on OAuth 2.0, see RFC 6749.
All requests to CORE APIs must be sent over HTTPS and require TLS 1.2 or higher. Requests sent over insecure HTTP or unsupported TLS versions are rejected.
OpenID Connect
OpenID Connect (OIDC) 1.0 is a simple identity layer and authentication protocol built on top of OAuth 2.0. It enables your application to verify the identity of the end-user based on authentication performed by the CORE Authorization Server, and to obtain basic profile information about the user in a secure and interoperable way.
OIDC is optional in CORE APIs. You only use it if your application needs to know the identity of the user (for example, to display their name or email, or to implement single sign-on). If you only need to access CORE APIs on behalf of a user, you can use OAuth 2.0 without OIDC.
OIDC can be used with any application type supported by CORE, including web, native, and JavaScript apps.
Using OpenID Connect
To use OIDC, simply include the openid scope in your authorization request when using the Auth Code flow. You may also request additional OIDC scopes (profile, email, and address) to access more user information.
GET /connect/authorize?client_id=YOUR_CLIENT_ID&response_type=code&scope=openid%20profile%20email&redirect_uri=https://yourapp.com/oauth-callbackWhen the user completes authentication and grants consent, your app receives an authorization code. Exchange this code at the token endpoint as usual. Because you requested the openid scope, the token response includes an id_token (a JSON Web Token containing user identity claims), along with the usual access_token.
id_token: Contains information about the authenticated user, signed by COREaccess_token: Used to access CORE APIs
After receiving the id_token, your app should validate it to ensure it was issued by CORE and has not been tampered with. Check Tokens: Validate an ID Token for details. If your app needs additional user profile information, you can call the userinfo endpoint using the access token. Check Tokens: User Info Endpoint for details.
Discovery Document
The Discovery Document is a JSON document containing key-value pairs that provide details about the CORE authorization server. The information provided by the discovery document includes authorization URLs, token, endpoints, scopes and userinfo. You can find CORE’s discovery document on:
Application Types
When you register an app on the CORE Developer Portal, you must select an application type, which determines how your app connects and interacts with CORE APIs. The table below summarizes the key differences between each application type, including where your code runs, whether a client secret is used, and whether security features like Proof Key for Code Exchange (PKCE) and Pushed Authorization Requests (PAR) are required. Use this table to understand the requirements for each app type.
| Application Type (Developer Portal) | Where code runs | Client secret used | PKCE | PAR |
|---|---|---|---|---|
Regular Web App | Server-side backend | Yes | Optional but recommended | No |
Web App (FAPI/PAR) | Server-side backend | Yes | Required | Required |
JavaScript App | Browser | No | Optional but recommended | No |
Native App | Mobile or Desktop | No | Required | No |
Proof Key for Code Exchange (PKCE) is a security technique that helps protect OAuth 2.0 Authorization Code flows against authorization code interception attacks. It is primarily used by public clients, such as mobile apps and single-page applications, which cannot securely store a client_secret, but it can also be used by confidential clients for additional protection. The client generates a random code_verifier and creates a code_challenge by applying a cryptographic hash to the verifier. The code_challenge is sent in the initial authorization request, and the original code_verifier is required when exchanging the authorization code for tokens. This ensures that only the app that started the flow can complete it. For details, see RFC 7636.
Choosing an Application Type
Choosing the right application type depends primarily on where your code runs and whether it can securely store a client secret. Below are the recommended use cases for each app type:
- Regular Web App for server-side applications such as Node.js, ASP.NET Core, PHP, or Java Spring that can securely store a client secret
- Web App (FAPI/PAR) for the same server-side scenario where your environment also requires FAPI 2.0 compliance or a hardened OAuth pattern for regulated or security-sensitive integrations
- JavaScript App for single-page applications that run entirely in the browser with no server-side component, such as React, Angular, or Vue
- Native App for applications that run on a mobile or desktop device, such as iOS, Android, Windows, or macOS
Only Regular Web App and Web App (FAPI/PAR) support refresh tokens. If your integration requires long-lived sessions or uninterrupted access without re-prompting the user for consent, use one of these app types.
Regular Web App
Regular Web App is the standard application type for server-side web applications that implement the OAuth 2.0 Authorization Code flow. Your server-side code handles token exchange and stores credentials securely. Unlike public clients (JavaScript or Native apps), Regular Web Apps use a Client Secret to authenticate with the CORE Authorization Server.
This application type is a confidential client (it runs on a server and can store secrets). Never expose your client_secret in browser code or public repositories.
Flow Summary
The Regular Web App Authorization Code flow involves these steps:
- Your app constructs an authorization URL and redirects the user's browser to it.
- The user logs in to CORE and grants consent on the consent screen.
- The CORE Authorization Server redirects the user back to your Redirect URI with an authorization code.
- Your server exchanges the authorization code for an access token (and optionally a refresh token) at the token endpoint.
Endpoints used in the flow
Base URI:
Endpoints:
- Authorization:
GET /connect/authorize - Token:
POST /connect/token
Step 1: Redirect the user to the authorization endpoint
Your app initiates the flow by constructing an authorization URL and redirecting the user's browser to it.
Endpoint used
/connect/authorize
GET /connect/authorize?client_id=YOUR_CLIENT_ID&response_type=code&scope=readwrite%3Acore%20offline_access&redirect_uri=YOUR_REDIRECT_URI&state=STATE_VALUEAuthorization request parameters
| Parameter | Values | Description |
|---|---|---|
| client_id required | Your app’s Client ID | Identifies the app making the request. Use the value from your app’s details in the Developer Portal Dashboard. |
| scope required | Space-delimited set of permissions that the app is requesting | Specifies what level of access your app is requesting. The values passed in this parameter inform the consent screen shown to the users. Available scopes include: |
| redirect_uri required | One of the Redirect URIs registered for your app | Specifies where the Authorization Server should send the response. The value must match exactly (including scheme, host, path, case, and any trailing slashes) with one of the Redirect URIs registered for your app in the Developer Portal. Otherwise the authorization request is rejected and the users see an error page. See Getting Started: Understanding your Redirect URI for details. |
| response_type required | code | Indicates the type of response your app expects. For Authorization Code flow, this must always be code, meaning your app expects to receive an authorization code. |
| state | Base64-encoded JSON object that can hold multiple values | An optional value your app can send in the authorization request. It is returned unchanged by the Authorization Server, allowing your app to verify that the response is tied to the original request. This can help with preventing Cross-Site Request Forgery (CSRF) attacks. |
Step 2: User login and consent
After being redirected, users see a secure CORE Log In screen where they enter their CORE company credentials. After logging in, they are shown a consent screen displaying your app's name and the permissions it is requesting. The users can click Grant Permission to authorize your app, or Decline to refuse access. If the users grant offline_access, your app also receives a refresh token in the token response. For more details on this step, see Getting Started: Implement Authorization Code Flow.
Step 3: Handle the redirect back to your app
If the user grants access, the CORE Authorization Server redirects to your registered Redirect URI with an authorization code and the state value (if provided):
https://YOUR_REDIRECT_URI?code=AUTHORIZATION_CODE&state=STATE_VALUEYour app must then:
- Extract the
codefrom the query string. - Verify that the returned
statematches the value your app originally sent. This round-trip check helps ensure the response belongs to a legitimate request.
If the user declines access, the Authorization Server redirects to your Redirect URI with the following parameters.
| Parameter | Value |
|---|---|
error | access_denied |
error_description | User declined access |
Step 4: Exchange the authorization code for tokens
Your server exchanges the authorization code for an access token and a refresh token (if offline_access was granted) by sending a POST request to the token endpoint. This request must be made server-side and not from the browser.
Endpoint used
/connect/token
curl --request POST \
--url /connect/token \
--header 'content-type: application/x-www-form-urlencoded' \
--data 'grant_type=authorization_code' \
--data 'redirect_uri=YOUR_REDIRECT_URI' \
--data 'code=AUTHORIZATION_CODE' \
--data 'client_id=YOUR_CLIENT_ID' \
--data 'client_secret=YOUR_CLIENT_SECRET'Token request parameters
| Parameter | Description |
|---|---|
| Must be |
| The authorization code received at your Redirect URI in Step 3 |
| Must match the Redirect URI used in the authorization request |
| Your app's Client ID |
| Your app's Client Secret |
A refresh_token is included only if the user granted offline_access. The endpoint field in the response is your Base URL for all subsequent API calls.
Response fields
| Field | Description |
|---|---|
access_token | The token your app must include in all CORE API requests |
refresh_token | Used to obtain a new access token without user interaction (only returned if offline_access was granted) |
expires_in | Remaining lifetime of the access token in seconds |
token_type | Identifies the type of token returned |
Common Errors and Troubleshooting
Authorization redirect fails
Common causes:
redirect_uridoes not exactly match the registered valueclient_idis incorrect or belongs to a different app- An invalid or unsupported
scopewas requested (invalid_scope)
Token exchange fails
Common causes:
- Wrong or reused authorization code (
invalid_grant) redirect_urimismatch between the authorization and token requests- Missing or incorrect
client_secret(invalid_client)
Security Notes
- Store
client_secreton the server only. Never expose it in client-side code, URLs, or logs. - Always use and validate the
stateparameter to mitigate CSRF attacks. - Authorization codes are single-use. Discard them immediately after the token exchange.
- Use short-lived sessions for pending authorization requests and clear them after the token exchange is complete.
Web App (FAPI/PAR)
Web App (FAPI/PAR) is a high-security application type for server-side web applications that must use a hardened OAuth 2.0 pattern. It is designed for regulated or security-sensitive integrations and builds on the Regular Web App Authorization Code flow, with these key differences:
- The authorization request parameters are pushed to a backchannel Pushed Authorization Request (PAR) endpoint first, instead of being placed directly in the browser redirect query string.
- The browser redirect uses a short-lived
request_urireference returned by the PAR endpoint. - PKCE is required, in addition to Client Secret.
This application type is a confidential client (it runs on a server and can store secrets). Never expose your client_secret or PKCE code_verifier in browser code.
Flow Summary
The Web App (FAPI/PAR) Authorization Code flow typically includes these steps:
- Your server generates PKCE values (
code_verifierandcode_challenge). - Your server sends a Pushed Authorization Request (PAR) to CORE Authorization Server and receives a
request_uri. - Your app redirects the user’s browser to the authorization endpoint using the
request_uri. - CORE Authorization Server authenticates the user and shows the consent screen.
- After the user grants consent, CORE Authorization Server redirects the user back to your redirect URI with an authorization code.
- Your server exchanges the code for tokens at the token endpoint, sending the
client_secretandcode_verifier.
For more details on PAR, refer to RFC 9126.
Endpoints used in the flow
Base URI:
Endpoints:
- PAR:
POST /connect/par - Authorization:
GET /connect/authorize - Token:
POST /connect/token
Step 1: Generate PKCE values
Before you start the flow, your server must:
- Generate a
code_verifier: a cryptographically random string (43–128 characters) - Derive a
code_challenge: Base64 URL-encoded SHA-256 hash of thecode_verifier - Set
code_challenge_methodtoS256
Store the code_verifier securely on the server (for example, in the user’s session) until the token exchange step.
Step 2: Send the Pushed Authorization Request (PAR)
Unlike the Regular Web App flow, your server sends the authorization parameters to the PAR endpoint instead of sending authorization parameters directly to /connect/authorize in the browser.
Endpoint used
/connect/par
curl --request POST \
--url /connect/par \
--header 'content-type: application/x-www-form-urlencoded' \
--data 'client_id=YOUR_CLIENT_ID' \
--data 'client_secret=YOUR_CLIENT_SECRET' \
--data 'response_type=code' \
--data 'redirect_uri=YOUR_REDIRECT_URI' \
--data 'scope=readwrite%3Acore%20offline_access' \
--data 'state=STATE_VALUE' \
--data 'code_challenge=YOUR_CODE_CHALLENGE' \
--data 'code_challenge_method=S256'PAR request parameters
| Parameter | Description |
|---|---|
| Your app’s Client ID from the Developer Portal |
| Your app’s Client Secret that you must have stored securely when registering the app on the Developer Portal |
| Must be |
| Must exactly match a Redirect URI registered for your app |
| Space-delimited scopes, URL-encoded in form requests. Example: |
| CSRF protection value returned back to your redirect URI |
| PKCE code challenge derived from |
| Must be |
A successful PAR response returns a short-lived request_uri value:
Save the full request_uri value and use it immediately in the redirect step. Do not treat it as a long-lived value.
Step 3: Redirect the user to the authorization endpoint
After receiving the request_uri, redirect the user’s browser to /connect/authorize using only the client_id and request_uri.
Endpoint used
/connect/authorize
GET ?client_id=YOUR_CLIENT_ID&request_uri=REQUEST_URIStep 4: User Consent
From this point forward, the user experience is the same as the Regular Web App flow. For more details on this step, see Getting Started: Implement Authorization Code Flow.
- Users see a secure CORE Log In screen where they need to enter their CORE company credentials.
- After logging in, users see a consent screen showing requested permissions (scopes).
- On the consent screen, users can click Grant Permission to grant the selected permissions to your app or Decline to refuse access.
- If the users grant permission, the Authorization Server redirects them to your Redirect URI with an authorization code.
Step 5: Handle the redirect back to your app
If a user grants access to your app, the CORE Authorization Server redirects to your registered redirect_uri with a code and (if you provided it) state.
https://YOUR_REDIRECT_URI?code=AUTHORIZATION_CODE&state=STATE_VALUEYour app must then:
- Extract
code - Verify that
statematches the value you originally generated and stored
If the user declines consent, your app receives an error response at the redirect URI (error=access_denied).
Step 6: Exchange the authorization code for tokens
Your server exchanges the authorization code for tokens using the token endpoint. For Web App (FAPI/PAR), the token request must include:
client_secret(confidential client)code_verifier(PKCE)
Endpoint used
/connect/token
curl --request POST \
--url /connect/token \
--header 'content-type: application/x-www-form-urlencoded' \
--data 'grant_type=authorization_code' \
--data 'redirect_uri=YOUR_REDIRECT_URI' \
--data 'code=AUTHORIZATION_CODE' \
--data 'client_id=YOUR_CLIENT_ID' \
--data 'client_secret=YOUR_CLIENT_SECRET' \
--data 'code_verifier=YOUR_CODE_VERIFIER'Token request parameters
| Parameter | Description |
|---|---|
| Must be |
| Authorization code received at your redirect URI |
| Must match the redirect URI used earlier in the PAR request |
| Your app's Client ID |
| Your app's Client Secret |
| The original PKCE verifier used to generate the |
The response contains an access_token. If the user granted offline_access, the response also includes a refresh_token.
Common Errors and Troubleshooting
PAR request fails immediately
Common causes:
- Invalid client credentials (
invalid_client) - Missing required parameter (
invalid_request) - Redirect URI mismatch
- Scope not valid (
invalid_scope)
Authorization redirect fails
Common causes:
- Expired or invalid
request_uri - Wrong (
client_id) - Attempting to reuse a (
request_uri)
Token exchange fails
Common causes:
- Wrong or reused authorization code (
invalid_grant) - Redirect URI mismatch
- Missing or incorrect
code_verifier - Invalid
client_secret
Security Notes
- Store
client_secretandcode_verifieron the server only. - Always use and validate
stateto mitigate CSRF. - Use short-lived sessions for pending authorization requests and clear them after the token exchange.
JavaScript App
JavaScript apps are single-page apps (or browser-based apps) that run entirely in the browser after loading the Javascript and HTML source code from a web page. As the entire source is available to the browser, they cannot maintain the confidentiality of a client secret. So the secret is not used for these apps. The Authorization Code flow here is similar to Regular Web App, but at the last step, the authorization code is exchanged for an access token without using the client secret.
Authorization
The authorization code is a temporary code that a client exchanges for an access token. The code is obtained from an authorization server, where the user gets a chance to see what information the client is requesting and whether to approve or deny the request.
Step 1: Initiating the Authorization RequestThe first step of the flow is to initiate the authorization process by redirecting the user to CORE authorization server. The discussion here assumes the base URI is:
GET /connect/authorize?client_id=a17c21ed&response_type=code&state=5ca75bd30&redirect_uri=https://example-app.com/authAuthorization Grant Parameters
The following parameters are used to make the authorization request.
| Name | Value | Description |
|---|---|---|
response_type | code | response_type is set to code indicating that you want an authorization code as the response |
client_id | The client ID you obtain from the developer portal dashboard | The client_id is the identifier for your app. You will have received a client_id when first registering your app on the CORE developer portal |
redirect_uri | One of the redirect URI values listed for this project in the developer portal dashboard | Required. Determines where the response is sent. The value of this parameter must exactly match one of the values listed for this app in the app settings. This includes the scheme, host, path, case, and any trailing slash |
scope | These are the set of permissions that the application requests. Multiple scopes can be passed in a single request separated by whitespace | Required. Identifies the CORE API access that your application is requesting. The values passed in this parameter inform the consent screen that is shown to the user. |
state (recommended) | This field can be a Base64 encoded JSON object that can hold multiple values | Authorization protocols provide a state parameter. During authentication, the application sends this parameter in the authorization request. The Authorization Server returns this parameter unchanged in the response. Your application can use this parameter in order to make sure that the response belongs to a request that was initiated by the same user. Therefore, state helps mitigate CSRF attacks. Restore the previous state of your application |
The lack of using a client secret means that using the state parameter is even more important for single-page apps.
Step 2: User Consent
After the user visits the authorization page, CORE displays a log-in window. Enter you CORE credentials and click Login.

When logged in, CORE displays a consent dialog with the name of your application and CORE Company name, requesting permission to access with your authorization credentials including scope, etc.

If you click Grant Permission, the server redirects to the website with an authorization code and state value in the URL query string.
CORE does not allow you to log-in to multiple companies during a single client app instance.
Handling the Response
The response is sent to the redirect_uri that you specified in the request. All responses are returned in the query string, as shown below:
http://yourdemoapp.com?code=CODEStep 3: Exchange the Authorization Code for an Access Token
To exchange the Authorization Code for an Access Token, the app makes a POST request to CORE’s token endpoint. The request will have the following parameters.
| Name | Values | Description |
|---|---|---|
| grant_type | Authorization code | Required. The grant_type parameter must be set to “authorization_code“ |
| code | Code value received | Required. This parameter is for the authorization code received from the authorization server, which is in the query string parameter “code” |
| redirect_uri | One of the redirect URI values listed for this project in the developer portal dashboard | If the redirect URL was included in the initial authorization request, it must be included in the token request as well and must be identical |
| Client_Id | The client ID you obtain from the developer portal dashboard | Required.Despite the client secret not being used in this flow, the request requires sending the client ID to identify the application making the request. This means the client must include the client ID as a POST body parameter |
Example: The request might look like the following.
The response is sent back as a json object given below:
Handling the Response
A successful response to this request contains the following fields:
| Name | Description |
|---|---|
| access_token | The token that must be used to access the CORE APIs |
| token_type | Identifies the type of token returned. At this time, the field will always have the value Bearer |
| Expires_in | The remaining lifetime of the access token in seconds. The value always returned is 3600 seconds (1 hour) |
| Id_token | Returned for openid and associated user scopes for user authentication |
Native App
If you are building a native application, the authorization code flow with a Proof Key for Code Exchange (PKCE) is the favored method for regulating the access between your application and a resource server. It includes an additional step at the beginning and an extra verification at the end.
When the native app begins the authorization request, instead of immediately launching a browser, the client first creates what is known as a ‘Code Verifier .‘ It is a cryptographically random string using the characters A-Z, a-z, 0-9, and the punctuation characters -._~ (hyphen, period, underscore, and tilde), between 43 and 128 characters long.
After the app has generated the code verifier, it uses that to create the ‘Code Challenge.’ The code challenge is a BASE64-URL-encoded string of SHA256 hash of the code verifier.
A complete authorization request will include the following parameters.
Initiating the Authorization Request
GET /connect/authorize?response_type=code&client_id=bJyXzz6X4pY0Qc5EuvKXL9UZ1hvGvt3X.apps.bqe.com&redirect_uri=http://localhost/pkcetestapp&scope=readwrite:core&state=pcMYJ722TrooUTrk&code_challenge=2cWTIbQvY6MNnIK4J8-p1Bb_8gqvv7YSZGRllDyb7f4&code_challenge_method=S256Authorization Grant Parameters
The following parameters are used to make the authorization request.
| Parameter | Value | Description |
|---|---|---|
response_type | Code | Response_type is set to code indicating that you want an authorization code as the response |
client_id | The client_id you obtain from the Developer Portal | The client_id is the identifier for your app. You will have received a client_id when first registering your app on the CORE Developer Portal |
redirect_uri | One of the redirect URI values listed for this project in the developer portal dashboard | Required. Determines where the response is sent. The value of this parameter must exactly match one of the values listed for this app in the app settings. This includes the scheme, the same case
|
scope | Required. Identifies the CORE API access that your application is requesting. The values passed in this parameter inform the consent screen that is shown to the user. Available scopes include: | |
State (recommended) | This field can be a Base64 encoded JSON object that can hold multiple values | Authorization protocols provide a state parameter. During authentication, the application sends this parameter in the authorization request. The Authorization Server returns this parameter unchanged in the response. |
code_challenge | The code challenge generated | Base64-URL-encoded string of SHA256 hash of the Code Verifier |
code_challenge_method | Whether the challenge is the plain verifier string or SHA256 hash of the string |
After you visit the authorization page, CORE displays a log-in window. Enter your CORE credentials and click Login.

When logged in, CORE displays a consent dialog with the name of your application and CORE Company name, requesting permission to access your authorization credentials including scope, etc.

If you click Grant Permission, the server redirects to the website with an authorization code and state.
CORE does not allow you to log-in to multiple companies amid a single client app instance.
Handling the response
The response is sent to the redirect URI specified in the request. All responses are returned in the query string as shown below:
https://www.coredemo.com/oauth-redirect?code=CODEStep 3: Exchanging Authorization Code for an Access Token
To exchange the Authorization Code for an Access Token, the app makes a POST request to CORE token endpoint. The request has the following parameters:
| Name | Values | Description |
|---|---|---|
grant_type | Authorization Code | Required. The grant_type parameter must be set to ‘authorization_code’ |
code | Code value received | Required. This parameter is for the authorization code received from the authorization server, which is in the query string parameter ‘code’ |
redirect_uri | One of the redirect URI values listed for this project in the Developer Portal | If the redirect URI was included in the initial authorization request, it must be included in the token request as well and must be identical |
client_Id | The client id you obtain from the Developer Portal | This is the applications registered client id |
code_verifier | Cryptographically random string | The code verifier for the PKCE request that the app originally generated before the authorization request |
Example: The actual request might look like the following.
The response is sent back as a json object given below:
Handling the response
A successful response to this request contains the following fields:
| Name | Description |
|---|---|
| access_token | The token that must be used to access the CORE APIs. |
| expires_in | The remaining lifetime of the access token in seconds. The value always returned is 3600 seconds (one hour). Use the refresh token to get a fresh one |
| token_type | Identifies the type of token returned. At this time, this field will always have the value 'bearer' |
| id_token | Returned for openid and associated user scopes during authentication |