This topic provides a general overview and a technical explanation of OAuth2 authentication for the Digital Commerce Gateway.
note: The documentation in this section applies only to customers who have purchased the Digital Commerce Gateway license. The instructions provided don't work without the Digital Commerce Gateway license.
Prerequisites
To use the information in this document, you must have previously requested and obtained a DCG environment. After the environment is provisioned, Salesforce sends you the following information:
-
The DCG Endpoint
-
Format:
api.{myenv}.{customername}.dc.vloc-dev.comor
api.{myenv}.{customername}.dc.vloc-prod.com
-
-
The OAuth2 Server
- Format:
vlocity-dc-{customername}-{platform}.auth.{region}.awscognito.com.com
- Format:
-
Four sets of OAuth2 credentials for this environment:
-
admin
-
cmig
-
ops
-
user
-
List of the DCG endpoints and associated scopes
You will find the mapping between app clients, scopes, and endpoints below. For each endpoint, you will find the list of methods authorized with which app client and scopes.
# App clients and matching scopes access
oauth2-{env}-admin = [admin, ops, user, cmig]
oauth2-{env}-cmig = [cmig]
oauth2-{env}-ops = [ops, user]
oauth2-{env}-user = [user]
# Scopes
- admin
- cmig
- ops
- user
# Digital Commerce
/dc/app-status
OPTIONS no-auth (AWS Mock 200)
ANY oauth2-{env}:[admin, ops]
/dc/app-diagnostic
OPTIONS no-auth (AWS Mock 200)
ANY oauth2-{env}:[admin, ops]
/dc/{proxy}+
OPTIONS no-auth (AWS Mock 200)
DELETE oauth2-{env}:[admin, ops]
PATCH oauth2-{env}:[admin, ops]
ANY oauth2-{env}:[admin, ops, user]
# Cache Migration
/cm/app-status
OPTIONS no-auth (AWS Mock 200)
ANY oauth2-{env}: [admin, ops]
/cm/app-diagnostic
OPTIONS no-auth (AWS Mock 200)
ANY oauth2-{env}: [admin, ops]
/cm/{proxy}+
OPTIONS no-auth (AWS Mock 200)
DELETE oauth2-{env}: [admin, cmig]
PATCH oauth2-{env}: [admin, cmig]
ANY oauth2-{env}: [admin, cmig, ops]
# Cache Administration
/admin/cache/status
OPTIONS no-auth (AWS Mock 200)
GET oauth2-{env}: [admin, ops]
/admin/cache/list
OPTIONS no-auth (AWS Mock 200)
GET oauth2-{env}: [admin, ops]
/admin/cache/flush
OPTIONS no-auth (AWS Mock 200)
POST oauth2-{env}: [admin, ops]
OAuth2 Description
“Cognito Application Clients” customer keys and secrets are:

