首页 > 解决方案 > Microsoft Graph 和 Java - 针对授权代码流的多次调用

问题描述

几个小时以来,我一直在尝试解决这个问题,现在我在兜圈子,浪费了有趣的 RnD 时间。我正在使用 MS Graph API 来访问 Office 365,并且我已经使用授权流程对其进行了设置,以授权我的 Java servlet。它工作正常(获取身份验证代码的 URL 在其他地方)但我只能运行一个调用。我在后续调用的异常中收到以下错误(在我的代码中,是在我尝试查看驱动器时):

OAuth2 授权代码已被兑换,请使用新的有效代码重试或使用现有的刷新令牌。

我假设这意味着我需要刷新我的令牌(真的很明显,而且我发现关于这个的注释说现在在这个流程中是必要的),但我不知道如何使用 GraphServiceClient .

我的代码在下面,在我将笔记本电脑从最近的窗口飞出之前,任何帮助都将受到欢迎。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


        PrintWriter out = response.getWriter();

        String code = request.getParameter("code");

        String clientId = "***";
        String clientSecret = "***";
        String authorisationCode = code; 
        String redirectURL = "http://localhost:8080/O365Web/auth";
        String tenant = "***";

        AuthorizationCodeCredential authCodeCredential = new AuthorizationCodeCredentialBuilder()
                .clientId(clientId)
                .clientSecret(clientSecret) //required for web apps, do not set for native apps
                .authorizationCode(authorisationCode)
                .redirectUrl(redirectURL)               
                .build();

        List<String> scopes = new ArrayList<String>();
        scopes.add("https://graph.microsoft.com/User.Read");
        scopes.add("https://graph.microsoft.com/Files.ReadWrite.All");
        scopes.add("https://graph.microsoft.com/offline_access");

        TokenCredentialAuthProvider tokenCredentialAuthProvider = new TokenCredentialAuthProvider(scopes, authCodeCredential);      

        GraphServiceClient graphClient =
                GraphServiceClient
                .builder()              
                .authenticationProvider(tokenCredentialAuthProvider)                
                .buildClient();

        try {
            final User me = graphClient.me().buildRequest().get();
            out.println("Name: " + me.displayName + "");
        } catch ( Exception ex ) {
            out.println("Exception in first user get: " + ex.getMessage() );    
            ex.printStackTrace();
        }

        try {
            DriveItemCollectionPage children = graphClient.me().drive().root().children().buildRequest().get();

            while ( children != null ) {

                for ( DriveItem item : children.getCurrentPage() ) {
                    out.println("C:" + item.name + " : " + item.id);
                }

                DriveItemCollectionRequestBuilder builder = children.getNextPage();
                if ( builder != null ) {
                    out.println("Loading page...");
                    children = children.getNextPage().buildRequest().get();
                } else {
                    children = null;
                }
            }
        } catch ( Exception ex ) {
            out.println("Exception in children get: " + ex.getMessage());   
            ex.printStackTrace();
        }

        try {
            final User me2 = graphClient.me().buildRequest().get();
            out.println(me2.displayName + "<br/>");
        } catch ( Exception ex ) {
            out.println("Exception in second user get: " + ex.getMessage());    
            ex.printStackTrace();
        }
    }

标签: javaoauth-2.0azure-active-directorymicrosoft-graph-api

解决方案


我已经在我的环境中测试过了。

当我首先运行请求时,我能够生成访问令牌

当我再次运行相同的请求时,我也得到了同样的错误:

OAuth2 授权码已兑换,请使用新的有效代码重试或使用现有的刷新令牌

错误原因是authCodeCredential中使用的授权码只能使用一次

String authorisationCode = code; 

如果要发出新请求,可以生成新的授权码(获取授权码的 URL 在别处)并在 authCodeCredential 中使用

这可以解决问题

另一种方法是使用刷新令牌。

使用 URL 生成授权代码时,您可以使用offline_access添加另一个范围

现在,在使用授权代码生成访问令牌时,使用offline_access添加另一个范围。这将生成一个刷新令牌和访问令牌。

现在,您可以在访问令牌过期时使用刷新令牌生成新的访问令牌

参考:代表用户获取访问权限 - Microsoft Graph | 微软文档


推荐阅读