ErrorAccessDenied удалить вложения с графиком Microsoft - PullRequest
0 голосов
/ 06 декабря 2018

Я пытаюсь удалить вложения с помощью Microsoft Graph.У меня есть следующая функция:

getAccessToken(function(accessToken) {
  if (accessToken) {
    // Create a Graph client
    var client = MicrosoftGraph.Client.init({
      authProvider: done => {
        // Just return the token
        done(null, accessToken);
      }
    });
    console.log(files);
    files.forEach(function(file) {
      client
        .api(
          "/me/messages/" +
            file.msg +
            "/attachments/" +
            file.attachment
        )
        .delete((err, res) => {
          if (err) {
            console.log(err);
            return;
          } else {
            console.log(res);
            $("#attachment_" + file.list).remove();
          }
        });
    });
  } else {
    var error = {
      responseText: "Could not retrieve access token"
    };
  }
});

// OAUTH FUNCTIONS =============================
function buildAuthUrl() {
  // Generate random values for state and nonce
  sessionStorage.authState = guid();
  sessionStorage.authNonce = guid();

  var authParams = {
    response_type: "id_token token",
    client_id: appId,
    redirect_uri: redirectUri,
    scope: scopes,
    state: sessionStorage.authState,
    nonce: sessionStorage.authNonce,
    response_mode: "fragment"
  };

  return authEndpoint + $.param(authParams);
}

function handleTokenResponse(hash) {
  // If this was a silent request remove the iframe
  $("#auth-iframe").remove();
  // clear tokens
  sessionStorage.removeItem("accessToken");
  sessionStorage.removeItem("idToken");

  var tokenresponse = parseHashParams(hash);

  // Check that state is what we sent in sign in request
  if (tokenresponse.state != sessionStorage.authState) {
    sessionStorage.removeItem("authState");
    sessionStorage.removeItem("authNonce");
    // Report error
    window.location.hash =
      "#error=Invalid+state&error_description=The+state+in+the+authorization+response+did+not+match+the+expected+value.+Please+try+signing+in+again.";
    return;
  }

  sessionStorage.authState = "";
  sessionStorage.accessToken = tokenresponse.access_token;

  // Get the number of seconds the token is valid for,
  // Subract 5 minutes (300 sec) to account for differences in clock settings
  // Convert to milliseconds
  var expiresin =
    (parseInt(tokenresponse.expires_in) - 300) * 1000;
  var now = new Date();
  var expireDate = new Date(now.getTime() + expiresin);
  sessionStorage.tokenExpires = expireDate.getTime();

  sessionStorage.idToken = tokenresponse.id_token;

  validateIdToken(function(isValid) {
    if (isValid) {
      // Re-render token to handle refresh
      renderTokens();

      // Redirect to home page
      window.location.hash = "#";
    } else {
      clearUserState();
      // Report error
      window.location.hash =
        "#error=Invalid+ID+token&error_description=ID+token+failed+validation,+please+try+signing+in+again.";
    }
  });
}

function validateIdToken(callback) {
  // Per Azure docs (and OpenID spec), we MUST validate
  // the ID token before using it. However, full validation
  // of the signature currently requires a server-side component
  // to fetch the public signing keys from Azure. This sample will
  // skip that part (technically violating the OpenID spec) and do
  // minimal validation

  if (
    null == sessionStorage.idToken ||
    sessionStorage.idToken.length <= 0
  ) {
    callback(false);
  }

  // JWT is in three parts seperated by '.'
  var tokenParts = sessionStorage.idToken.split(".");
  if (tokenParts.length != 3) {
    callback(false);
  }

  // Parse the token parts
  var header = KJUR.jws.JWS.readSafeJSONString(
    b64utoutf8(tokenParts[0])
  );
  var payload = KJUR.jws.JWS.readSafeJSONString(
    b64utoutf8(tokenParts[1])
  );

  // Check the nonce
  if (payload.nonce != sessionStorage.authNonce) {
    sessionStorage.authNonce = "";
    callback(false);
  }

  sessionStorage.authNonce = "";

  // Check the audience
  if (payload.aud != appId) {
    callback(false);
  }

  // Check the issuer
  // Should be https://login.microsoftonline.com/{tenantid}/v2.0
  if (
    payload.iss !==
    "https://login.microsoftonline.com/" +
      payload.tid +
      "/v2.0"
  ) {
    callback(false);
  }

  // Check the valid dates
  var now = new Date();
  // To allow for slight inconsistencies in system clocks, adjust by 5 minutes
  var notBefore = new Date((payload.nbf - 300) * 1000);
  var expires = new Date((payload.exp + 300) * 1000);
  if (now < notBefore || now > expires) {
    callback(false);
  }

  // Now that we've passed our checks, save the bits of data
  // we need from the token.

  sessionStorage.userDisplayName = payload.name;
  sessionStorage.userSigninName =
    payload.preferred_username;

  // Per the docs at:
  // https://azure.microsoft.com/en-us/documentation/articles/active-directory-v2-protocols-implicit/#send-the-sign-in-request
  // Check if this is a consumer account so we can set domain_hint properly
  sessionStorage.userDomainType =
    payload.tid === "9188040d-6c67-4c5b-b112-36a304b66dad"
      ? "consumers"
      : "organizations";

  callback(true);
}

