Skip to main content
Glama
index.md12.6 kB
Nylas v3 introduces a Hosted OAuth system that completely replaces v2 Hosted Auth. The new Hosted OAuth system is OAuth 2.0-compliant, and offers multiple ways to authorize requests after you complete the authentication process. Nylas also offers PKCE options for use with single page applications (SPAs) and mobile apps. OAuth access tokens expire after one hour, so for most applications, Nylas recommends authenticating end users with OAuth, then using an application API key to authorize requests so you don't need to worry about refresh tokens. You can also choose to receive a refresh token during the authentication process, then use it to get a new access token when an older one expires. To access your end users' data using pure OAuth, pass the access token as the Bearer token in your request's auth header. See [Authentication in Nylas v3](https://developer.nylas.com/docs/v3/auth/) and the [Authentication references](https://developer.nylas.com/docs/api/v3/admin/#tag--Authentication-APIs) for more details. ### New Hosted OAuth endpoints - Revoke an OAuth token: [`POST /v3/connect/revoke`](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connect/revoke) ### Migrated Hosted auth endpoints - Hosted auth - Authenticate user → Hosted OAuth - Authorization request (`GET /oauth/authorize` → [`GET /v3/connect/auth`](https://developer.nylas.com/docs/api/v3/admin/#get-/v3/connect/auth)) - Hosted auth - Send authorization code → Hosted OAuth - Token exchange (`POST /oauth/token` → [`POST /v3/connect/token`](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connect/token)) - Get token information: `POST /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>/token-info` → [`GET /v3/connect/tokeninfo`](https://developer.nylas.com/docs/api/v3/admin/#get-/v3/connect/tokeninfo) ### Deprecated Hosted auth endpoints - Revoke all access tokens: `POST /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>/revoke-all` ### Start a Hosted OAuth authorization request `GET /oauth/authorize` → [`GET /v3/connect/auth`](https://developer.nylas.com/docs/api/v3/admin/#get-/v3/connect/auth) ```Node import 'dotenv/config' import express from 'express' import Nylas from 'nylas' const config = { clientId: process.env.NYLAS_CLIENT_ID, callbackUri: "http://localhost:3000/oauth/exchange", apiKey: process.env.NYLAS_API_KEY, apiUri: process.env.NYLAS_API_URI, } const nylas = new Nylas({ apiKey: config.apiKey, apiUri: config.apiUri, }) const app = express() const port = 3000 // Route to initialize authentication. app.get('/nylas/auth', (req, res) => { const authUrl = nylas.auth.urlForOAuth2({ clientId: config.clientId, provider: 'google', redirectUri: config.redirectUri, loginHint: 'email_to_connect', accessType: 'offline', }) res.redirect(authUrl) }) ``` ```Java get("/nylas/auth", (request, response) -> { List<String> scope = new ArrayList<>(); scope.add("https://www.googleapis.com/auth/calendar"); UrlForAuthenticationConfig config = new UrlForAuthenticationConfig("<NYLAS_CLIENT_ID>", "http://localhost:4567/oauth/exchange", AccessType.ONLINE, AuthProvider.GOOGLE, Prompt.DETECT, scope, true, "sQ6vFQN", "swag@nylas.com"); String url = nylas.auth().urlForOAuth2(config); response.redirect(url); return null; }); get("/oauth/exchange", (request, response) -> { String code = request.queryParams("code"); if(code == null) { response.status(401);} assert code != null; CodeExchangeRequest codeRequest = new CodeExchangeRequest( "http://localhost:4567/oauth/exchange", code, "<NYLAS_CLIENT_ID>", null, null); try{ CodeExchangeResponse codeResponse = nylas.auth().exchangeCodeForToken(codeRequest); request.session().attribute("grant_id", codeResponse.getGrantId()); return "%s".formatted(codeResponse.getGrantId()); }catch(Exception e){ return "%s".formatted(e); } }); ``` ```Python @app.route("/nylas/auth", methods=["GET"]) def login(): if session.get("grant_id") is None: config = URLForAuthenticationConfig({"client_id": "<NYLAS_CLIENT_ID>", "redirect_uri" : "http://localhost:5000/oauth/exchange"}) url = nylas.auth.url_for_oauth2(config) return redirect(url) else: return f'{session["grant_id"]}' @app.route("/oauth/exchange", methods=["GET"]) def authorized(): if session.get("grant_id") is None: code = request.args.get("code") exchangeRequest = CodeExchangeRequest({"redirect_uri": "http://localhost:5000/oauth/exchange", "code": code, "client_id": "<NYLAS_CLIENT_ID>"}) exchange = nylas.auth.exchange_code_for_token(exchangeRequest) session["grant_id"] = exchange.grant_id return redirect(url_for("login")) ``` ```Ruby get '/nylas/auth' do config = { client_id: '<NYLAS_CLIENT_ID>', provider: 'google', redirect_uri: 'http://localhost:4567/oauth/exchange', login_hint: 'swag@nylas.com', access_type: 'offline' } url = nylas.auth.url_for_oauth2(config) redirect url end get '/oauth/exchange' do code = params[:code] status 404 if code.nil? begin response = nylas.auth.exchange_code_for_token({ client_id: '<NYLAS_CLIENT_ID>', redirect_uri: 'http://localhost:4567/oauth/exchange', code: code}) rescue StandardError status 500 else response[:grant_id] response[:email] session[:grant_id] = response[:grant_id] end end ``` ```API curl -X GET "https://api.us.nylas.com/v3/connect/auth?client_id=<CLIENT_ID>&provider=<PROVIDER>&redirect_uri=<REDIRECT_URI>&response_type=<RESPONSE>" ``` ### Get token information `POST /a/<NYLAS_CLIENT_ID>/accounts/<NYLAS_ACCOUNT_ID>/token-info` → [`GET /v3/connect/tokeninfo`](https://developer.nylas.com/docs/api/v3/admin/#get-/v3/connect/tokeninfo) ```Node import 'dotenv/config' import Nylas from 'nylas' // Configure the Nylas SDK with your API key and server URL const NylasConfig = { apiKey: process.env.NYLAS_API_KEY, apiUri: process.env.NYLAS_API_URI, } const nylas = new Nylas(NylasConfig) const revokeToken = async () => { try { const token = process.env.TOKEN const response = await nylas.auth.accessTokenInfo(token) console.log('Token Revoked:', response) } catch (error) { console.error('Error removing connector:', error) } } revokeToken() ``` ```Java import com.nylas.NylasClient; import com.nylas.models.*; public class GetTokenInfo { public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError { NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build(); Response<TokenInfoResponse> token = nylas.auth().idTokenInfo("<ACCESS_TOKEN_ID>"); System.out.println(token); } } ``` ```Python import sys from nylas import Client nylas = Client( '<NYLAS_API_KEY>', '<NYLAS_API_URI>' ) request = nylas.auth.id_token_info( '<ACCESS_TOKEN_ID>', ) print(request) ``` ```Ruby require 'nylas' nylas = Nylas::Client.new( api_key: "<NYLAS_API_KEY>" ) query_params = { id_token: "<ACCESS_TOKEN_ID>" } token_info = nylas.auth.access_token_info(query_params: query_params) puts token_info ``` ```API curl --request GET \ --url 'https://api.us.nylas.com/v3/connect/tokeninfo?id_token=<ACCESS_TOKEN_ID>&access_token=<NYLAS_ACCESS_TOKEN>' \ --header 'Accept: application/json' \ --header 'Authorization: Bearer <NYLAS_API_KEY>' \ ``` ### Exchange tokens `POST /connect/token` → [`POST /v3/connect/token`](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connect/token) ```Node app.get('/oauth/exchange', async (req, res) => { console.log(res.status) const code = req.query.code if (!code) { res.status(400).send('No authorization code returned from Nylas') return } try { const response = await nylas.auth.exchangeCodeForToken({ clientId: config.clientId, redirectUri: config.redirectUri, codeVerifier: 'insert-code-challenge-secret-hash', code }) const { grantId } = response res.status(200) } catch (error) { console.error('Error exchanging code for token:', error) res.status(500).send('Failed to exchange authorization code for token') } }) ``` ```Java get("/oauth/exchange", (request, response) -> { String code = request.queryParams("code"); if(code == null) { response.status(401); } assert code != null; CodeExchangeRequest codeRequest = new CodeExchangeRequest( "http://localhost:4567/oauth/exchange", code, "<NYLAS_CLIENT_ID>", "nylas" ); try { CodeExchangeResponse codeResponse = nylas.auth().exchangeCodeForToken(codeRequest); return "%s".formatted(codeResponse); } catch(Exception e) { return "%s".formatted(e); } }); ``` ```Python import json import os from functools import wraps from io import BytesIO from flask import Flask from nylas import Client nylas = Client( "<NYLAS_CLIENT_ID>", "<NYLAS_API_URI>" ) REDIRECT_CLIENT_URI = 'http://localhost:9000/oauth/exchange' @flask_app.route("/oauth/exchange", methods=["GET"]) def exchange_code_for_token(): code_exchange_response = nylas.auth.exchange_code_for_token( request={ "code": request.args.get('code'), "client_id": "<NYLAS_CLIENT_ID>", "redirect_uri": REDIRECT_CLIENT_URI } ) return { 'email_address': code_exchange_response.email, 'grant_id': code_exchange_response.grant_id } ``` ```Ruby get '/oauth/exchange' do code = params[:code] status 404 if code.nil? begin response = nylas.auth.exchange_code_for_token({ client_id: "<NYLAS_CLIENT_ID>", redirect_uri: 'http://localhost:4567/oauth/exchange', code: code }) rescue StandardError status 500 else grant_id = response[:grant_id] email = response[:email] "Grant_Id: #{grant_id} \n Email: #{email}" end end ``` ```API curl -X POST "https://api.us.nylas.com/v3/connect/token" \ -H "accept: application/json"\ -H "content-type: application/json" \ -d '{"client_id":"<NYLAS_CLIENT_ID>","client_secret":"<NYLAS_API_KEY>","grant_type":"authorization_code","code":"string","redirect_uri":"https://example.com/callback-handler","code_verifier":"nylas"}' \ ``` ### Revoke a specific token You can use the [`POST /v3/connect/revoke` endpoint](https://developer.nylas.com/docs/api/v3/admin/#post-/v3/connect/revoke) to revoke a specific access token. ```Node import 'dotenv/config' import Nylas from 'nylas' // Configure the Nylas SDK with your API key and server URL const NylasConfig = { apiKey: process.env.NYLAS_API_KEY, apiUri: process.env.NYLAS_API_URI, } const nylas = new Nylas(NylasConfig) const revokeToken = async () => { try { const token = process.env.TOKEN const response = await nylas.auth.revoke(token) console.log('Token Revoked:', response) } catch (error) { console.error('Error removing connector:', error) } } revokeToken() ``` ```Java package org.example; import com.nylas.NylasClient; import com.nylas.models.TokenParams; public class Revoke_Auth_Token { public static void main(String[] args) { Dotenv dotenv = Dotenv.load(); NylasClient nylas = new NylasClient.Builder("<V3_TOKEN_API>").build(); TokenParams token = new TokenParams("<NYLAS_AUTH_TOKEN>"); try{ boolean token_status = nylas.auth().revoke(token); if(token_status){ System.out.println("The token was successfully removed"); }else{ System.out.println("The token cannot be removed"); } }catch (Exception e){ System.out.println("Invalid token cannot be removed"); } } } ``` ```Python from dotenv import load_dotenv import os from nylas import Client load_dotenv() nylas = Client( os.environ.get('NYLAS_API_KEY') ) try: token_state = nylas.auth.revoke("") if token_state: print("The token was successfully removed") else: print("The token cannot be removed") except: print("Invalid token cannot be removed") ``` ```Ruby require 'nylas' nylas = Nylas::Client.new( api_key: "<ACCESS_TOKEN_ID>" ) token_state = nylas.auth.revoke("<NYLAS_AUTH_TOKEN>") if(token_state) puts "The token was successfully removed" else puts "Invalid token cannot be removed" end ``` ```API curl -X POST "https://api.us.nylas.com/v3/connect/revoke?token=<NYLAS_AUTH_TOKEN>" \ -H "accept: application/json" \ ```

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nylas-samples/nylas-api-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server