Implement OAuth

Use OAuth 2.0 to connect to Aconex APIs.

What is OAuth?

Open Authorization (OAuth) is the industry-standard protocol for authorization that allows third-party applications to access a user's data without exposing their credentials and is commonly used to provide secure API access and user authentication.

The OAuth 2.0 Authorization Framework was published as RFC 6749.  You should be familiar with the concepts and terminology presented in this document.

Subsequently, several recent RFCs and articles related to OAuth have been released, providing guidance on best practices for the implementation of OAuth 2.0.

Some notable examples include:

How does Aconex support OAuth?

The Oracle Construction and Engineering Lobby (or "Lobby" for short), provides an OAuth 2.0 implementation for all Oracle Smart Construction Platform applications, including Aconex.  This implementation is sometimes referred to as "Lobby OAuth".

Users authenticate with their Lobby account credentials and if they have multiple linked Aconex accounts, will be required to select one account.


Authorization Server

The Oracle Construction and Engineering Lobby acts as the Authorization Server.

There is a single Lobby for all commercial Aconex instances (ASIA1, ASIA2, AU1, CA1, EU1, KSA1, MEA, UK1, US1).

The Lobby URL is https://constructionandengineering.oraclecloud.com.  

There is a separate Early Access (EA) Lobby for the Aconex Early Access (EA1) instance, which is used for testing Smart Construction Platform integrations in a non-production environment.

The EA Lobby URL is https://constructionandengineering-ea.oraclecloud.com.  


Resource Server

There is a single Resource Server for all commercial Aconex instances (ASIA1, ASIA2, AU1, CA1, EU1, KSA1, MEA, UK1, US1) and Aconex Early Access (EA1).