function makeSilentTokenRequest(callback) {
  // Build up a hidden iframe
  var iframe = $("<iframe/>");
  iframe.attr("id", "auth-iframe");
  iframe.attr("name", "auth-iframe");
  iframe.appendTo("body");
  iframe.hide();

  iframe.load(function() {
    callback(sessionStorage.accessToken);
  });

  iframe.attr(
    "src",
    buildAuthUrl() +
      "&prompt=none&domain_hint=" +
      sessionStorage.userDomainType +
      "&login_hint=" +
      sessionStorage.userSigninName
  );
}

// Helper method to validate token and refresh
// if needed
function getAccessToken(callback) {
  var now = new Date().getTime();
  var isExpired =
    now > parseInt(sessionStorage.tokenExpires);
  // Do we have a token already?
  if (sessionStorage.accessToken && !isExpired) {
    // Just return what we have
    if (callback) {
      callback(sessionStorage.accessToken);
    }
  } else {
    // Attempt to do a hidden iframe request
    makeSilentTokenRequest(callback);
  }
}

токен доступа

eyJ0eXAiOiJKV1QiLCJub25jZSI6IkFRQUJBQUFBQUFDNXVuYTBFVUZnVElGOEVsYXh0V2pUUEF3aGltT2hjOXAxUkdiSnVjTDcyd0pjSFdTd1lpUXNFdDdqXzgxRVd6UXhvaWRaWnVXU2d5VS1HWXRqNFFNa3JjMUNpeFFTWElNRVpYQWhSUlJXZENBQSIsImFsZyI6IlJTMjU2IiwieDV0Ijoid1VMbVlmc3FkUXVXdFZfLWh4VnRESkpaTTRRIiwia2lkIjoid1VMbVlmc3FkUXVXdFZfLWh4VnRESkpaTTRRIn0.eyJhdWQiOiJodHRwczovL2dyYXBoLm1pY3Jvc29mdC5jb20iLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9iNmFjNDlmNy1iMTNlLTQyOWMtYmI4NS0wODQ4OTY5NTA2OTkvIiwiaWF0IjoxNTQ0MTkyODUxLCJuYmYiOjE1NDQxOTI4NTEsImV4cCI6MTU0NDE5Njc1MSwiYWNjdCI6MCwiYWNyIjoiMSIsImFpbyI6IjQyUmdZT0JiMFhGQjBNSHFySW5FbVU5aEc4T1p6MTllOHpIRld1S0sxbldqQzVrOFAvd0IiLCJhbXIiOlsicHdkIl0sImFwcF9kaXNwbGF5bmFtZSI6IkZvcm1wcmVzcyBjbGVhciBhdHRhY2htZW50cyIsImFwcGlkIjoiNTY0NzBlMjctZTAxNC00Zjg4LWEzY2QtZjQxODNlZjBhMjkxIiwiYXBwaWRhY3IiOiIwIiwiZmFtaWx5X25hbWUiOiJLYXJsc3NvbiIsImdpdmVuX25hbWUiOiJDaHJpc3RvcGhlciIsImlwYWRkciI6IjE1NS40LjE5NC4xMzQiLCJuYW1lIjoiQ2hyaXN0b3BoZXIgS2FybHNzb24iLCJvaWQiOiI5Y2JlMjBlYy1iMTk0LTRjZTYtOTU0Zi1hMTgzNTlmNGYzYTAiLCJwbGF0ZiI6IjMiLCJwdWlkIjoiMTAwMzAwMDA5QzI0MTI0NyIsInNjcCI6Ik1haWwuUmVhZCBvcGVuaWQgcHJvZmlsZSBVc2VyLlJlYWQgZW1haWwiLCJzaWduaW5fc3RhdGUiOlsia21zaSJdLCJzdWIiOiI5NVhONDhua08zbDJIeGYyTmdVTFo2YjA3WWpVV0lHOTRUQjA2bVNRUk9vIiwidGlkIjoiYjZhYzQ5ZjctYjEzZS00MjljLWJiODUtMDg0ODk2OTUwNjk5IiwidW5pcXVlX25hbWUiOiJjaHJpc3RvcGhlckBpdHBhcnRuZXJhYi5zZSIsInVwbiI6ImNocmlzdG9waGVyQGl0cGFydG5lcmFiLnNlIiwidXRpIjoiVmJGRW9EQ0RqMEMxVkFfSTNITWRBQSIsInZlciI6IjEuMCIsInhtc19zdCI6eyJzdWIiOiJka1FicDc3c2Y5ZmJlSnVYM1NqUml3aVhPa1FYOV9MZTF6MHp4X3Q4SU5BIn0sInhtc190Y2R0IjoxNDc4ODg0NzA1fQ.YQlKVdhXQcVwkcmbpY9Wx6ENro2DL7yH1rWwwkDZLD1inUrfbLRVb67lWKzgK9GnYP81d58Fp_2CZBw8C2E4X1eo02vog6_Qga9kVb8GF2-Ue0VP0KUv8EtRpEty_DBK7Re3iOkJR9yFSPQgf11Gf15l5O2mcEifrwny5nkRvab4_ssRt6hNf53V99uTFJ3_yKycGHPTobVbyQT5ZyDKxXRwoZVprFU70qrHGcBgo5emO8HbziYCUiQ9vGMpmtz61tE0U-c0E20FPC82i3zgLfMgmhNqmljZOpkOe85PFrxoep7fYkpZpWowCozugDW0E2A3SxBLZ_JHpci2R4irxg

