尝试从 Azure AD 获取访问令牌时获取响应代码 400

Posted

技术标签:

【中文标题】尝试从 Azure AD 获取访问令牌时获取响应代码 400【英文标题】:Getting response code 400 when trying to get access token from Azure AD 【发布时间】:2018-06-04 23:32:14 【问题描述】:

我正在为我的 Web 应用程序实现 azure,并尝试按照 openId 连接教程获取访问令牌

https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-code

当我请求获取访问令牌时,我总是收到错误的请求 400

请求获取访问令牌:

POST /租户/oauth2/token HTTP/1.1

主持人:https://login.microsoftonline.com

内容类型:application/x-www-form-urlencoded

grant_type=authorization_code

&client_id=2d4d11a2-f814-46a7-890a-274a72a7309e

&code=AwABAAAAvPM1KaPl.......

&redirect_uri=https%3A%2F%2Flocalhost%2Fmyapp%2F

&resource=https%3A%2F%2Fservice.contoso.com%2F

&client_secret=p@ssw0rd

这是我的代码:

public static String post( String endpoint,
        Map<String, String> params) //YD
    StringBuffer paramString = new StringBuffer("");
    //if(!Utilities.checkInternetConnection(context))
    //  return XMLHandler.getXMLForErrorCode(context, JSONHandler.ERROR_CODE_INTERNET_CONNECTION);
    //
    Iterator<Entry<String, String>> iterator = params.entrySet().iterator();
    StringBuffer tempBuffer = new StringBuffer("");
    String paramval;
    while (iterator.hasNext()) 
        Entry<String, String> param = iterator.next();
        if (param != null) 
            if (paramString.length() > 0) 
                paramString.append("&");
            
            System.out.println( "post key : " + param.getKey());
            String value;
            try 
                paramval = param.getValue();
                if(paramval!=null)
                    value = URLEncoder.encode(paramval, "UTF-8");
                else
                    value = "";
             catch (UnsupportedEncodingException e) 
                value = "";
                e.printStackTrace();
            


                paramString.append(param.getKey()).append("=")
                        .append(value);
        
    
    try 
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost(endpoint);
        String data = "";

        try 
            // Add your data
            // httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs))
            //httppost.addHeader("Host", host);
            httppost.addHeader("Content-Type",
                    "application/x-www-form-urlencoded");

            if (!paramString.equals("")) 
                if (tempBuffer.length() > 0) 
                    data = data + tempBuffer.toString();
                
                data = data + paramString.toString();

                if (data.endsWith("&")) 
                    data = data.substring(0, data.length() - 1);
                 

                httppost.setEntity(new ByteArrayEntity(data.getBytes()));
            

            System.out.println( "post Stringbuffer  : " + data);

            // Execute HTTP Post Request
            HttpResponse response = httpclient.execute(httppost);
            int statuscode = response.getStatusLine().getStatusCode();
            System.out.println("Response code : " + statuscode);
            if (statuscode != 200) 
                return null;
            
            HttpEntity entity = response.getEntity();
            InputStream in = null;
            if (entity != null) 
                in = entity.getContent();
            

            if (in != null) 
                StringBuilder builder = new StringBuilder();
                String line;
                try 
                    BufferedReader reader = new BufferedReader(
                            new InputStreamReader(in, "UTF-8"));
                    while ((line = reader.readLine()) != null) 
                        builder.append(line);
                    
                 finally 
                    in.close();
                

                String response2 = builder.toString();

                System.out.println("response :" + response2);
                retrycount = 0;

                return response2;
            
        
        catch(UnknownHostException e)
            e.printStackTrace();
            return null;
        
        catch (EOFException eof) 
            if (retrycount < max_retry) 
                eof.printStackTrace();
                post( endpoint, params);
                retrycount = 1;
            
         catch (Throwable th) 
            throw new IOException("Error in posting :" + th.getMessage());
        
        retrycount = 0;
        return null;
     catch (Exception e) 
        e.printStackTrace();
    
    return null;

请帮帮我

提前致谢

【问题讨论】:

客户端的秘密就一定是为应用程序制作的密钥吗?它还需要进行 URL 编码。 【参考方案1】:

请参考下方代码申请AuthorizationCode

public static void getAuthorizationCode() throws IOException 

        String encoding = "UTF-8";
        String params = "client_id=" + clientId 
                + "&response_type=" + reponseType
                + "&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F"
                + "&response_mode=query"
                + "&resource=https%3A%2F%2Fgraph.windows.net"
                + "&state=12345";
        String path = "https://login.microsoftonline.com/" + tenantId + "/oauth2/authorize";
        byte[] data = params.getBytes(encoding);
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("Content-Length", String.valueOf(data.length));
        conn.setConnectTimeout(5 * 1000);
        OutputStream outStream = conn.getOutputStream();
        outStream.write(data);
        outStream.flush();
        outStream.close();
        System.out.println(conn.getResponseCode());
        System.out.println(conn.getResponseMessage());

        BufferedReader br = null;
        if (conn.getResponseCode() != 200) 
            br = new BufferedReader(new InputStreamReader((conn.getErrorStream())));
         else 
            br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
        
        System.out.println("Response body : " + br.readLine());
    

然后您可以使用您获得的AuthorizationCode 获取access token,并使用以下代码获取刷新代码。

public static void getToken(String refreshToken) throws IOException 

        String encoding = "UTF-8";
        String params = "client_id=" + clientId + "&refresh_token=" + refreshToken
                + "&grant_type=refresh_token&resource=https%3A%2F%2Fgraph.windows.net";
        String path = "https://login.microsoftonline.com/" + tenantId + "/oauth2/token";
        byte[] data = params.getBytes(encoding);
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("Content-Length", String.valueOf(data.length));
        conn.setConnectTimeout(5 * 1000);
        OutputStream outStream = conn.getOutputStream();
        outStream.write(data);
        outStream.flush();
        outStream.close();
        System.out.println(conn.getResponseCode());
        System.out.println(conn.getResponseMessage());

        BufferedReader br = null;
        if (conn.getResponseCode() != 200) 
            br = new BufferedReader(new InputStreamReader((conn.getErrorStream())));
         else 
            br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
        
        System.out.println("Response body : " + br.readLine());
    

希望对你有帮助。

【讨论】:

【参考方案2】:

您是否确保传递给 /token 的重定向 uri 与传递给 /authorize 的重定向 uri 相同

我相信,如果您可以使用 Postman 工具使用当前客户端 ID、机密和范围测试 OAuth 身份验证代码流以排除错误配置,这将有所帮助。

【讨论】:

以上是关于尝试从 Azure AD 获取访问令牌时获取响应代码 400的主要内容,如果未能解决你的问题,请参考以下文章

使用 JWT 令牌保护 asp.net 核心 Web api 时如何从 Azure AD 获取用户

通过邮递员从 Azure 应用服务验证令牌返回 401

在 Postman 中为 Azure AD B2C 请求访问令牌

如何使用 Postman 获取 Azure AD 刷新令牌?

如何在 Azure Ad 中实现代流?

使用刷新令牌 adal azure AD 静默更新访问令牌