Regarding auth flow of email and scheduler

Suppose i have authenticated my email through nylas authentication
so is there any way to authenticate nylas meeting scheduler using same email (instead of doing multiple api call for auth)
for example :

      const schedulerEditor = document.querySelector("nylas-scheduler-editor");
      schedulerEditor.schedulerPreviewLink = `${window.location.origin}/?config_id={config.id}`; // Replace with the URL of the page where you want to display the scheduler
      schedulerEditor.configurationId = "config.id"; // Replace with the configuration ID you want to edit
      schedulerEditor.nylasSessionsConfig = {
        clientId: "91d00c.............................", // Replace with your Nylas client ID from nylas dashboard
        redirectUri: `${window.location.origin}/scheduler-editor`, // Replace with the redirect URI you set in the Nylas dashboard
        domain: "https://api.eu.nylas.com/v3", // or 'https://api.us.nylas.com/v3' for US data center
        hosted: true,
        accessType: "offline", 
      };

is there any parameter we can pass which will help us to authenticate the nylas meeting scheduler for the same email (to bypass the auth flow of nylas meeting scheduler)
and get this page directly :

Hello @dhruv Let me ask the Scheduler team and will get back to you :slight_smile:

@dhruv I have the same schedulerEditor script that you have to render it, but I’m getting issues on my server regarding the code verifier and code challenge. Could you provide your code regarding that to get your user logged into the scheduler successfully?

The code that I’m getting to my server from the scheduler UI component tells me that its invalid

@sboynton Have you checked the Schedule Quickstart Guide? Scheduler Quickstart guide: set up Scheduler | Nylas Docs

@dhruv The scheduler editor component requires the authed user’s access token to make API requests. If you already used nylas authentication, you can use custom auth method. Here is a sample app example: scheduler-v3-code-samples/react/scheduler-editor-custom-auth at main · nylas-samples/scheduler-v3-code-samples · GitHub

You can use the access token from authing in email to set up the scheduler editor (already logged in)

@Blag it will work for html/vanila js also right ?
but when i tried to bypass it through that it send me this error

here is my code for ref:

    <div class="grid h-full place-items-center">
      <!-- Add the Nylas Scheduler Editor component -->
      <nylas-scheduler-editor 
        />
      </div>

    <!-- Configure the Nylas Scheduler Editor component -->
    <script type="module">
              class CustomIdentityRequestWrapper {
            constructor(accessToken) {
                this.accessToken = accessToken;
            }

            async request(args) {
                try {
                    console.log('args', args);
                    console.log('args method',args.method)
                    const response = await fetch(`https://api.eu.nylas.com/v3/grants/me/${args.path}`, {
                      mode:"no-cors",
                        method: args.method,
                        body: JSON.stringify(args.body),
                        headers: {
                          ...args.headers,
                          'Authorization': `Bearer ${this.accessToken}`,
                          'Content-Type': 'application/json',
                          'Access-Control-Allow-Origin': '*',
                        },
                    });

                    if (!response.ok) {
                        console.error(`Error: ${response.status} ${response.statusText}`);
                        return { error: `Error: ${response.status} ${response.statusText}` };
                    }

                    const data = await response.json();
                    return [data, null];
                } catch (error) {
                    console.error('Fetch error:', error);
                    return { error: "Error" };
                }
            }

            async currentUser() {
                return {
                    id: 'eyJhbG................................',
                    email: 'dhruv...............',
                    name: 'dhruv',
                    provider: 'google',
                };
            }

            async setDefaultAuthArgs(authArgs) {
                return authArgs;
            }

            async authenticationUrl() {
                return 'http://localhost:3000/scheduler-editor';
            }
        }
        // const schedulerEditor = document.querySelector("nylas-scheduler-editor");
        // schedulerEditor.schedulerPreviewLink = `${window.location.origin}/?config_id={config.id}`;

        const accessToken = 'BI6A3fKRLxJNEzHXXixvMExqrYRMSEKKHhSpvbWoiJytFm07bvCObTc2r1Tc2305_kpL_9_9.......................................................................'
        // Create an instance of the CustomIdentityRequestWrapper class defined above
        const schedulerEditor = document.querySelector("nylas-scheduler-editor");
        const nylasApiRequest = new CustomIdentityRequestWrapper(accessToken)
        schedulerEditor.nylasApiRequest = nylasApiRequest


      schedulerEditor.schedulerPreviewLink = `${window.location.origin}/?config_id={config.id}`; // Replace with the URL of the page where you want to display the scheduler
      schedulerEditor.configurationId = "config.id"; // Replace with the configuration ID you want to edit
      // schedulerEditor.nylasSessionsConfig = {
      //   clientId: "91d00.......................................", // Replace with your Nylas client ID from nylas dashboard
      //   redirectUri: `${window.location.origin}/scheduler-editor`, // Replace with the redirect URI you set in the Nylas dashboard
      //   domain: "https://api.eu.nylas.com/v3", // or 'https://api.us.nylas.com/v3' for US data center
      //   hosted: true,
      //   accessType: "offline", 
      // };
      
      schedulerEditor.defaultSchedulerConfigState = {
        selectedConfiguration: {
          requires_session_auth: false, // creates public configuration which does not require session tokens
          scheduler: {
            // organizer_confirmation_url: `${window.location.origin}/confirmation/:booking_ref`,
            cancellation_url: `${window.location.origin}/cancel/:booking_ref`,
            rescheduling_url: `${window.location.origin}/reschedule/:booking_ref`,
            // confirmation_redirect_url: `${window.location.origin}/booking-confirmed`
          },
        },
      };