-
Used to request an OAuth2 JWT to the AWS Cognito OAuth2 server.
-
Generated by Salesforce and provided to the customer.
-
Specific to each environment.
OAuth2 JWT (JSON Web Token):
-
The OAuth2 JWT are temporary authorization code used to access the DCG API Endpoints.
-
These are obtained from the AWS Cognito OAuth2 server by a trusted client application.
-
The DCG OAuth2 JWT can be reused multiple times until its expiration date and can be shared by several application clients to connect to the same API.
-
The expiration time of the JWT is 3600 seconds (1 hour) and cannot be changed at the moment (AWS Cognito constraint).
The JSON Web Token or Bearer Token received from the OAuth2 server (also known as the AWS Cognito server) contains the following (among other things):
-
A string identifying the customer application used to deliver the token
-
A timestamp and expiration date
-
A scope or list of scopes that this token grants access to
-
A signature (to prevent JWT forgery)
You can find more information about OAuth2 JWT here: https://oauth.net/2/jwt/.
DCG uses OAuth2 Scopes to control access to the protected resource. Each Application Client is granted a list of scopes represented by arbitrary strings. The protected resources are assigned one or more scopes for specific paths. The scope, being part of the JWT content, the protected resource can validate whether the client has access to and/or requested access to this specific resource.
Implementation of OAuth2 for Digital Commerce
Below is a sample procedure with example calls to obtain and consequently use an OAuth2 JWT token against a sample test deployment.
-
Obtain an OAuth2 JWT access token: Obtaining an OAuth2 JWT access token requires making a POST HTTPS request to the AWS OAuth2 Cognito endpoint using a specific set of credentials which Salesforce has created and provided. These credentials are referred to as customer application secrets.
Multiple sets of secrets with different access levels are provided.
# "Cognito Application Clients": customer application secrets customer_app_key="6gi8...imprk" customer_app_secret="1dh9t...4iu2rn" # cognito_oauth2_server (provided by Salesforce, below is an example) cognito_oauth2_server="vl-dc-test.auth.eu-central-1.amazoncognito.com" # Template curl call to retrieve an oauth2 token curl -s -X POST --user "${customer_app_key}:${customer_app_secret}" \ -H 'Content-Type: application/x-www-form-urlencoded' \ "https://${cognito_oauth2_server}/oauth2/token?grant_type=client_credentials" # Response template: { "access_token": "[...]", "expires_in": 3600, "token_type": "Bearer"} # Example call curl -s -X POST --user "6gi88ku...9imprk:1dh9to...0j4iu2rn" \ -H 'Content-Type: application/x-www-form-urlencoded' \ "https://vl-dc-test.auth.eu-central-1.amazoncognito.com/oauth2/token?grant_type=client_credentials" # Example response:{"access_token":"eyJraWQiOiJQbGkyTkJcL3NBczBabkVWaXdPS0ZhQ0JsbWpHcUxXblFOMlo0RmE1d09Ecz0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI2Z2k4OGt1bmdkbmI0NDB0OWdpYzlpbXByayIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiZGMtdGVzdC1hcGlcL2FkbWluIGRjLXRlc3QtYXBpXC9yZWFkIGRjLXRlc3QtYXBpXC93cml0ZSIsImF1dGhfdGltZSI6MTU2MzM3NjMxNiwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLmV1LWNlbnRyYWwtMS5hbWF6b25hd3MuY29tXC9ldS1jZW50cmFsLTFfelJHb2dweHc4IiwiZXhwIjoxNTYzMzc5OTE2LCJpYXQiOjE1NjMzNzYzMTYsInZlcnNpb24iOjIsImp0aSI6IjFmYTU5YWQ1LTIwNDEtNDAyZS04NGIxLTExNjFjMWIxMmQ1YyIsImNsaWVudF9pZCI6IjZnaTg4a3VuZ2RuYjQ0MHQ5Z2ljOWltcHJrIn0.awj5M4AvLXbL7TJrPIQguEUv2ifFurmZnqZraoNy5g9UP365_vknj-hJrgFzZ4OtOYlopQTdMgD-8m1n7vVqwUPfywr8qK2bJHOS8Dm9WycNypnsiFYC4eIDHjLd2526-G63w6shTj4B53QmtpCzJF8lIvB9rGcsiQgxIlRNK9ZRSmc0opHZSLnts0xeLUvHCW5eb5Uys7eIY_MPtc6GAMca0A6AObxADdklHMYLLagvEZdPPtj-A-HG04jLuNCwcS3lpuhtmw7W0F0hgGhIIuI0ZQez7TxzdeaV2B3v9_P_dLPe18-3mD1BV0kZyjYqcZYqFo4nHSg-UT33FLByWg","expires_in":3600,"token_type":"Bearer"} -
Use an OAuth2 JWT: The resource protected by OAuth2 tokens can be accessed after you have retrieved a valid OAuth2 bearer token (also known as a JWT):
# Obtain the FQDN of the resource to access / protect (in this case the DCG API)api_fqdn="api-test-cognito.platform.customer.dc.vloc-dev.com" # Example of URL path of the resource to be accessed url_path="/dc/app-status" url_path="/dc/v3/catalogs/CATALOG_CODE/offers" # The OAuth2 response from cognito is stored in the oauth2_cognito_response oauth2_cognito_response='{"access_token":"[...]","expires_in":3600,"token_type":"Bearer"}' # The OAuth2 token is stored in the variable oauth2_token # Example of extraction of the access_token from oauth2_cognito_response via Python’s jq tool oauth2_token="$(echo -e "$oauth2_cognito_response" | jq -r .access_token )" # Template for calls made to the protected resource: curl -s -i -X GET -H "authorization: Bearer ${oauth2_token}" \ -H "Content-Type: application/json; charset=UTF-8" \ "https://${api_fqdn}${url_path}" ; echo -e "\n\nCurl returned $?"# Example: # - Setting variables and contextapi_fqdn="api-test-cognito.platform.customer.dc.vloc-dev.com" url_path="/dc/app-status" oauth2_token="eyJraWQiOiJQbGkyTkJcL3NBczBabkVWaXdPS0ZhQ0JsbWpHcUxXblFOMlo0RmE1d09Ecz0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI2Z2k4OGt1bmdkbmI0NDB0OWdpYzlpbXByayIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiZGMtdGVzdC1hcGlcL2FkbWluIGRjLXRlc3QtYXBpXC9yZWFkIGRjLXRlc3QtYXBpXC93cml0ZSIsImF1dGhfdGltZSI6MTU2MzM3NjMxNiwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLmV1LWNlbnRyYWwtMS5hbWF6b25hd3MuY29tXC9ldS1jZW50cmFsLTFfelJHb2dweHc4IiwiZXhwIjoxNTYzMzc5OTE2LCJpYXQiOjE1NjMzNzYzMTYsInZlcnNpb24iOjIsImp0aSI6IjFmYTU5YWQ1LTIwNDEtNDAyZS04NGIxLTExNjFjMWIxMmQ1YyIsImNsaWVudF9pZCI6IjZnaTg4a3VuZ2RuYjQ0MHQ5Z2ljOWltcHJrIn0.awj5M4AvLXbL7TJrPIQguEUv2ifFurmZnqZraoNy5g9UP365_vknj-hJrgFzZ4OtOYlopQTdMgD-8m1n7vVqwUPfywr8qK2bJHOS8Dm9WycNypnsiFYC4eIDHjLd2526-G63w6shTj4B53QmtpCzJF8lIvB9rGcsiQgxIlRNK9ZRSmc0opHZSLnts0xeLUvHCW5eb5Uys7eIY_MPtc6GAMca0A6AObxADdklHMYLLagvEZdPPtj-A-HG04jLuNCwcS3lpuhtmw7W0F0hgGhIIuI0ZQez7TxzdeaV2B3v9_P_dLPe18-3mD1BV0kZyjYqcZYqFo4nHSg-UT33FLByWg"# - Running the command curl -s -i -X GET -H "authorization: Bearer ${oauth2_token}" \ -H "Content-Type: application/json; charset=UTF-8" \ "https://${api_fqdn}${url_path}" ; echo -e "\n\nCurl returned $?" # - Received response HTTP/2 200 date: Mon, 10 Aug 2020 15:36:32 GMT content-type: application/vnd.spring-boot.actuator.v2+json;charset=UTF-8 content-length: 586 x-amzn-requestid: 4c427148-f29e-4d34-b909-00594a31728d x-amz-apigw-id: RD1r8GTePHcF4Yw= x-amzn-lambda-integration-tag: 457b37f4-324c-4ba3-a405-e87945962669 vloc-op-cache: NOT_APPLICABLE x-amzn-trace-id: Root=1-5f31697f-895fde273e05332417fd3f41 {"status":"UP","details":{"health":{"status":"UP","details":{"app_name":"Vlocity V3 Edge API","version":"1.0-SNAPSHOT","build_time":"2020-06-11T14:03:37Z","build_info":{"commit":"f925489","buildInfo":"tblanchard@tblanchard","branch":"v17","date":"2020-06-11T14:03:37Z"},"salesforce_last_contact":"","app_start_time":"2020-08-10T15:09:58.058Z","jks_expire_ms":"2022-03-22T09:16:52+0000"}},"redis":{"status":"UP","details":{"redis":"UP","hits":55516102,"misses":7363576,"evicted":0,"expired":178034,"hit_ratio":0.88,"con_active":0,"con_idle":0,"con_wait":0,"redis_pool_size":8}}}} -
Scopes with different endpoints and app-clients: The resource protected by OAuth2 tokens can be accessed once we have retrieved a valid oauth2 bearer token.
Not all app-clients give access to all resources; this allows you to share or use different app clients depending on your users.
You will find the complete list of endpoints and scope access in the next section.
The following is an example with the following 2 app clients
oauth2-myenv-ops scope access: ops and user oauth2-myenv-user scope access: userThe URL path
/dc/app-statusis accessible by all scopes (admin, ops, user).The URL path
/dc/v3/catalogs/CATALOG_CODE/offersis accessible only by the admin and ops scopes.To set up different endpoints and app-clients:
cognito_oauth2_server="vl-dc-test.auth.eu-central-1.amazoncognito.com" # We’ve created a second "Cognito Application Clients" with different scopes # Retrieve and store a different JWT with each set of credentials # Template curl call to retrieve an oauth2 token curl -s -X POST --user "${customer_app_key}:${customer_app_secret}" -H 'Content-Type: application/x-www-form-urlencoded' "https://${cognito_oauth2_server}/oauth2/token?grant_type=client_credentials" # "Cognito Application Clients" oauth2-myenv-ops with ops and user scopes customer_app_key="6gi88ku...9imprk" customer_app_secret="1dh9to...0j4iu2rn" oauth2_token_ops=[...] # "Cognito Application Clients" oauth2-myenv-user with only user scope customer_app_key="7j2o4n...4u97ri" customer_app_secret="10m997...inlejh" oauth2_token_user=[...]Responses received using the oauth2_token_user JWT from the oauth2-myenv-user app client:
-
/dc/v3/catalogs/CATALOG_CODE/offers should return 200 unauthorized
-
/dc/app-status should return 401
api_fqdn="api-test-cognito.platform.customer.dc.vloc-dev.com" url_path="/dc/v3/catalogs/CATALOG_CODE/offers" curl -s -i -X GET -H "authorization: Bearer ${oauth2_token_user}" -H "Content-Type: application/json; charset=UTF-8" "https://${api_fqdn}${url_path}" HTTP/2 200 date: Mon, 22 Jul 2019 14:13:38 GMT content-type: application/json;charset=ISO-8859-1 content-length: 12332 x-amzn-requestid: e65a90de-ac8a-11e9-93cd-9d8d58cb662d x-amzn-remapped-content-length: 12332x-amz-apigw-id: dOum1EZeFiAFg8Q= x-amzn-trace-id: Root=1-5d35c492-6dbf677d7c12525a746c90fe;Sampled=0 [...body...] api_fqdn="api-test-cognito.platform.customer.dc.vloc-dev.com" url_path="/dc/app-status" curl -s -i -X GET -H "authorization: Bearer ${oauth2_token_user}" -H "Content-Type: application/json; charset=UTF-8" "https://${api_fqdn}${url_path}" HTTP/2 401 date: Mon, 22 Jul 2019 14:13:32 GMT content-type: application/json content-length: 26 x-amzn-requestid: e2bf9017-ac8a-11e9-b915-3f49f14f8dec x-amzn-errortype: UnauthorizedException x-amz-apigw-id: dOul5H4YFiAFsxQ= {"message":"Unauthorized"}Responses received using the oauth2_token_ops JWT from the oauth2-myenv-ops app client:
-
/dc/v3/catalogs/CATALOG_CODE/offers should return 200
-
/dc/app-status should return 200
api_fqdn="api-test-cognito.platform.customer.dc.vloc-dev.com" url_path="" curl -s -i -X GET -H "authorization: Bearer ${oauth2_token_ops}" -H "Content-Type: application/json; charset=UTF-8" "https://${api_fqdn}${url_path}" HTTP/2 200 date: Mon, 22 Jul 2019 14:30:16 GMT content-type: application/json content-length: 19 x-amzn-requestid: 3929aeba-ac8d-11e9-b4cd-11d6a4139ed9 x-amz-apigw-id: dOxCwFxMliAFZkw= {"statusCode": 200} api_fqdn="api-test-cognito.platform.customer.dc.vloc-dev.com" url_path="/dc/app-status" curl -s -i -X GET -H "authorization: Bearer ${oauth2_token_user}" -H "Content-Type: application/json; charset=UTF-8" "https://${api_fqdn}${url_path}" HTTP/2 200 date: Mon, 22 Jul 2019 14:32:38 GMT content-type: application/json;charset=ISO-8859-1 content-length: 697 x-amzn-requestid: 8e0c7ccc-ac8d-11e9-b742-815dfc2c8abc x-amzn-remapped-content-length: 697x-amz-apigw-id: dOxZBGEXliAFheg= x-amzn-trace-id: Root=1-5d35c906-d3704ba9ad66385d1f8c14c6;Sampled=0 -
Troubleshooting
If the application returns an HTTP status code other than 200 or 401, it may not be related to OAuth2 setup. For example, 403, 404, and 500 HTTP status codes are generally not related with OAuth2 setup or usage.
-
Error code 401: Access denied, see next section “Common 401 HTTP status code and errors returned by oauth2 auth“ for the different scenarios.
-
Error code 403: If you receive a code 403 from the DCG application, it generally means that there is a problem with the configuration of your client. It can be any of the following:
-
Wrong URL or path.
-
Missing or misspelled headers.
-
Client IP outside access list when allow list has been configured (endpoints are opened to the world by default).
-
-
Error code 5xx: These errors generally indicate an issue with the DC API request itself or the data sets retrieved. Please get in touch with Customer Support or Professional Services to solve them.
-
Common 401 HTTP status code and errors returned by oauth2 auth:
-
Expired token:
# - declaring an expired token oauth2_token="eyJraWQiOiJQbGkyTkJcL3NBczBabkVWaXdPS0ZhQ0JsbWpHcUxXblFOMlo0RmE1d09Ecz0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI2Z2k4OGt1bmdkbmI0NDB0OWdpYzlpbXByayIsInRva2VuX3VzZSI6ImFjY2VzcyIsInNjb3BlIjoiZGMtdGVzdC1hcGlcL2FkbWluIGRjLXRlc3QtYXBpXC9yZWFkIGRjLXRlc3QtYXBpXC93cml0ZSIsImF1dGhfdGltZSI6MTU2MzM3NjMxNiwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLmV1LWNlbnRyYWwtMS5hbWF6b25hd3MuY29tXC9ldS1jZW50cmFsLTFfelJHb2dweHc4IiwiZXhwIjoxNTYzMzc5OTE2LCJpYXQiOjE1NjMzNzYzMTYsInZlcnNpb24iOjIsImp0aSI6IjFmYTU5YWQ1LTIwNDEtNDAyZS04NGIxLTExNjFjMWIxMmQ1YyIsImNsaWVudF9pZCI6IjZnaTg4a3VuZ2RuYjQ0MHQ5Z2ljOWltcHJrIn0.awj5M4AvLXbL7TJrPIQguEUv2ifFurmZnqZraoNy5g9UP365_vknj-hJrgFzZ4OtOYlopQTdMgD-8m1n7vVqwUPfywr8qK2bJHOS8Dm9WycNypnsiFYC4eIDHjLd2526-G63w6shTj4B53QmtpCzJF8lIvB9rGcsiQgxIlRNK9ZRSmc0opHZSLnts0xeLUvHCW5eb5Uys7eIY_MPtc6GAMca0A6AObxADdklHMYLLagvEZdPPtj-A-HG04jLuNCwcS3lpuhtmw7W0F0hgGhIIuI0ZQez7TxzdeaV2B3v9_P_dLPe18-3mD1BV0kZyjYqcZYqFo4nHSg-UT33FLByWg" # - Running the command curl -s -i -X GET -H "authorization: Bearer ${oauth2_token}" -H "Content-Type: application/json; charset=UTF-8" "https://${api_fqdn}${url_path}" ; echo -e "\n\nCurl returned $?" # - Received response HTTP/2 401 date: Thu, 04 Jul 2019 12:35:15 GMT content-type: application/json content-length: 44 x-amzn-requestid: 2cd359f0-9e58-11e9-a702-3b62603f614d x-amzn-errortype: UnauthorizedException x-amz-apigw-id: cTLUlGjdliAFbig= {"message":"The incoming token has expired"} -
Malformed token: In the following example, remove some characters from the end of the base64 oauth2 token, in effect corrupting the signature.
# - Received response HTTP/2 403 date: Mon, 22 Jul 2019 13:39:21 GMT content-type: application/json content-length: 27 x-amzn-requestid: 1c7a8f4b-ac86-11e9-b10d-e70db1458280 x-amzn-errortype: AccessDeniedException x-amz-apigw-id: dOpleEcSFiAFdxg= {"Message":"Access Denied"}
-
-
Invalid token: The token is not authorized to access this request (e.g. the scope of the Application Client does not grant access to a specific resource).
# - Received response HTTP/2 401 date: Wed, 03 Jul 2019 15:00:06 GMT content-type: application/json content-length: 26 x-amzn-requestid: 3ec26cce-9da3-11e9-8211-2d7edd287f91 x-amzn-errortype: UnauthorizedException x-amz-apigw-id: cQNmlFoEFiAFppA= {"message":"Unauthorized"}
See Also
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization
- https://oauth.net/2/bearer-tokens/
- https://swagger.io/docs/specification/authentication/bearer-authentication/
- https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html
- https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html