Creating Grants with OAuth and Access token
The Nylas API v3 is in public beta. It might contain bugs, and might change before it is generally available. See the v3 Beta documentation for more information.
API v3 includes new OAuth 2.0 hosted authentication methods. These are similar to the v2 hosted implementation in that the user starts an authentication session, and on successful authentication Nylas gets an authentication token from the provider, which it exchanges for an access token.
In v3 the OAuth access tokens expire hourly, so Nylas also gets a refresh token which is used when re-authenticating. You can use the access token in requests for the user's data, and use the refresh token to re-authenticate when the access token expires.
If you're using hosted authentication and are developing a Single Page App (SPA) or mobile app, use the OAuth 2.0 with PKCE authentication method for extra security. 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 client_secret
. This is optional, but a good idea, for projects that have a backend.
Before you begin
Before you begin, make sure you set up all the required parts for your authentication system:
- If you haven't already, log in to the v3 Dashboard and create a new Nylas application.
If you're using API key authentication, generate an API key in the v3 Dashboard. - Create a provider auth application in the provider's console or app.
See the detailed instructions for Creating a v3 provider auth application in Google or Creating a v3 provider auth application in Azure. - Create a connector in your Nylas application for the provider you want to authenticate with.
- Add your project's
callback_uri
-s (also called a redirect URIs) in the Nylas Dashboard.
These are where Nylas forwards end users after an auth request.
Creating Grants with OAuth and Access Token
Authorization request
The first step of the OAuth process is to collect the information you need to include when starting an authorization request. You usually start the request using either a button or link that the user clicks, which redirects them to api.us.nylas.com/v3/connect/auth
and includes their information. The example below requests two scopes using a Google provider auth application.
/v3/connect/auth?
client_id=<your_nylas_app_client_id>
&redirect_uri=https://myapp.com/callback-handler
&response_type=code
&provider=google
&access_type=offline
&state=sQ6vFQN
The example also uses the access_type=offline
parameter to specify that we do want to receive a refresh token. This is optional.
The rendered URL the user goes to would look something like this:
https://accounts.google.com/o/oauth2/auth/oauthchooseaccount?
client_id=<client_id> // Comes from already created integration
&prompt=consent
&redirect_uri=https://accounts.nylas.com/connect/callback
&response_type=code
&scope=https://www.googleapis.com/auth/gmail.readonly%20profile
&access_type=offline
&state=BA630DED06... // Stored and checked/compared internally by Nylas for security
Provider consent flow
The user goes to the URL Nylas starts a secure authentication session and redirects the user to the provider website.
Each provider displays the consent and approval steps differently, and it's only visible to the end-user. In all cases the user authenticates, then either accepts or declines the scopes your project requested.
Authorization response and grant creation
Next, the auth provider sends the user to the Nylas redirect_uri
(https://api.us.nylas.com/connect/callback
), and includes information about the outcome of the session as query parameters in the URL.
Nylas uses the information in the response to find your Nylas application by client_id
and, if the auth was successful, create an unverified Grant record for the user and record their details.
Get the user's code
Nylas then then uses your Nylas application's callback_uri
(for example, app.example.com/callback-handler
) to forward the user back to your project. The callback URI includes query parameters to indicate to your project if authentication was successful.
The example below shows parameters for a successful authentication. The code
and state
query parameters are standard OAuth 2.0 fields, but Nylas provides some optional fields to give you more context about the authentication.
https://myapp.com/callback-handler?
state=... // Passed value of initial state if it was provided
&code=... // Use this code value for the next step of authentication.
Exchange the code for token
Next, you exchange the code
for an access token. Make a call to the /v3/connect/token
endpoint and include the the code
parameter from the success response.
POST /token HTTP/1.1
Host: /v3/connect/token
Content-Type: application/json
{
"code": "<code>",
"client_id": "<nylas_client_id>",
"client_secret": "<nylas_client_secret>",
"redirect_uri": "<application_redirect_uri>",
"grant_type": "authorization_code"
}
The auth provider responds with an access token, a refresh token (because you asked for one by setting access_type=offline
), and other information. When this completes successfully, Nylas marks the user's Grant as verified and sends you the grant_id
and the email address for the user.
Your application should store the grant_id
, the access_token
, and refresh_token
(for later reauthentication).
{
"access_token": "<access_token>",
"refresh_token": "<refresh_token>",
"scope": "https://www.googleapis.com/auth/gmail.readonly profile",
"token_type": "Bearer",
"id_token": "<id_token>",
"grant_id": "<grant_id>"
}
Refreshing an expired access token (optional)
If you set access_type=offline
in the initial authorization request, Nylas returns a refresh_token
along with the access_token
during the token exchange. When the initial access_token
expires, you can use the refresh_token
to request a new one.
Refresh tokens do not expire unless revoked. If your application is client-side-only, you shouldn't request offline access or need this step.
Make a request to /v3/connect/token
that specifies "grant_type": "refresh_token"
, and includes the refresh token. The auth provider returns a fresh access token.
POST /token HTTP/1.1
Host: /v3/connect/token
Content-Type: application/json
{
"client_id": "<nylas_client_id>",
"client_secret": "<nylas_client_secret>",
"grant_type": "refresh_token",
"refresh_token": "<refresh_token>"
}
{
"access_token": "<access_token>",
"scope": "https://www.googleapis.com/auth/gmail.readonly profile",
"token_type": "Bearer"
}
Creating Grants with OAuth 2.0 and PKCE
The OAuth PKCE (Proof Key for Code Exchange) flow improves security for client-side-only applications, such as browser-based and mobile applications that don't have a backend server.
For security reasons, you should not store an application-wide credentials like the client_secret
in your client-side code. Instead, you want to complete the code exchange flow without using your Nylas application's client_secret
.
Even if your application does have a backend, Nylas still recommends that you use PKCE for extra security.
Make a connect request with a code verifier
The first step for OAuth with PKCE is the same as without PKCE: make a request to /v3/connect/auth
to generate a URL to redirect the end-user. It will look something like the example below.
Note the long code_challenge
string, and code_challenge_method
included in the call.
/connect/auth?
client_id=<your_nylas_app_client_id>
&redirect_uri=https://myapp.com/callback-handler
&response_type=code
&provider=google
&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fgmail.readonly%20profile
&state=sQ6vFQN
&code_challenge=ZTk2YmY2Njg2YTNjMzUxMGU5ZTkyN2RiNzA2OWNiMWNiYTliOTliMDIyZjQ5NDgzYTZjZTMyNzA4MDllNjhhMg
&code_challenge_method=S256
Constructing a code_challenge
This example uses the code verifier string of nylas
, but sets the method to S256
instead of plain
for extra security. If you set the method as plain
the code_challenge
value would be nylas
as a regular string. Since the method is SHA256, you take the code verifier string, hash it using SHA256, convert it to Base64 encoding, and set the code_challenge
param to that value.
This example sets the code verifier string to nylas
, which is e96bf6686a3c3510e9e927db7069cb1cba9b99b022f49483a6ce3270809e68a2
when SHA256 hashed:
SHA256("nylas") => "e96bf6686a3c3510e9e927db7069cb1cba9b99b022f49483a6ce3270809e68a2"
Once you convert it to Base64 encoding (and remove the padding) it becomes: ZTk2YmY2Njg2YTNjMzUxMGU5ZTkyN2RiNzA2OWNiMWNiYTliOTliMDIyZjQ5NDgzYTZjZTMyNzA4MDllNjhhMg
Exchange the token
The rest of the OAuth flow should complete as usual: the user goes to the auth provider, authenticates and accepts or rejects the requested scopes, the provider sends the user back to Nylas with a code, Nylas creates an unverified grant and returns the user back to your project with a code
to exchange for an access token.
Use the code
parameter returned from the example above in a call to the /v3/connect/token
endpoint to exchange tokens, but set the grant_type
to authorization_code
, and include the code_verifier
string.
For readability, this example sets code_verifier
to the original plain text code_verifier
value.
POST /token HTTP/1.1
Host: /v3/connect/token
Content-Type: application/json
{
"code": "<code>",
"client_id": "<nylas_client_id>",
"client_secret": "<nylas_client_secret>",
"redirect_uri": "<application_redirect_uri>",
"grant_type": "authorization_code",
"code_verifier":"nylas"
}
Note: You can't refresh your access token unless you provide your Nylas application's client_secret
. You don't want to store this value for client-side Javascript or mobile applications, so you should use grant_type=authorization_code
instead of grant_type=refresh_token
for these applications.
Handling authentication errors
If authentication fails, Nylas returns the standard OAuth 2.0 error fields in the 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 flow, the response includes an error_code
field instead of an 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 // Error of internal error
Learn more
What's next?
Now that you have a Connector set up and received a Grant, you can:
- Manage your Connectors (previously called "integrations")
- Manage your Grants
- Review the Event codes