Using Mailchimp’s OAuth Flow with Self-Hosted Integrations

Introduction

OAuth is the recommended and most secure authentication method for building Mailchimp integrations. OAuth uses a redirect URI, which Mailchimp requires, to increase security and prevent attackers from redirecting users to malicious websites. The URI specified allows Mailchimp to match the URI at the end of the authentication flow increasing security and ensures that we send the user to the appropriate website. Self-hosted integrations struggle to implement the OAuth flow because their integrations run on multiple domains, therefore they have multiple redirect URIs.

This guide describes the recommended architecture and best practices for using a middleware architecture which will serve as a single redirect URI by which self hosted applications can authenticate. Mailchimp strongly recommends that you use this solution to ensure a consistent redirect URI that supports the Mailchimp OAuth flow described below.

Before You Start

To ensure a secure connection, Mailchimp recommends the following:

  • Communication between the store server and the middleware server should take place over TLS (1.3 recommended).

  • Middleware servers should delete records every few minutes. During the OAuth flow to Mailchimp, the request that exchanges an authorization code for an access token must take place quickly. The middleware server should dispose of expired authorization codes and access tokens that have been passed along to the store servers.

Database Design

The Mailchimp middleware server is used for authentication purposes only and only needs to hold data for a limited time.

We recommended a database table structure similar to the example below.

Columns: Type

domain: String

temporary_expiring_token: String

access_token: String

expires_at: DateTime

Additional Requirements

It is recommended that you run a cron job or background process that deletes user data every few minutes. The cron job should delete the records with an expires_at timestamp that indicates it should be deleted. This helps ensure security by not holding onto access tokens for longer than necessary.

Deployment, Configuration, and Maintenance

All middleware server maintenance is the developer’s responsibility. Mailchimp does not require that you deploy your middleware application to any particular service, use any specific programming language, or database. If you have additional questions or concerns, contact the Mailchimp Partnerships team at partnerships@mailchimp.com and we will be happy to assist you.

Required Components

  • Self-Hosted Application: An e-commerce store or service running in a self-hosted environment with a Mailchimp integration or plugin installed. Throughout the flow, we differentiate calls from the store’s server and the store’s browser. Once authenticated, all communications with Mailchimp is done via the API and not made through the middleware server.

  • Middleware Server: A registered Mailchimp application that handles all authentication between Mailchimp and the application. It also has the following:

    • Single Redirect URI that Mailchimp will use to redirect users to upon authentication.

    • OAuth client_id and client_secret stored on the server in a .env file.

    • TLS protocol for all communication between the application and the middleware server

  • Mailchimp: The traditional OAuth flow will take place once the middleware server redirects the user to Mailchimp. Refer to How to Use OAuth2. for detailed instructions.

Middleware Flow Overview

The following overview illustrates the flow between a self-hosted application that authenticates with Mailchimp through the middleware server.

Note that as of February 2019, the Mailchimp security team recommends the flow described in this article. You can modify this flow, however, we highly encourage you to contact the Mailchimp Partnerships team to obtain security approval.

The store’s server makes a POST request to the middleware server with a payload of { “domain”: “example.com” }.

Store Server: POST { "domain": "example.com"}

The middleware server stores this domain for verification in the future when returning the access token. The middleware server returns a temporary expiring token generated by the middleware server, which will be stored on the Store Server (cache, database, session). This is used for association and authentication.

Middleware Server Response: { "temporary_expiring_token": "token" }

The store’s browser opens a modal that sends a GET request to the middleware server along with a query string variable with the value set as the temporary expiring token.

Browser: GET middlewareserver.com/start?temp_token=$temporary_expiring_token

The store’s browser performs an AJAX GET request every few seconds to verify that the authentication process is complete and an access token is available.

Store Client/Browser: GET every few seconds to middlewareserver.com/status?temp_token=$temporary_expiring_token

The middleware server responds with the status of the authentication. Some optional statuses may include, but are not limited to, pending(no result), accepted(access token available), denied(user did not authenticate), and expired(user did not complete the process in the allowed time).

Middleware Server: Responds with the status of the authentication(pending,accepted,denied,expired)

While the self-hosted application checks for the status, the actual Mailchimp OAuth flow takes place. The middleware server redirects the GET request to Mailchimp’s authorize endpoint where the login form is displayed.

Middleware Server: Redirects to https://login.mailchimp.com/oauth2/authorize

Upon the user successfully logging in, Mailchimp redirects to the middleware server with the code via a query string variable. This code is used to retrieve the access token.

Mailchimp redirects back to redirect_uri as a GET request with the code as the parameter middlewareserver.com/oauth/complete.php?code=example_code

The middleware server performs a POST request to Mailchimp’s token endpoint with the client id, client secret, and code. This returns an access token.

Middleware Server: POSTS to https://login.mailchimp.com/oauth2/token with { "client_id": "id", "client_secret": "secret", "code": "example_code" }

MailChimp responds with the access token that the middleware server stores in its database.

Mailchimp: Response { "access_token": "token", "expires_in": 0, "scope": null }

During this process, the self-hosted application was performing the periodic AJAX GET requests to check the status of the authentication. The middleware server returns an accepted status letting the self-hosted application know that the access token is available.

Middleware Server: Responds to the AJAX status call with an "accepted" status

The store’s server refreshes the page and performs a POST request with the domain and temporary expiring token so it can retrieve the access token.

Store Server: POST { "domain": "example.com", "token": "temporary_expiring_token" }

The middleware server returns the access token and the self-hosted application stores this access token to perform API calls to Mailchimp in the future.

Middleware Server: Response{ "access_token": "token" }

Finally, the cron job runs every few minutes to delete the domain, access token, and temporary expiring token for all records with an appropriate expires_at timestamp. This ensures security for our user’s data.

Thank you for reading. Are you considering building an integration with Mailchimp? Please reach out to our Partnerships team at partnerships@mailchimp.com and we would be happy to talk to you about how Mailchimp can help your users.