Skip to content

Creating grants with OAuth and an access token

Nylas supports Hosted OAuth to get the user’s authorization for scopes and create their grant, and PKCE for extra security during the process.

If you’re developing a single page application (SPA) or a mobile app, we recommend you use [Hosted OAuth with PKCE]. This extra layer of security adds a key to the authentication exchange that you can safely store on a mobile device, instead of including the API key. This is optional for projects that have a backend, but it’s a good security practice to implement anyway.

How Hosted OAuth works

Nylas creates only one grant per email address in each application. If a user authenticates with your Nylas application using the email address associated with an existing grant, Nylas re-authenticates the grant instead of creating a new one.

  1. The user clicks a link or button in your project to start an authorization request.
  2. Nylas forwards the user to their provider where they complete the authorization flow.
  3. The provider directs the user to the Nylas callback URI and includes URL parameters that indicate whether the authorization succeeded or failed, along with other information.
  4. If the authorization succeeded, Nylas creates an unverified grant record.
  5. Nylas forwards the user to your project’s callback URI and includes the access code from the provider as a URL parameter.
  6. Your project uses the code to perform a token exchange with the provider.
  7. When the token exchange completes successfully, Nylas marks the grant record as verified and creates a grant ID for the user.

Start an authorization request

The first step of the authentication process is to start an authorization request. Usually this is a button or link that the user clicks.

Your project redirects the user to the authorization request endpoint and includes their information as a set of query parameters, as in the example below. When the user goes to this URL, Nylas starts a secure authentication session and redirects them to their provider’s website.

Each provider displays their authorization consent and approval steps differently. The steps are visible only to the user.

If a user authenticates using their Google account, they might be directed to Google’s authorization page twice. This is a normal part of the Hosted OAuth flow, and it ensures that the user approves all necessary scopes.

Use access_type to request refresh tokens

You can use the access_type parameter in your authorization request to indicate whether you want Nylas to return a refresh token for the grant.

If you’re developing a mobile or client-side-only app, we recommend you use access_type=online. This prevents the OAuth process from creating a refresh token. When you use this method, your users need to re-authenticate manually when their access token expires.

Otherwise, you can use access_type=offline to get a refresh token when a user authenticates. You can use the refresh token to request a new access token for the user when their old one expires, without prompting them to re-authenticate.

For security reasons, we strongly recommend against using access_type=offline for mobile and client-side-only apps. In these cases it’s best for your users to manually re-authenticate when their access tokens expire.

Pass user information in state parameter

Nylas Hosted OAuth supports the optional state parameter. If you include it in an authorization request, Nylas returns the unmodified value to your project. You can use this as a verification check, or to track information about the user that you need when creating a grant or logging them in.

For more information about the state parameter, see the OAuth 2.0 specification and the official OAuth 2.0 documentation.

Accept authorization response

