title: How do I get refresh token from microsoft graph
body: <p>I am trying to create an outlook email automation tool. In order for it to do things such as send a email in a folder for the user at a given time. Microsoft allows third party apis to trigger microsoft's apis on behalf of a user through auth2. I am able to retrieve the necessary access token, but I need a refresh token in order to call code on behalf of the user without forcing him to login every hour. </p>
  
  <p>I am currently using the microsoft's javascript authentication library in order to receive tokens. From what I have read, it seems refresh token must have the offline scope in the token request. With code below, I am able to a response with the access token, but I am still unable to get the access token.</p>
  
  <p><a href="https://i.stack.imgur.com/AMgNz.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/AMgNz.png" alt="enter image description here"></a></p>
  
  <pre><code>const tokenRequest = {
    scopes: [
      "https://graph.microsoft.com/Mail.ReadWrite",
      "https://graph.microsoft.com/mail.send",
      "https://graph.microsoft.com/offline_access"
    ]
  };
  
  const hostname = "http://localhost:5000";
  
  const backendServerAdress = "http://localhost:8050";
  var xhr = new XMLHttpRequest();
  xhr.open("POST", backendServerAdress, true);
  xhr.setRequestHeader("Content-Type", "application/json");
  
  const msalConfig = {
    auth: {
      clientId: "something",
      redirectUri: hostname + "/homepage/index.html"
    }
  };
  
  var loginRequest = {
    scopes: ["Mail.ReadWrite", "mail.send", "offline_access"] // optional Array&lt;string&gt;
  };
  
  const TOKEN_ID = "token_id";
  const msalInstance = new Msal.UserAgentApplication(msalConfig);
  
  msalInstance.handleRedirectCallback((error, response) =&gt; {
    console.log("redirect callback done");
  });
  
  async function redirectToDashboard() {
    console.log("redirect to dashboard");
    // var response = await requestTokenSilent();
    var response;
    if (!response || !response.status == 200) {
      response = await requestTokenPopup();
    }
  
    if (response &amp;&amp; response.status == 200) {
      xhr.send(
        JSON.stringify({
          firstname: "something",
          lastname: "something",
          accessToken: "something"
        })
      );
      location.href = hostname;
    } else {
      console.log("Unable to acquire token");
    }
  }
  
  function redirectLogin() {
    console.log("redirect called");
    if (!msalInstance.getAccount()) {
      return msalInstance
        .loginRedirect(loginRequest)
        .then(response =&gt; {
          console.log(response);
          return response;
        })
        .catch(err =&gt; {
          console.log("Authentication error: ", err);
        });
    }
  
    if (msalInstance.getAccount()) {
      redirectToDashboard();
    }
  }
  
  async function requestTokenSilent() {
    console.log("requestTokenSilent");
    if (msalInstance.getAccount()) {
      return msalInstance
        .acquireTokenSilent(tokenRequest)
        .then(response =&gt; {
          localStorage.setItem(TOKEN_ID, response.accessToken);
          console.log("response reached: ", response);
          resolve(response);
        })
        .catch(err =&gt; {
          if (err.name === "InteractionRequiredAuthError") {
            alert("Authentication failed try again");
          }
        });
    }
  }
  
  async function requestTokenPopup() {
    console.log("requestTokenPopup");
    if (msalInstance.getAccount()) {
      return msalInstance
        .acquireTokenPopup(tokenRequest)
        .then(response =&gt; {
          localStorage.setItem(TOKEN_ID, response.accessToken);
          return response;
        })
        .catch(err =&gt; {
          console.log(err);
          if (err.name === "InteractionRequiredAuthError") {
            alert("Authentication failed try again");
          }
        });
    }
  }
  </code></pre>