files является глобальной переменной, которая содержит массив объектов, данные, кажется,быть правильным.

Вот пример ответа, который я получаю при запуске кода:

{
    statusCode: 403, 
    code: "ErrorAccessDenied", 
    message: "Access is denied. Check credentials and try again.", 
    requestId:  "0739c0d9-38f2-45f7-a57d-c25dfbf92f75", 
    date: Fri Dec 07 2018 14:54:32 GMT+0100 (centraleuropeisk normaltid), …
} 

URL API

me/messages/{id}/attachments/{id}

При https://apps.dev.microsoft.com/#/application/ У меня естьучитывая доступ к приложению Mail.ReadWrite и Mail.ReadWrite.Shared, хотя он упоминает только чтение при регистрации в приложении, что я нахожу странным.

Похоже, мое приложение не имеет правильного доступа.Есть ли что-то еще, что я должен сделать, что я пропустил?Мой клиентский запрос неверен?

1 Ответ

0 голосов
/ 07 декабря 2018

Вы должны снова проверить свои возможности.Предоставленный вами токен доступа включает в себя только следующие области действия: Mail.Read openid profile User.Read email.

Предоставленный вами пример кода ссылается на переменную scopes, но неясно, что вы установили:

  var authParams = {
    response_type: "id_token token",
    client_id: appId,
    redirect_uri: redirectUri,
    scope: scopes,
    state: sessionStorage.authState,
    nonce: sessionStorage.authNonce,
    response_mode: "fragment"
  };

Значение этого свойства должно быть чем-то вроде openid profile email Mail.ReadWrite Mail.ReadWrite.Shared.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...