in above code i have used hard coded values as of now for testing auth but it didn’t worked out do i missing something or is there any mistake from my side ??

ok so now i have solved this i was using wrong sub
my next question is the accesstoken will expire in some hours or mins
so we need to refresh it every time with the refresh token (which we are storing already)

We already store the refresh token, and I need to implement a solution in HTML and Vanilla JavaScript to automatically refresh the access token whenever it expires.

Could you please help me with a code example that demonstrates how to:

  1. Use the stored refresh token to obtain a new access token.
  2. Apply this new access token to bypass the login request.

here is my current code

       <script type="module">

     import { CustomIdentityRequestWrapper } from './custom.js';

        const schedulerEditor = document.querySelector("nylas-scheduler-editor");


        const accessToken = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
        const domain ='https://api.eu.nylas.com/v3'; // or 'https://api.us.nylas.com/v3' for EU data center
        const nylasApiRequest = new CustomIdentityRequestWrapper(accessToken, domain);
        schedulerEditor.nylasApiRequest = nylasApiRequest
        schedulerEditor.schedulerPreviewLink = `${window.location.origin}/?config_id={config.id}`; // Replace with the URL of the page where you want to display the scheduler

        schedulerEditor.defaultSchedulerConfigState = {
        selectedConfiguration: {
          requires_session_auth: false, // creates public configuration which does not require session tokens
          scheduler: {
            // organizer_confirmation_url: `${window.location.origin}/confirmation/:booking_ref`,
            cancellation_url: `${window.location.origin}/cancel/:booking_ref`,
            rescheduling_url: `${window.location.origin}/reschedule/:booking_ref`,
            // confirmation_redirect_url: `${window.location.origin}/booking-confirmed`
          },
        },
      };
    </script>

here is custom.js file code

export class CustomIdentityRequestWrapper {
    accessToken;
    domain;
  
    constructor(accessToken, domain) {
      // Initialize the class
      this.accessToken = accessToken;
      this.domain = domain;
    }
    async request(args) {
      try {
        const response = await fetch(`${this.domain}/grants/me/${args.path}`, {
          method: args.method,
          body: JSON.stringify(args.body),
          headers: {
            ...args.headers,
            'Authorization': `Bearer ${this.accessToken}`,
            'Content-Type': 'application/json',
          },
        });
  
        // Check if the response is not okay (e.g., 404, 500)
        if (!response.ok) {
          console.error(`Error: ${response.status} ${response.statusText}`);
          return { error: `Error: ${response.status} ${response.statusText}` };
        }
  
        // Parse the response
        const data = await response.json();
        return [data, null];
      } catch (error) {
        console.error('Fetch error:', error);
        return { error: "Error" };
      }
    }
  
    /**
     * This method returns the current user's information.
     */
  
    async currentUser() {
      // IMPLEMENT: Get the logged in user's ID token and return the user information
      return {
        id: '7dXXXXXXXXXXXXXXXXXX',
        email: 'dhruv.....................',
        name: 'dhruv',
        provider: 'google',
      };
    }
  
    /**
     * This method sets the default authentication arguments to use when authenticating the user.
     */
    async setDefaultAuthArgs(authArgs) {
      // Set the default authentication arguments
      return authArgs;
    }
  
    /**
     * This method returns the URL to redirect the user to for authentication.
     */
    async authenticationUrl() {
      // IMPLEMENT: Return the URL to redirect the user to for authentication
      return 'http://localhost:3000/scheduler-editor';
    }
  }