After the user completes the authorization process, their provider sends them to Nylas’ redirect URI (https://api.us.nylas.com/v3/connect/callback) and includes URL parameters with information about the user. Nylas uses the information in the parameters to find your application using its client ID and, if the authentication succeeded, create an unverified grant record for the user.

Nylas then uses your application’s callback URI to direct the user back to your project, along with the code it received from the provider.

https://myapp.com/callback-handler?code=<CODE>

If you specified a state in the initial authorization request, Nylas includes it as a URL parameter.

Exchange code for access token

The OAuth code is a unique, one-time-use credential. This means that if your POST /v3/connect/token request fails, you’ll need to restart the OAuth flow to generate a new code. If you try to pass the original code in another token exchange request, Nylas returns an error.

Make a POST /v3/connect/token request to exchange the user’s code for an access token. Nylas returns an access token and other information about the user.

The user’s provider responds with an access token, a refresh token (because you set access_type=offline in your authorization request), and some other information.

{
"access_token": "<ACCESS_TOKEN>",
"refresh_token": "<REFRESH_TOKEN>",
"scope": "<SCOPES>",
"token_type": "Bearer",
"id_token": "<ID_TOKEN>",
"grant_id": "<NYLAS_GRANT_ID>"
}

OAuth 2.0 access tokens expire after one hour. When the access token expires, you can either use the refresh token to get a new access token, or the user can re-authenticate their grant to access your project.

Nylas marks the user’s grant as verified and sends you their grant ID and email address.

Your project should store the user’s grant ID, access token, and refresh token (for later re-authentication).

Secure the authentication process with PKCE

The OAuth PKCE (Proof Key for Code Exchange) flow improves security for client-side-only applications, such as browser-based or mobile apps that don’t have a backend server. Even if your project does have a backend server, we recommend you use PKCE for extra security.

Never store application-wide credentials like API keys in mobile or client-side code. You should complete the code exchange flow without using your Nylas application’s API key. If you’re using PKCE, you can set platform to android, desktop, ios, or js when you create a callback URI to make the client_secret field optional.

Create a code_challenge

Before you make an authentication request using PKCE, you need to create a code_challenge. You’ll use this when you [make an authorization request].

The following example uses nylas as a code verification string and sets the encoding method to S256 for extra security.

If you don’t set an encoding method, Nylas assumes you’re using a plain text code verification string. We strongly recommend you use SHA-256 encoding to create a more secure code_challenge.

  1. Hash the verification string using an SHA-256 encoding tool (SHA256("nylas") -> e96bf6686a3c3510e9e927db7069cb1cba9b99b022f49483a6ce3270809e68a2).
  2. Convert the hashed string to Base64 encoding and remove any padding (e96bf6686a3c3510e9e927db7069cb1cba9b99b022f49483a6ce3270809e68a2 -> ZTk2YmY2Njg2YTNjMzUxMGU5ZTkyN2RiNzA2OWNiMWNiYTliOTliMDIyZjQ5NDgzYTZjZTMyNzA4MDllNjhhMg).
  3. Save the resulting encoded string to use as the code_challenge in your [authorization request].

Make authorization request with code_challenge

Make a GET /v3/connect/auth request to create a URL that redirects your user to the authorization flow.

Exchange code for access token with code_challenge

The rest of the OAuth flow proceeds as usual: your project redirects the user to their provider where they authenticate and either accept or reject the requested scopes. The provider then sends them back to Nylas with an authorization code, and Nylas creates an unverified grant record. Nylas returns the user to your project with the code.

Next, use the code in a POST /v3/connect/token request to get an access token. Because you’re using PKCE, you need to set the grant_type to authorization_code and include your code_verifier.

For readability, the example below sets code_verifier to the original plain text code_challenge value.

Make API requests with access token

Now that you have a grant for your user, you can make requests on their behalf with their access token and the /me/ syntax.

You can’t use an access token to authorize API requests that access or modify data at the application level. Those requests require an API key for authorization.

To authorize an API request, pass the user’s access token in the request header and substitute me where you’d usually specify a grant ID.

curl --request GET \
--url 'https://api.us.nylas.com/v3/grants/me/calendars' \
--header 'Authorization: Bearer <ACCESS_TOKEN>' \
--header 'Content-Type: application/json'

When Nylas receives a request using the /me/ syntax, it checks the authorization header token, finds the associated grant ID, and uses that ID to locate the user’s data.

Refresh an expired access token

If you set access_type=offline in your authorization request, Nylas returns a refresh token along with the access token during the token exchange process. When the access token expires, you can use the refresh token to request a new one.

Refresh tokens don’t expire unless they’re revoked. If your project is client-side-only, you shouldn’t request offline access or need this step.

Make a POST /v3/connect/token request that sets the grant_type to refresh_token and includes the user’s refresh token. The user’s provider returns a fresh access token for their grant.

Handle authentication errors

If the authentication process fails, Nylas returns the standard OAuth 2.0 error fields in its response: error, error_description, and error_uri.

https://myapp.com/callback-handler?
state=... # Passed value of initial state if it was provided.
&error=... # Error type/constant.
&error_description=... # Error description.
&error_uri=... # Error or event code.

If an unexpected error occurs during the callback URI creation step at the end of the authentication flow, Nylas’ response includes the error_code field instead of error_uri.

https://myapp.com/callback-handler?
&error=internal_error # Error type/constant.
&error_description=Internal+error%2C+contact+administrator # Error description.
&error_code=500 # Code of internal error.