# Use OAuth2 Authentication with Event Notification Service

Access to the Event Notification Service (ENS) is secured using message signing and IP allowlisting. In some cases, it's preferable to have ENS authenticate with your system before pushing event notifications. To meet this requirement, ENS supports OAuth2 authentication.

These instructions assume that you’re familiar with the [Event Notification Service API](/docs/marketing/marketing-cloud/guide/ens.md).

## Supported Grant Types

Marketing Cloud Engagement supports authentication using the OAuth2 `client_credentials` and `password` grant types.

To use the `client_credentials` grant type, your system must support `clientId`, `clientSecret`, `authUrl`.

The `password` grant type uses resource owner password credential (ROPC). To use this grant type, your system must support `clientId`, `clientSecret`, `username`, `password`, `authUrl`.

:::note
The `password` grant type is considered a legacy authentication scheme. However, many customers find the level of risk for this use case to be acceptable.
:::

## OAuth2 Authorization Server Requirements

Your authorization server must be publicly accessible and must serve requests over HTTPS. It must be able to return authorization tokens within 2 seconds of the request being issued, and must support the concurrent provisioning of multiple tokens. The server must support client requests with parameters in `application/x-www-form-urlencoded` format with UTF-8 character encoding. Successful responses must include the `access_token` property.

If you use the `password` grant type, your server must support the HTTP Basic authentication scheme for authenticating clients that were issued a client password.