and also confirm that the sub used here in above code is same everytime right it doesn’t change (which we get from “https://api.eu.nylas.com/v3/connect/tokeninfo?id_token=my_id_token” after succesful auth)

Hello @dhruv I’m not an Scheduler expert, so let me connect you with @ram who might be able to help you out with this :slight_smile:

@dhruv - taking a look at this, so the item to clarify is:

How can I refresh the access token using the refresh token on the frontend?

I need to dig into this further, as we do have the ability to refresh the access token via API taking a look at our docs.

@ram I currently need to retrieve only the name specified in the email. Is there a way to get this information using just the grant ID and API key, without needing the access token?

Here’s my current flow, which doesn’t require refreshing the token every hour to get calendar information:

export class CustomIdentityRequestWrapper {
    accessToken;
    domain;

    constructor(API_KEY, domain) {
        this.API_KEY = API_KEY;
        this.domain = domain;
    }

    async request(args) {
        try {
            const user = await this.currentUser();
            const response = await fetch(`${this.domain}/grants/${user.id}/${args.path}`, {
                method: args.method,
                body: JSON.stringify(args.body),
                headers: {
                    ...args.headers,
                    'Authorization': `Bearer ${this.API_KEY}`,
                    'Content-Type': 'application/json',
                },
            });

            if (!response.ok) {
                console.error(`Error: ${response.status} ${response.statusText}`);
                return { error: `Error: ${response.status} ${response.statusText}` };
            }

            const data = await response.json();
            return [data, null];
        } catch (error) {
            console.error('Fetch error:', error);
            return { error: "Error" };
        }
    }

    async currentUser() {
        return {
            id: '7..........................',
            email: 'dhruv...........',
            provider: 'google',
            name: ''
        };
    }

    async setDefaultAuthArgs(authArgs) {
        console.log(authArgs);
        return authArgs;
    }

    async authenticationUrl() {
        return 'http://localhost:3000/scheduler-editor';
    }
}

I’ve modified the scheduler editor code to use an API key instead of an access token. Now, the current user info can be retrieved through a tokeninfo request, which requires either an access token or an ID token obtained after the connect token request. However, the ID token also expires after some time. Is there any way to get user data like grant ID, name, email, and provider without handling the refresh token?
becuase name is important thing to shown on scheduler-editor component
ref-api : Nylas v3 Administration API docs | Nylas Docs

So two inquiries:

  1. Is there a way to get this information using just the grant ID and API key, without needing the access token?
  2. Is there any way to get user data like grant ID, name, email, and provider without handling the refresh token?

For 1 & 2, our API by default works using grant ID, here is our API reference.

One thing I recommend to keep in mind is that its not secure to expose the API Key in your frontend, so you will need a backend API to ensure the API Key is key secure as an environment variable for example.

@ram @Blag one more question here can i use this component with vue2 ?
if yes then how because i only see the support for react js

@ram @Blag any update here?
it would be very helpful if i get any

@dhruv did you ever receive a reply here? we are dealing with a similar issue and have made zero progress over the last two days.

@nmchilders @dhruv I asked a member of the scheduler team to jump in an help…also I added this to the Scheduler tag :wink:

We don’t support Vue out of the box, but have you tried leveraging the web version of our components by following something like this? Vue and Web Components | Vue.js

We offer both web components, as well as React.

@ram @antoine @Blag
i have solved the issue by using node modules of web components and importing it directly to the vue component

<template>
            <div class="grid h-full place-items-center">
               <nylas-scheduler-editor></nylas-scheduler-editor>
           </div>
</template>
<script>
import '../../node_modules/@nylas/web-elements/dist/nylas-web-elements/nylas-web-elements.esm.js';
import { CustomIdentityRequestWrapper } from '../nylas-scheduler/nylas-scheduler-auth.js';
    data() {
        return {
            API_KEY:'Get from env',
            domain: 'Get from env',
        }
    },
    async mounted() {
            const nylasApiRequest = new CustomIdentityRequestWrapper(this.API_KEY,this.domain);
            const schedulerEditor = document.querySelector("nylas-scheduler-editor");
            schedulerEditor.nylasApiRequest = nylasApiRequest;
            schedulerEditor.schedulerPreviewLink = `${window.location.origin}/?config_id={config.id}`;
            schedulerEditor.defaultSchedulerConfigState = {
            selectedConfiguration: {
                requires_session_auth: false, // Creates a public configuration which doesn't require a session
                scheduler: { // The callback URLs to be set in email notifications
                rescheduling_url: `${window.location.origin}/reschedule/:booking_ref`, // The URL of the email notification includes the booking reference
                cancellation_url: `${window.location.origin}/cancel/:booking_ref`
                }
            }
            };
    }

</script>

this is how it will work guys bypassing the auth flow and using vue js component to render it in your vue file

2 Likes

@dhruv so you were able to bypass the scheduler editor login page? We have your code above, with the obvious exception of our current user, but we still remain on the login page…

hi @sboynton what kind of issue you are facing and i am able to bypass it perfectly you just need correct api key of v3 grant id of v3 ,provider and email ,
explain your problem in detail so i could help you if i can

@dhruv thanks. We were actually able to bypass the login successfully with the help of your code shared above. We appreciate it a lot. :+1: