首页 文章

将访问令牌传递给CRM API会导致未经授权的(401)错误

提问于
浏览
1

我正在尝试使用Azure AD oAuth 2身份验证访问Dynamics CRM Online REST API . 为此,我按照以下步骤操作:

  • 我在Azure中注册了一个Web应用程序和/或web api

  • 将Dynamics CRM的权限配置为具有委派权限"Access CRM Online as organization user"

  • 并创建了一个有效期为1年的密钥并保留了客户端ID .

我的代码:

package com.JasonLattimer.crm.auth;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.naming.ServiceUnavailableException;

import com.microsoft.aad.adal4j.AuthenticationContext;
import com.microsoft.aad.adal4j.AuthenticationResult;
import com.microsoft.aad.adal4j.ClientCredential;

import net.minidev.json.JSONObject;
import net.minidev.json.JSONValue;

public class App {


    // CRM URL
    private final static String RESOURCE = "xxxxxx.crm8.dynamics.com";
    private final static String CLIENT_ID = "xxxxxxx-xxxxx-xxxxxxx-xxxxxxxxx";
    private final static String CLIENT_SECRET_KEY = "xxxxxxxxxxxxxxxxxxxxxx";
    private final static String TENANTID = "xxxxxxxxxxx-xxxx-xxxxx-xxxxxxx";
    private final static String AUTHORITY = "login.microsoftonline.com" + TENANTID + "/oauth2/authorize";

    public static void main(String args[]) throws Exception {
        AuthenticationResult result = getAccessTokenFromUserCredentials();
        System.out.println("Access Token - " + result.getAccessToken());
        System.out.println("Token expires on - " + result.getExpiresOn());

        //String userId = WhoAmI(result.getAccessToken());
        //System.out.println("UserId - " + userId);

        String fullname = FindFullname(result.getAccessToken(), "2b8fc8ca-86cd-e611-8109-c4346bdc0e01");
        System.out.println("Fullname: " + fullname);
    }

    private static AuthenticationResult getAccessTokenFromUserCredentials() throws Exception {

        AuthenticationContext authContext = null;
        AuthenticationResult authResult = null;
        ExecutorService service = null;

        try {
            service = Executors.newFixedThreadPool(1);
            authContext = new AuthenticationContext(AUTHORITY, false, service);

            ClientCredential clientCred = new ClientCredential(CLIENT_ID, CLIENT_SECRET_KEY);
            Future<AuthenticationResult> future = authContext.acquireToken(RESOURCE, clientCred, null);
            authResult = future.get();
        } catch (Exception ex) {
            System.out.println(ex);
        } finally {
            service.shutdown();
        }

        if (authResult == null) {
            throw new ServiceUnavailableException("authentication result was null");
        }
        return authResult;
    }

    private static String FindFullname(String token, String userId) throws MalformedURLException, IOException {
        System.out.println("AAAAAAAAAAAAAAAAAA");
        HttpURLConnection connection = null;
        //The URL will change in 2016 to include the API version - /api/data/v8.0/systemusers
        URL url = new URL(RESOURCE + "/api/data/systemusers(" + userId + ")?$select=fullname");
        connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("OData-MaxVersion", "4.0");
        connection.setRequestProperty("OData-Version", "4.0");
        connection.setRequestProperty("Accept", "application/json");
        connection.addRequestProperty("Authorization", "Bearer " + token);

        int responseCode = connection.getResponseCode();

        BufferedReader in = new BufferedReader(
                new InputStreamReader(connection.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

        Object jResponse;
        jResponse = JSONValue.parse(response.toString());
        JSONObject jObject = (JSONObject) jResponse;
        String fullname = jObject.get("fullname").toString();
        System.out.println("FULL NAME" + fullname);
        return fullname;
    }

    private static String WhoAmI(String token) throws MalformedURLException, IOException {
        HttpURLConnection connection = null;
        //The URL will change in 2016 to include the API version - /api/data/v8.0/WhoAmI
        URL url = new URL(RESOURCE + "/api/data/WhoAmI");
        connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("OData-MaxVersion", "4.0");
        connection.setRequestProperty("OData-Version", "4.0");
        connection.setRequestProperty("Accept", "application/json");
        connection.addRequestProperty("Authorization", "Bearer " + token);

        int responseCode = connection.getResponseCode();

        BufferedReader in = new BufferedReader(
                new InputStreamReader(connection.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

        Object jResponse;
        jResponse = JSONValue.parse(response.toString());
        JSONObject jObject = (JSONObject) jResponse;
        String userId = jObject.get("UserId").toString();
        return userId;
    }
}

我成功检索了一个访问令牌,但是当我尝试对CRM进行httprequest时,我总是得到一个401 - 未经授权的状态代码 . 我错过了什么?

1 回答

  • 0

    你有2个选择:

    • 在CRM中作为"normal"用户进行身份验证的旧方法(您需要密码但可以避免弹出流程) . C#示例here .

    • 新方法是"Server to Server authentication",需要您创建Application User . 注意这个例子也是C#,但ADAL代码在Java中应该非常相似 .

相关问题