Optionally, responses can use the `access_token` scope. See [IETF: RFC 6749](https://tools.ietf.org/html/rfc6749#section-3.3).

## Create an ENS Callback Authentication Scheme

Before you configure ENS callbacks for authentication, create an authentication scheme. When you create or update calls for OAuth2 requests, verify that the authentication URL successfully returns a token.

When there is a delete request, ENS confirms that all callback associations with the authentication scheme have been removed. If this verification step isn't successful, the request fails.

### Client Credential Authentication Example

This code sample shows an example of a REST request using the `client_credential` grant type.

```json
Host: https://YOUR_SUBDOMAIN.rest.marketingcloudapis.com
POST /platform/v1/ens-authentications
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN

[
  {
    "authType": "oauth2",
    "grantType": "client_credentials",
    "clientId": "YOUR_CLIENT_ID",
    "clientSecret": "YOUR_CLIENT_SECRET",
    "authUrl": "https://example.com/oauth/token",
    "scope": "write"
  }
]
```

The response includes an `authID` parameter. Fields that contain sensitive data, such as the `clientId` and `clientSecret` fields, aren't included in the response.

```json
[
  {
    "authId": "22z825az-c2b5-46fe-81d0-d6abcbe8111c",
    "authType": "oauth2",
    "grantType": "client_credentials",
    "authUrl": "https://example.com/oauth/token",
    "scope": "write"
  }
]
```

### Password Authentication Example

This code sample shows an example of a REST request using the `password` grant type.

```json
Host: https://YOUR_SUBDOMAIN.rest.marketingcloudapis.com
POST /platform/v1/ens-authentications
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN

[
  {
    "authType": "oauth2",
    "grantType": "password",
    "clientId": "YOUR_CLIENT_ID",
    "clientSecret": "YOUR_CLIENT_SECRET",
    "username": "YOUR_USERNAME",
    "password": "YOUR_PASSWORD",
    "authUrl": "https://example.com/oauth/token",
    "scope": "write"
  }
]
```

The response includes an `authID` parameter. Fields that contain sensitive data, such as the `clientId`, `clientSecret`, `username`, and `password` fields, aren't included in the response.

```json
[
  {
    "authId": "22z825az-c2b5-46fe-81d0-d6abcbe8111c",
    "authType": "oauth2",
    "grantType": "password",
    "authUrl": "https://example.com/oauth/token",
    "scope": "write"
  }
]
```

## Create the ENS Callback

Register a new callback to receive event notifications by sending a POST request to the `/platform/v1/ens-callbacks` API endpoint.

```json
Host: https://YOUR_SUBDOMAIN.rest.marketingcloudapis.com
POST /platform/v1/ens-callbacks
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN

[
  {
    "callbackName": "cb1",
    "url": "https://example.com/sfmc-events",
    "maxBatchSize": 1000,
    "authId": "22z825az-c2b5-46fe-81d0-d6abcbe8111c"
  }
]
```

The response includes the callback ID and a signature key.

```json
HTTP/1.1 201 Created

[
  {
    "callbackName": "cb1",
    "callbackId": "65b885ab-c2b4-46fe-85d0-d6cb8be8057d",
    "url": "https://example.com/sfmc-events",
    "signatureKey":"V27FXfqI3DnhfQW1bhFDeJixpt8eDAY5R24UJI3cK6M=",
    "maxBatchSize": 1000,
    "authUrl": "22z825az-c2b5-46fe-81d0-d6abcbe8111c"
  }
]
```

To verify events via message signature, capture the value of the `signatureKey` property in the response.

For more information about the `ens-callbacks` endpoint, see [Create Callback](/docs/marketing/marketing-cloud/references/mc_rest_event_notification/createCallback.md).

## Verify ENS Callback

Verify that the callback can receive notifications by sending a POST request to the `/platform/v1/ens-verify` endpoint. The request includes the callback ID and the verification key from the creation request.

```json
Host: https://YOUR_SUBDOMAIN.rest.marketingcloudapis.com
POST /platform/v1/ens-verify
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN

{
  "callbackId": "65b885ab-c2b4-46fe-85d0-d6cb8be8057d",
  "verificationKey": "CZwJw4XATH6LK1fPWFeMDkIyVbro6T3ijXK8CrzQe2s="
}
```

If the callback is operating as expected, the API returns a `200 OK` response.

For more information about the `ens-verify` endpoint, see [Verify Callback](/docs/marketing/marketing-cloud/references/mc_rest_event_notification/verifyCallback.md).

## Create an ENS Subscription

After you verify the callback, create a subscription. A subscription indicates the event types that you want to receive notifications for and which callback to receive them on. A new subscription takes up to 2 minutes to become active. Each callback can have up to 200 subscribers.

Ensure that the callback you specify is ready to receive events before creating a subscription for it. This code provides an example of a request to create a subscription. It includes these properties:

| Property             | Type             | Description                                                                                                                                                                                                                                                                         |
| -------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `subscriptionName`   | String           | A unique name for the subscription.                                                                                                                                                                                                                                                 |
| `callbackId`         | String           | The unique identifier of the callback that receives the notification events. This callback must exist and must be verified.                                                                                                                                                         |
| `eventCategoryTypes` | Array of strings | The comma-separated list of fully qualified event types for which you’re requesting notifications. This list is expressed as `NotificationEventCategory.NotificationEventType`. See [Supported Notification Events](/docs/marketing/marketing-cloud/guide/ens-supported-events.md). |
| `filters`            | Array of strings | Each string in the array is a key-value pair to filter on. Filter values must use the syntax `key=value`. See [Subscription Filters](/docs/marketing/marketing-cloud/guide/ens-subscription-filters.md).                                                                            |

```json
Host: https://YOUR_SUBDOMAIN.rest.marketingcloudapis.com
POST /platform/v1/ens-subscriptions
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN

[
  {
    "callbackId": "65b885ab-c2b4-46fe-85d0-d6cb8be8057d",
    "subscriptionName": "sub1",
    "eventCategoryTypes": [
      "TransactionalSendEvents.EmailNotSent",
      "TransactionalSendEvents.EmailSent"
    ],
    "filters": ["definitionKey=12345"]
  }
]
```

The response includes a subscription ID and the status of the subscription.

```json
HTTP/1.1 201 Created

[
  {
    "callbackId": "65b885ab-c2b4-46fe-85d0-d6cb8be8057d",
    "callbackName": "cb1",
    "subscriptionName": "sub1",
    "eventCategoryTypes": [
      "TransactionalSendEvents.EmailNotSent",
      "TransactionalSendEvents.EmailSent"
    ],
    "subscriptionId": "d89c87c4-70f8-43d6-be1e-f01dce97fe4c",
    "filters": ["definitionKey=12345"],
    "status": "active"
  }
]
```

For more information about the `ens-subscription` endpoint, see [Create Subscription](/docs/marketing/marketing-cloud/references/mc_rest_event_notification/createSubscription.md).

## ENS Stream Processing

When the callback is configured and subscribed to, you can begin to send events to the authentication server. This code sample shows an example of a request to log an event.

:::important
The Authorization header in the request includes the bearer token only if the authentication token was retrieved successfully. If the token retrieval fails, the Authorization header contains a value of `Bearer null`, and the request fails.
:::

```js
Host: https://example.com
POST /sfmc-events
Content-Type: application/json
Authorization: Bearer b2f67f94-2956-42c0-88b3-c246f5da8ba0
x-sfmc-ens-signature: 0lpCnt5QNGcLbFJxw3H15wjtWI+T0ZaLUHlrCS6LWUQ=

[
  {
    "eventCategoryType":"TransactionalSendEvents.EmailSent",
    "timestampUTC":1596137717051,
    "compositeId":"6b1a9f18-2de9-e911-a2d6-1402ec938821.14598719.2262900.400.935980107",
    "definitionKey":"eventbus_definition_key",
    "mid":10991090,
    "eid":10991090,
    "info": {
      "to":"eventbus@bh.exacttarget.com",
      "subscriberKey":"eventbus_sub_key",
      "messageKey":"072b0950-1f41-4ed4-9920-b65b033b2f47",
      "status":"Sent",
      "renderedSubject":"Test email"
    },
    "definitionId":"6b1a9f18-2de9-e911-a2d6-1402ec938821"
  }
]
```

## Update ENS Callback Authentication

To modify the authentication configuration for a callback, send a PUT request to the `/platform/v1/ens-authentications` endpoint. There can be a delay of a few minutes before the changes to the callback become active. This code example shows how to update a callback.

```js
Host: https://YOUR_SUBDOMAIN.rest.marketingcloudapis.com
PUT /platform/v1/ens-authentications
Content-Type: application/json
Authorization: Bearer YOUR_ACCESS_TOKEN

[
  {
    "authId": "22z825az-c2b5-46fe-81d0-d6abcbe8111c",
    "authType": "oauth2",
    "grantType": "password",
    "clientId": "myClientId",
    "clientSecret": "myClientSecret",
    "username": "exampleUsername",
    "password": "examplePassword",
    "authUrl": "https://example.com/oauth/token"
  }
]
```

The response includes an updated `authId` property.

```js
HTTP/1.1 200 OK

[
  {
    "authId": "22z825az-c2b5-46fe-81d0-d6abcbe8111c",
    "authType": "oauth2",
    "grantType": "password",
    "authUrl": "https://example.com/oauth/token"
  }
]
```