You can use the same Resource Server URL (https://api.aconex.com) to access all of these Aconex instances.


Integration Types

Lobby supports the following types of integrations:

  • Web Server Application: A server-side user application delivering a user interface in a web browser
    • This is a confidential client that uses Authorization Code grant type
  • Installed Application: An application that a user installs onto their device, such as a Windows app, macOS app, mobile app, or a single-page app (SPA) running entirely in a web browser.
    • This is a public client that uses Authorization Code grant type, plus Proof-Key for Code Exchange (PKCE)
  • Non-Interactive Integration: An integration that has no user interaction.
    • This is a trusted client that uses JWT Bearer (otherwise known as User Assertion) grant type.
  • User-Bound Integration: An integration that has no user interaction and is bound to a specified Lobby user account.
    • This is a confidential client that uses Client Credentials grant type

Tip!

Unsure which type you need? See What type of OAuth Integration should I register?

Implement OAuth in a Web Server Application

Web Server Application runs on a server and delivers a user interface in a web browser, that users interact with.

A Web Server Application is a confidential client that uses the Authorization Code grant type to request an access token, as described below.

 

Step 1: Obtain Client Credentials

Follow the steps to create an OAuth Client.

Your Web Server Application will be registered as a confidential client and you will receive client credentials in the form of a Client ID and Client Secret

These credentials must be kept confidential and must not be shared with anyone outside of your organization.

 

 

Step 2: Redirect the User to the Authorization Endpoint

When a user of your Web Server Application wants to access their Aconex data, redirect them to the authorization endpoint of the Lobby as follows:

/auth/authorize?response_type=code&client_id=&redirect_uri=

Here is an example:

https://constructionandengineering.oraclecloud.com/auth/authorize?response_type=code&client_id=MyClientId&redirect_uri=https://myapp.com/oauth/callback

 

Step 3: User Authentication and Consent

The Lobby responds to this request by prompting the user to sign in with their Lobby account credentials, if they are not already logged in. 

If the user has more than one Aconex user account linked to their Lobby account, they will be prompted to select an Aconex user account. 

The user authorizes your application to access their Aconex data by the act of authenticating their account.

 

Step 4: Receive the Authorization Code

The Lobby returns an Authorization Code to the specified redirect URL, as follows:

?code=

Here is an example:

https://myapp.com/oauth/callback?code=TXlBdXRob3JpemF0aW9uQ29kZQ

 

Step 5: Exchange the Authorization Code for an Access Token

Your application exchanges the Authorization Code for an Access Token and Refresh Token by making a POST request to the token endpoint of the Lobby specifying the client credentials using Basic Authentication (Base64 encoding of the Client ID and Secret joined by a colon ':'), as follows:

POST /auth/token

Headers:
 Content-Type: application/x-www-form-urlencoded
Authorization: Basic

Body:
grant_type=authorization_code
code=
redirect_uri=

Here is an example cURL request:

curl --request POST 'https://constructionandengineering.oraclecloud.com/auth/token' \
--header 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' \
--header 'Authorization: Basic TXlDbGllbnRJRDpNeUNsaWVudFNlY3JldA==' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'code=TXlBdXRob3JpemF0aW9uQ29kZQ' \
--data-urlencode 'redirect_uri=https://myapp.com/oauth/callback'

The response is in JSON format and contains the access token, expiration time of the access token and refresh token.

Here is an example response:

{
   "access_token": "eyJ4NXQjUzI1NiI...KtK5elB38rcAbgFtVP9A",
   "token_type": "Bearer",
   "expires_in": 3600,
    "refresh_token": "TXlSZWZyZXNoVG9rZW4="
}

 

Step 6: Use the Access Token

Use the Access Token to make authorized requests to Aconex APIs on behalf of the authenticated user by including it in the Authorization header of your HTTP requests, as follows:

Authorization: Bearer 

Here is an example cURL request:

curl 'https://api.aconex.com/api/projects' \

--header 'Authorization: Bearer eyJ4NXQjUzI1NiI...KtK5elB38rcAbgFtVP9A'

 

Step 7: Refresh the Access Token

When the Access Token expires, request a new access token without requiring the user to authenticate by making a POST request to the token endpoint of the Lobby, as follows:

POST /auth/token

Headers:
 Content-Type: application/x-www-form-urlencoded
Authorization: Basic

Body:
grant_type=refresh_token
refresh_token=

Here is an example cURL request:

curl --request POST 'https://constructionandengineering.oraclecloud.com/auth/token' \
--header 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' \
--header 'Authorization: Basic TXlDbGllbnRJRDpNeUNsaWVudFNlY3JldA==' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=TXlSZWZyZXNoVG9rZW4='

The response is the same as the original token response, including a new access token, access token expiry and new refresh token.

 

(Optional) Proof Key for Code Exchange (PKCE)

Proof Key for Code Exchange (PKCE) is an optional additional security protocol for use with Authorization Code flows.  It helps prevent interception of the authorization code by malicious actors. PKCE involves the client generating a random secret (called a code verifier) and creating a derived value (called a code challenge) from it using a transform function. The code challenge is sent to the Lobby during the initial authorization request, while the code verifier is kept secret. When the Authorization Code is returned, the client provides the code verifier to prove its identity and exchanges the Authorization Code for an access token.  For more details, see RFC 7636

PKCE is not required for Web Server Applications, but it has been recommended by various authors for use in all Authorization Code flows.

If you choose to implement PKCE, follow the steps described below.

  1. Generate a random code verifier, which is a high-entropy cryptographic random string of between 43-128 characters.
  2. Create a code challenge by applying a cryptographic hash function like SHA-256 to the code verifier.  Encode the result as URL-safe Base64.

    For testing purposes, you can use the helper utility at https://example-app.com/pkce to generate the required values.

    Here is an example using JavaScript:
const crypto = require('crypto');

// Generate a random code verifier
const codeVerifier = base64URLEncode(crypto.randomBytes(48));

// Create a code challenge using SHA-256
const codeChallenge = base64URLEncode(crypto.createHash('sha256').update(codeVerifier).digest());

function base64URLEncode(buffer) {
    return buffer.toString('base64')
        .replace(/=/g, '')
        .replace(/\+/g, '-')
        .replace(/\//g, '_');
}
  1. When your application redirects the User to the Authorization Endpoint, include the code challenge and code challenge method as follows:
/auth/authorize?response_type=code&client_id=&redirect_uri=&code_challenge=&code_challenge_method=

Here is an example:

https://constructionandengineering.oraclecloud.com/auth/authorize?response_type=code&client_id=MyClientId&redirect_uri=https://myapp.com/oauth/callback&code_challenge=mS8J4mBfBb-6Qh8VdcP4XyDG0g0-URpKVTzIltVt5-2k&code_challenge_method=S256
  1. When your application exchange the Authorization Code for an Access Token, include the code verifier as follows:
POST /auth/token

Headers:
 Content-Type: application/x-www-form-urlencoded

Body:
client_id=
grant_type=authorization_code
code=
code_verifier=
redirect_uri=

Here is an example cURL request:

curl --request POST 'https://constructionandengineering.oraclecloud.com/auth/token' \
--header 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' \
--data-urlencode 'client_id=MyClientId' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'code=TXlBdXRob3JpemF0aW9uQ29kZQ' \
--data-urlencode 'code_verifier=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM' \
--data-urlencode 'redirect_uri=https://myapp.com/oauth/callback'

 

(Optional) State Parameter

The state parameter is an optional security measure to prevent Cross-Site Request Forgery (CSRF) attacks.  It's a random value generated by the client and used to verify the integrity of the authorization process.  The Lobby includes this value when redirecting back to the client with the Authorization Code.

If you choose to make use of the state parameter, follow the steps described below.

Generate a random, unique value in your client application.

Include this value in the authorization request sent to the Lobby as follows:

/auth/authorize?response_type=code&client_id=&redirect_uri=&state=

Here is an example:

https://constructionandengineering.oraclecloud.com/auth/authorize?response_type=code&client_id=MyClientId&redirect_uri=https://myapp.com/oauth/callback&state=TXlTdGF0ZQ

When your application receives the OAuth response, check that the state parameter in the response matches the previously sent.  It will be returned as follows:

?code=&state=

Here is an example:

https://myapp.com/oauth/callback?code=TXlBdXRob3JpemF0aW9uQ29kZQ&state=TXlTdGF0ZQ

If they match, proceed with the authorization process.  If they don't, consider it a potential security breach, reject the response, invalidate the state parameter, and generate a new one for the next authorization request.

 

Allow the User to Switch Aconex Accounts

Some users will have multiple Aconex user accounts linked to their Lobby account.

During the OAuth flow, the user will be required to select one Aconex user account.

If you wish to allow the user to switch to another of their Aconex user accounts, initiate the OAuth flow again to display the Aconex user account selector.  In some cases, the user may have to authenticate their Lobby account again.

Implement OAuth in an Installed Application

An Installed Application is a user-facing application that is installed by the user onto their device.  Typical examples are Windows, macOS, iOS app and Android apps. A single-page app (SPA) running entirely in a web browser is another example. 

The difference between an Installed Application and a Web Server Application is that code runs on the user's device, not on a server.  This is an important difference from a security perspective, because the code cannot maintain the confidentiality of the client credentials used for OAuth.

An Installed Application is a public client that uses the Authorization Code grant type with Proof Key for Code Exchange (PKCE) to request an access token, as described below.

PKCE is required in this case to enhance the security of the flow, since a public client cannot keep its client credentials confidential.  It involves the client generating a random secret (called a code verifier) and creating a derived value (called a code challenge) from it. The code challenge is sent to the Lobby during the initial authorization request, while the code verifier is kept secret. When the Authorization Code is returned, the client provides the code verifier to prove its identity and exchanges the Authorization Code for an access token.  For more details, see RFC 7636

 

Step 1: Obtain Client Credentials

Follow the steps to create an OAuth Client.

Redirect URI Recommendations

RFC 8252 states that Installed Applications should use one of the following types of redirect URI:

Private-use URI scheme redirect uses a custom URI scheme that has been registered on the device for your application, taking the form:

scheme:/path

Here's an example:

com.example.app:/oauth2/callback

Loopback redirect URI uses the "http" scheme with the loopback IP literal and whatever port the application is listening on, taking the form:

http://127.0.0.1:{port}/{path}

Here's an example:

http://127.0.0.1:54001/oauth2/callback

If your Installed Application loops through a number of ports to find an available port for binding the callback, you may register a single loopback redirect URI with a wildcard (*) port identifier, rather than registering multiple redirect URIs.

Your Installed Application will be registered as a public client and you will receive client credentials in the form of a Client ID only. 

The Client ID must be kept confidential and must not be shared with anyone outside of your organization.

 

Step 2: Generate Code Verifier and Code Challenge

Generate a random code verifier, which is a high-entropy cryptographic random string of between 43-128 characters.

Create a code challenge by applying a cryptographic hash function like SHA-256 to the code verifier.  Encode the result as URL-safe Base64.

For testing purposes, you can use the helper utility at https://example-app.com/pkce to generate the required values.

Here is an example using JavaScript:

const crypto = require('crypto');

// Generate a random code verifier
const codeVerifier = base64URLEncode(crypto.randomBytes(48));

// Create a code challenge using SHA-256
const codeChallenge = base64URLEncode(crypto.createHash('sha256').update(codeVerifier).digest());

function base64URLEncode(buffer) {
    return buffer.toString('base64')
        .replace(/=/g, '')
        .replace(/\+/g, '-')
        .replace(/\//g, '_');
}

 

Step 3: Redirect the User to the Authorization Endpoint

When a user of your Installed Application wants to access their Aconex data, redirect them via the native web browser (not an embedded browser) to the authorization endpoint of the Lobby as follows: 

/auth/authorize?response_type=code&client_id=&redirect_uri=&code_challenge=&code_challenge_method=

Here is an example:

https://constructionandengineering.oraclecloud.com/auth/authorize?response_type=code&client_id=MyClientId&redirect_uri=https://myapp.com/oauth/callback&code_challenge=mS8J4mBfBb-6Qh8VdcP4XyDG0g0-URpKVTzIltVt5-2k&code_challenge_method=S256

 

Step 4: User Authentication and Consent

The Lobby responds to this request by prompting the user to sign in with their Lobby account credentials, if they are not already logged in. 

If the user has more than one Aconex user account linked to their Lobby account, they will be prompted to select an Aconex user account. 

The user authorizes your application to access their Aconex data by the act of authenticating their account.

 

Step 5: Receive the Authorization Code

The Lobby returns an Authorization Code to the redirect URI specified for your application, as follows:

?code=

Here is an example:

https://myapp.com/oauth/callback?code=TXlBdXRob3JpemF0aW9uQ29kZQ

 

Step 6: Exchange the Authorization Code for an Access Token

Your application exchanges the Authorization Code for an Access Token and Refresh Token by making a POST request to the token endpoint of the Lobby specifying the client ID in the request body, as follows:

POST /auth/token

Headers:
 Content-Type: application/x-www-form-urlencoded

Body:
client_id=
grant_type=authorization_code
code=
code_verifier=
redirect_uri=

Here is an example cURL request:

curl --request POST 'https://constructionandengineering.oraclecloud.com/auth/token' \
--header 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' \
--data-urlencode 'client_id=MyClientId' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'code=TXlBdXRob3JpemF0aW9uQ29kZQ' \
--data-urlencode 'code_verifier=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM' \
--data-urlencode 'redirect_uri=https://myapp.com/oauth/callback'

The response is in JSON format and contains the access token, expiration time of the access token and refresh token.

Here is an example of a response:

{
   "access_token": "eyJ4NXQjUzI1NiI...KtK5elB38rcAbgFtVP9A",
   "token_type": "Bearer",
   "expires_in": 3600,
    "refresh_token": "TXlSZWZyZXNoVG9rZW4="
}

 

Step 7: Use the Access Token

Use the Access Token to make authorized requests to Aconex APIs on behalf of the authenticated user by including it in the Authorization header of your HTTP requests, as follows:

Authorization: Bearer 

Here is an example cURL request:

curl 'https://api.aconex.com/api/projects' \
--header 'Authorization: Bearer eyJ4NXQjUzI1NiI...KtK5elB38rcAbgFtVP9A'

 

Step 8: Refresh the Access Token

When the Access Token expires, request a new access token without requiring the user to authenticate by making a POST request to the token endpoint of the Lobby, as follows:

POST /auth/token

Headers:
  Content-Type: application/x-www-form-urlencoded

Body:
  grant_type=refresh_token
  refresh_token=
client_id=

Here is an example cURL request:

curl --request POST 'https://constructionandengineering.oraclecloud.com/auth/token' \
--header 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' \
--data-urlencode 'client_id=MyClientId' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=TXlSZWZyZXNoVG9rZW4='

The response is the same as the original token response, including a new access token, access token expiry and new refresh token.

 

(Optional) State Parameter

The state parameter is an optional security measure to prevent Cross-Site Request Forgery (CSRF) attacks.  It's a random value generated by the client and used to verify the integrity of the authorization process.  The Lobby includes this value when redirecting back to the client with the Authorization Code.

If you choose to make use of the state parameter, follow the steps described below.

Generate a random, unique value in your client application.

Include this value in the authorization request sent to the Lobby as follows:

/auth/authorize?response_type=code&client_id=&redirect_uri=&state=

Here is an example:

https://constructionandengineering.oraclecloud.com/auth/authorize?response_type=code&client_id=MyClientId&redirect_uri=https://myapp.com/oauth/callback&state=TXlTdGF0ZQ

When your application receives the OAuth response, check that the state parameter in the response matches the previously sent.  It will be returned as follows:

?code=&state=

Here is an example:

https://myapp.com/oauth/callback?code=TXlBdXRob3JpemF0aW9uQ29kZQ&state=TXlTdGF0ZQ
If they match, proceed with the authorization process.  If they don't, consider it a potential security breach, reject the response, invalidate the state parameter and generate a new one for the next authorization request.

 

Allow the User to Switch Aconex Accounts

Some users will have multiple Aconex user accounts linked to their Lobby account.

During the OAuth flow, the user will be required to select one Aconex user account.

If you wish to allow the user to switch to another of their Aconex user accounts, initiate the OAuth flow again to display the Aconex user account selector.  In some cases, the user may have to authenticate their Lobby account again.

Implement OAuth in a Non-Interactive Integration

Non-Interactive Integration is one that calls APIs without any user interaction. Typical examples would be scripted integrations between a 3rd party application and Lobby, or software that runs on a scheduled basis and calls APIs to access data without any user interface.

A Non-Interactive Integration is a trusted client that uses the JWT Bearer (otherwise known as User Assertion) grant type to request an access token.

When requesting an Access Token, a User Assertion is provided to request authorization on behalf of a user within your organization.

There is no refresh flow for Non-Interactive Integrations.  When the Access Token expires, your integration should request a new Access Token.


Step 1: Obtain Client Credentials
Follow the steps to create an OAuth Client. You will upload a public certificate that Lobby uses to verify that the User Assertion is signed by you.
 
Your Non-Interactive Integration will be registered as a trusted client and you will receive client credentials in the form of a Client ID and Client Secret.
 

These credentials must be kept confidential and must not be shared with anyone outside of your organization.

 

Step 2: Create a User Assertion

An Assertion is a package of information that facilitates the sharing of identity and security information across security domains. A User Assertion contains information about a user and information about the conditions under which the assertion is to be considered valid.

By providing a User Assertion in the request for an Access Token, a Non-Interactive Integration can receive an Access Token allowing access to Aconex APIs on behalf of the identified user.

Lobby supports user assertions in JSON Web Token (JWT) format that are signed by the private key of a trusted issuer.  Lobby uses the corresponding public certificate of the trusted issuer that was specified in the registration of your integration to validate the supplied user assertion.

More information about JWT can be found here

User Assertion comprises a header, body and signature.

The header has the following claims:

Claim

Description

x5t Base64 URL encoded X.509 certificate sha1 thumbprint. Used to identify the trusted third-party certificate to validate the assertion signature. The x5t or kid claim must be present in the assertion header.
typ Type. Identifies the type of assertion, which is always "JWT".
kid Key identifier. Used to identify the trusted third-party certificate to validate the assertion signature.  Must match the certificateAlias of the uploaded public certificate.
alg Algorithm. Identifies the specific type of JWT signing algorithm, which is always "RS256".

The following claims must be included in the body:

Claim

Description

sub Subject. The Oracle Construction and Engineering Lobby account username.
iss Issuer. The Client ID of your registered integration.
aud Audience. Identifies the recipients for which the assertion is intended, which is always "https://identity.oraclecloud.com/".
exp Expiration. The time (UNIX epoch time) when the assertion expires.
iat Issued at. The date (UNIX epoch time) when the assertion was issued.
jti JWT Identifier.  Unique identifier for the JWT. A JWT ID can only be used once.
user_id (optional) Aconex user ID.  The user ID of the linked Aconex account for the user.  This does not need to be specified if there is only one Aconex account linked to the Lobby account specified in the sub claim.
user_site (optional) Aconex instance.  The URL of the Aconex instance on which the linked Aconex account is located.  This does not need to be specified if there is only one Aconex account linked to the Lobby account specified in the sub claim.

Here is an example JSON header and body:


{"kid":"MyCertificateAlias","typ":"JWT","alg":"RS256"}

{"sub":"patrick.oleary@majestic.com","iss":"MyClientID","aud":"https://identity.oraclecloud.com/","exp":1708778535,"iat":1708774935,"jti":12345,"user_id":"1879050130","user_site":"https://au1.aconex.com"}

The header and body are Base64-encoded and concatenated by a dot (.) then signed in the RS256 algorithm, using the trusted issuer's private key.

The result is three Base64 strings separated by dots (.) in the format of Header.Body.Signature

Here is an example signed User Assertion:


eyJraWQiOiJNeUNlcnRpZmljYXRlQWxpYXMiLCJ0eXBlIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJwYXRyaWNrLm9sZWFyeUBtYWplc3RpYy5jb20iLCJpc3MiOiJNeUNsaWVudElEIiwiYXVkIjoiaHR0cHM6Ly9pZGVudGl0eS5vcmFjbGVjbG91ZC5jb20vIiwiZXhwIjoxNzA4Nzc4NTM1LCJpYXQiOjE3MDg3NzQ5MzUsImp0aSI6MTIzNDUsInVzZXJfaWQiOiIxODc5MDUwMTMwIiwidXNlcl9zaXRlIjoiaHR0cHM6Ly9hdTEuYWNvbmV4LmNvbSJ9.jaQ2NyGk8wOWWHMGi2QJTsYlKGcHrfqkvP2Gb8AlBbJDQy7NDonXh6YMcAe17iIVaOfH7lDgJyF95xPv3nPHdIezbqobHBck34yct6I6a_xpKcV5kmJfXLHeb9LenqZTbdMMQ95vlUL8R914AmE2TbwGqjl4XkIoADHDez7PVM2MwyIDSfEaQ6o7J05ES7wIgI9gGspQ5w-2Xem4GOare25FBo-LrgVADDiAhKUhSLNT6XISCMAHZ3L2J86cnRhU1fekr-DJYFyfDcgAZeQPSPETHGokBWYtC1K-2qIouODKBKBcooABYEh6YTkC7bdax5KqFFbvJmSfDEjyN3tZ4wz
You may retrieve the User Assertion from an external Identity Provider (IdP), or you can generate a self-signed User Assertion.
 
Oracle Security Developer Tools (OSDT) can be used to generate a self-signed JWT User Assertion using the Oracle JSON Web Token class. Alternatively, third party libraries can be found here.

The Oracle Java Key and Certificate Management Tool can be used to generate a self-signing key pair.

 

Step 3: Request a Token

Make a POST request to the token endpoint of the Lobby specifying your client credentials using Basic Authentication (Base64 encoding of the Client ID and Secret joined by a colon ':') as follows:


POST /auth/token

Headers:
  Content-Type: application/x-www-form-urlencoded
  Authorization: Basic 

Body:
  grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
  assertion=

Here is an example cURL request:


curl --request POST 'https://constructionandengineering.oraclecloud.com/auth/token' \
--header 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' \
--header 'Authorization: Basic TXlDbGllbnRJRDpNeUNsaWVudFNlY3JldA==' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer' \ 
--data-urlencode 'assertion=eyJraWQiOiJNeUNlcnRpZmljYX..3tZ4w'

The response is in JSON format and contains the access token:


{
    "access_token": "eyJ4NXQjUzI1NiI...KtK5elB38rcAbgFtVP9A",
    "token_type": "Bearer",
    "expires_in": 3600
}

Note: If you are unable to generate a User Assertion that contains the user_id and user_site claims, and there are multiple Aconex accounts linked to the Lobby account specified by the sub claim, you can specify these claims in the request body.  You cannot specify these claims in both the User Assertion and the request body.

 
Step 4: Use the Access Token

Use the Access Token to make authorized requests to Aconex APIs on behalf of the authenticated user by including it in the Authorization header of your HTTP requests, as follows:


Authorization: Bearer 

Here is an example cURL request:


curl 'https://api.aconex.com/api/projects' \
--header 'Authorization: Bearer eyJ4NXQjUzI1NiI...KtK5elB38rcAbgFtVP9A'
 
 
Step 5: Refresh the Access Token

There is no refresh token flow for Non-Interactive Integrations.  When the Access Token expires, make the same POST request to the token endpoint of the Lobby to get a new Access Token.

Implement OAuth in a User-Bound Integration

User-Bound Integration is one that calls Aconex APIs without any user interaction.  Typical examples would be scripted integrations between a 3rd party application and Aconex, or software that runs on a scheduled basis and calls Aconex APIs to access data without any user interface. 

As its name suggests, a User-Bound Integration is bound to a single Lobby user account and is an easy-to-implement method for accessing Aconex APIs securely on behalf of a single Lobby user account within your organization.

When you register your User-Bound Integration, you must specify the Lobby user account to be bound to the integration.  This Lobby user account will be linked to one or more Aconex accounts.

A User-Bound Integration is a confidential client that uses the Client Credentials grant type to request an Access Token by making a POST request to the token endpoint of the Lobby.

There is no refresh flow for User-Bound Integrations.  When the Access Token expires, your integration should request a new Access Token.


Step 1: Obtain Client Credentials

Follow the steps to create an OAuth Client.

You will specify a Lobby user account to be bound to your integration. The Lobby user account may be linked to a single Aconex account, or multiple. Every call made to an Aconex API by your integration will be performed in the context of the user specified in this registration request.  If the Lobby account is linked to multiple Aconex accounts, you will specify the desired Aconex account when requesting an access token.

Your User-Bound Integration will be registered as a confidential client and you will receive client credentials in the form of a Client ID and Client Secret

These credentials must be kept confidential and must not be shared with anyone outside of your organization.

 

Step 2: Request a Token

Make a POST request to the token endpoint of the Lobby specifying your client credentials using Basic Authentication (Base64 encoding of the Client ID and Secret joined by a colon ':') and identifying the Aconex user account that is linked to the bound Lobby account, as follows:

POST /auth/token

Headers:
  Content-Type: application/x-www-form-urlencoded
  Authorization: Basic

Body:
  grant_type=client_credentials
  user_id=
user_site=

Here is an example cURL request:

curl --request POST 'https://constructionandengineering.oraclecloud.com/auth/token' \
--header 'Content-Type: application/x-www-form-urlencoded;charset=UTF-8' \
--header 'Authorization: Basic TXlDbGllbnRJRDpNeUNsaWVudFNlY3JldA==' \
--data-urlencode 'grant_type=client_credentials'
--data-urlencode 'user_id=123456789' \
--data-urlencode 'user_site=https://au1.aconex.com'

The response is in JSON format and contains the access token:

{
   "access_token": "eyJ4NXQjUzI1NiI...KtK5elB38rcAbgFtVP9A",
   "token_type": "Bearer",
   "expires_in": 3600
}
 
Step 3: Use the Access Token

Use the Access Token to make authorized requests to Aconex APIs on behalf of the authenticated user by including it in the Authorization header of your HTTP requests, as follows:

Authorization: Bearer 

Here is an example cURL request:

curl 'https://api.aconex.com/api/projects' \
--header 'Authorization: Bearer eyJ4NXQjUzI1NiI...KtK5elB38rcAbgFtVP9A'
 
Step 4: Refresh the Access Token

There is no refresh token flow for User-Bound Integrations.  When the Access Token expires, make the same POST request to the token endpoint of the Lobby to get a new Access Token.

OAuth Tokens

Access Token

An Access Token is a JSON Web Token (JWT) generated and signed by the Lobby to facilitate authenticated and authorized access to Aconex APIs.

Access Tokens have an expiry period of 1 hour.

Clients do not need to know the contents of an Access Token, but for troubleshooting purposes, the contents are described below.

Claim Information Provided
sub The Lobby account
idcs_access_token The underlying access token provided by Oracle Identity Cloud Service
user_hat The username of the Aconex user account
user_id The user ID of the Aconex user account
user_site The URL of the Aconex instance
scope The authorized scopes
amr The Authentication Methods References, which is a JSON array of strings that are identifiers for methods used in the authentication of the user (for example USERNAME_PASSWORD, or TOTP)
exp The token expiry time in seconds
iat The time the token was issued in seconds
client_id The Client ID of the client application

 

Refresh Token

A Refresh Token is a JSON Web Token (JWT) generated and signed by the Lobby to facilitate retrieval of a new Access Token when the old one has expired.

Refresh Tokens have an expiry period of 1 week (7 days).

Clients do not need to know the contents of a Refresh Token.

Error Handling

Web Server Applications and Installed Applications that implement the Authorization Code grant type to first request an Authorization Code may instead receive an error in the callback, as follows:

?error=

Here is an example:

https://myapp.com/oauth/callback?error=invalid_client

Any HTTP GET or POST may return Status Code 400 or 401 and a response Body, as follows:

{

  "error": ,
  "error_description": 
}

Here is an example:

{

  "error":"invalid_grant",
  "error_description":"Audience validation failed"
}

Possible error codes include:

Error Code Cause
invalid_client Either the Client ID or Secret was incorrectly specified.  Alternatively, an Installed Application may have attempted to include the Client ID in the Authorization header rather than request body.
invalid_grant The grant_type was incorrectly specified.
invalid_request The request has not been formed correctly.  Please refer closely to the documentation.