使用通行证库访问Microsoft Graph API时,CompactToken解析失败,错误代码:80049217

时间:2019-11-03 12:06:44

标签: node.js microsoft-graph auth0 adal microsoft-graph-calendar

我正在使用'passport-azure-ad-oauth2' npm模块来获取访问令牌,然后可以将其传递给MS Graph API。

passport.use(new AzureAdOAuth2Strategy({
    clientID: process.env.OUTLOOK_CLIENT_ID,
    clientSecret: process.env.OUTLOOK_SECRET,
    callbackURL: '/auth/outlook/callback',
},
    function (accesstoken: any, refresh_token: any, params: any, profile, done) {
        logger.info('Completed azure sign in for : ' + JSON.stringify(profile));
        logger.info('Parameters returned: ' + JSON.stringify(params));
        const decodedIdToken: any = jwt.decode(params.id_token);
        logger.info('Outlook Access Token:' + accesstoken);
        logger.info('Decoded Token: ' + JSON.stringify(decodedIdToken, null, 2));

        process.env['OUTLOOK_ACCESS_TOKEN'] = accesstoken;
        // add new user with token or update user's token here, in the database

    }));

然后,使用'@ microsoft / microsoft-graph-client' npm模块,从Graph API获取日历事件,如下所示:

try {
    const client = this.getAuthenticatedClient(process.env['OUTLOOK_ACCESS_TOKEN']);
    const resultSet = await client
                .api('users/' + userId + '/calendar/events')
                .select('subject,organizer,start,end')
                .get();
    logger.info(JSON.stringify(resultSet, null, 2));
} catch (err) {
    logger.error(err);
}

getAuthenticatedClient(accessToken) {
    logger.info('Using accestoken for initialising Graph Client: ' + accessToken);
    const client = Client.init({
        // Use the provided access token to authenticate requests
        authProvider: (done) => {
            done(null, accessToken);
        }
    });

    return client;
}

但是,使用成功登录时提供的accessToken,出现以下错误: CompactToken解析失败,错误代码:80049217

任何建议我在做什么不正确?

更新: 这些是我正在使用的范围:“ openid,profile,offline_access,calendars.read”

更新: 稍作修改后,现在出现以下错误:无效的受众。

在解码在jwt.ms处接收到的令牌时,这是'aud'的值:“ 00000002-0000-0000-c000-000000000000”

passport-azure-ad-oauth2 是为MS Graph API检索令牌的错误库吗?

6 个答案:

答案 0 :(得分:1)

根据我的测试,我们可以使用以下代码获取访问令牌。 app.js

require('dotenv').config();
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var session = require('express-session');
var flash = require('connect-flash');
var passport = require('passport');
var OIDCStrategy = require('passport-azure-ad').OIDCStrategy;


// Configure simple-oauth2
const oauth2 = require('simple-oauth2').create({
  client: {
    id: process.env.OAUTH_APP_ID,
    secret: process.env.OAUTH_APP_PASSWORD
  },
  auth: {
    tokenHost: process.env.OAUTH_AUTHORITY,
    authorizePath: process.env.OAUTH_AUTHORIZE_ENDPOINT,
    tokenPath: process.env.OAUTH_TOKEN_ENDPOINT
  }
});
var users = {};

// Passport calls serializeUser and deserializeUser to
// manage users
passport.serializeUser(function(user, done) {
  // Use the OID property of the user as a key
  users[user.profile.oid] = user;
  done (null, user.profile.oid);
});

passport.deserializeUser(function(id, done) {
  done(null, users[id]);
});

// Callback function called once the sign-in is complete
// and an access token has been obtained
async function signInComplete(iss, sub, profile, accessToken, refreshToken, params, done) {
  if (!profile.oid) {
    return done(new Error("No OID found in user profile."), null);
  }


  // Create a simple-oauth2 token from raw tokens
  let oauthToken = oauth2.accessToken.create(params);

  // Save the profile and tokens in user storage
  users[profile.oid] = { profile, oauthToken };
  return done(null, users[profile.oid]);
}

// Configure OIDC strategy
passport.use(new OIDCStrategy(
  {
    identityMetadata: `${process.env.OAUTH_AUTHORITY}${process.env.OAUTH_ID_METADATA}`,
    clientID: process.env.OAUTH_APP_ID,
    responseType: 'code id_token',
    responseMode: 'form_post',
    redirectUrl: process.env.OAUTH_REDIRECT_URI,
    allowHttpForRedirectUrl: true,
    clientSecret: process.env.OAUTH_APP_PASSWORD,
    validateIssuer: false,
    passReqToCallback: false,
    scope: process.env.OAUTH_SCOPES.split(' ')
  },
  signInComplete
));

有关更多详细信息,请参阅documentsample

答案 1 :(得分:1)

enter image description here

通过 postman 调用图形 API 时出现此错误

答案 2 :(得分:0)

结果是有一个用于Microsoft-graph api的护照库: passport-microsoft

我从该软件包中使用了MicrosoftStrategy,一切似乎都工作正常。

passport-azure-ad-oauth2 用于旧的Azure AD Graph API,而 passport-microsoft 用于新的Microsoft Graph API

答案 3 :(得分:0)

我有同样的问题。就我而言,授权标头的格式不正确:

Bearereyxxxx

而不是

轴承eyxxxx

我是该项目的新手,但似乎以前曾经被Azure接受。

答案 4 :(得分:0)

我解决了这个问题,只通过 authenticationProvider 中的 accessToken 而不是旧的“Bearer”+ 令牌:例如:

TokenCredential tokenCredential = tokenRequestContext -> Mono.just(new AccessToken(accessToken, OffsetDateTime.MAX));
IAuthenticationProvider authenticationProvider = new TokenCredentialAuthProvider(tokenCredential);

答案 5 :(得分:0)

我在使用 Graph API 时遇到此错误,因为我在翻阅结果时添加了多个授权标头。每个@odata.nextlink 页面都添加了相同的令牌,导致它在带有此错误消息的初始请求后中断。

这是我的 C# 代码:

private Tuple<JToken, JToken> GetUsersAndNextLink()
    {
        client.BaseUrl = new Uri("https://graph.microsoft.com/v1.0/users");
        var request = new RestRequest("", Method.GET);
        client.AddDefaultHeader("Authorization", string.Format("Bearer {0}", Token));
        IRestResponse response = client.Execute(request);
        var content = response.Content;
        var des = JsonConvert.DeserializeObject<JObject>(content);
        var nextlink = des["@odata.nextLink"];

        var value = des["value"];
        return new Tuple<JToken, JToken>(value, nextlink);
    }

    private Tuple<JToken, JToken> GetUsersAndNextLink(string prevnextlink)
    {
        client.BaseUrl = new Uri(prevnextlink);
        var request = new RestRequest("", Method.GET);
        client.AddDefaultHeader("Authorization", string.Format("Bearer {0}", Token));
        IRestResponse response = client.Execute(request);
        var content = response.Content;
        var des = JsonConvert.DeserializeObject<JObject>(content);
        var nextlink = des["@odata.nextLink"];
        var value = des["value"];
        return new Tuple<JToken, JToken>(value, nextlink);
    }

每当@odata.nextlink 值出现在对结果页面的响应中时,代码就会进行迭代。但是,添加多个标题每次都会导致错误。

删除第三行 GetUsersAndNextLink(string prevnextlink) 方法调用为我解决了这个问题。

确保您的授权标头是有序的 - 在使用 Graph API 时,这似乎是这些问题的所有错误代码。