【问题标题】:ADAL4j java - use refresh token with username and password to get the access tokenADAL4j java - 使用带有用户名和密码的刷新令牌来获取访问令牌
【发布时间】:2018-01-23 11:36:43
【问题描述】:

我正在使用 java 后端服务器连接到启用 Azure AD 的 API。我可以通过以下 java 代码获取访问令牌。

    String tenantId = "************";
    String username = "***************";
    String password = "*************";
    String clientId = "**********";
    String resource = "***********";
    String userEmail = "**********";


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

    try
    {
        service = Executors.newFixedThreadPool( 1 );
        String url = "https://login.microsoftonline.com/" + tenantId + "/oauth2/authorize";
        authContext = new AuthenticationContext( url, false, service );
        Future<AuthenticationResult> future = authContext.acquireToken(
                resource,
                clientId,
                userEmail,
                password,
                null );

        authResult = future.get();

    }
    catch( Exception ex )
    {
        ex.printStackTrace();
    }

请注意,API 提供商目前不支持客户端凭据。

我的问题是,使用上面代码中收到的刷新令牌来获取新的访问令牌。

ADAL4j java 库似乎没有任何方法支持这一点。 A Documentation for java library

但在 .NET 库中有类似的方法,

public AuthenticationResult AcquireTokenByRefreshToken(
string refreshToken,
string clientId,
string resource
)

用于在不提供任何凭据的情况下刷新访问令牌。

为什么Java库中没有提供这些方法?。有什么限制吗? 有哪些可能的解决方法?

提前致谢。

【问题讨论】:

    标签: java azure oauth-2.0 refresh-token adal4j


    【解决方案1】:

    据我所知,虽然Java ADAL4J库不支持该方法

    public AuthenticationResult AcquireTokenByRefreshToken(
    string refreshToken,
    string clientId,
    string resource
    )
    

    .Net库支持,这两种库都是通过HTTP REST API实现的。

    您可以参考官方document中的刷新访问令牌

    // Line breaks for legibility only
    
    POST /{tenant}/oauth2/token HTTP/1.1
    Host: https://login.microsoftonline.com
    Content-Type: application/x-www-form-urlencoded
    
    client_id=6731de76-14a6-49ae-97bc-6eba6914391e
    &refresh_token=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq...
    &grant_type=refresh_token
    &resource=https%3A%2F%2Fservice.contoso.com%2F
    &client_secret=JqQX2PNo9bpM0uEihUPzyrh    // NOTE: Only required for web apps
    

    我使用 Postman 测试通过 refreshToken 获取 accessToken 的请求,无需凭据供您参考:

    对应,我用下面的Java代码实现了请求:

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    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 com.microsoft.aad.adal4j.AuthenticationContext;
    import com.microsoft.aad.adal4j.AuthenticationResult;
    
    public class AcquireTokenByRefreshToken {
    
        static String tenantId = "***";
        static String username = "***";
        static String password = "***";
        static String clientId = "***";
        static String resource = "https://graph.windows.net";
        static String userEmail = "***";
    
        public static void main(String[] args) throws MalformedURLException, IOException {
            AuthenticationContext authContext = null;
            AuthenticationResult authResult = null;
            ExecutorService service = null;
    
            try {
                service = Executors.newFixedThreadPool(1);
                String url = "https://login.microsoftonline.com/" + tenantId + "/oauth2/authorize";
                authContext = new AuthenticationContext(url, false, service);
                Future<AuthenticationResult> future = authContext.acquireToken(resource, clientId, userEmail, password,
                        null);
    
                authResult = future.get();
                System.out.println("get access token: \n" + authResult.getAccessToken());
                System.out.println("get refresh token: \n" + authResult.getRefreshToken());
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            // get access token by refresh token
            getToken(authResult.getRefreshToken());
        }
    
        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());
        }
    
    }
    

    控制台打印的结果如下:

    希望对你有帮助。

    【讨论】:

    • 谢谢。我发现您提供的替代方案非常有用。
    • 但是你知道为什么 java 库不支持这个功能吗?应该是有原因的。
    猜你喜欢
    • 2015-07-19
    • 2021-03-02
    • 2020-06-12
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 2013-08-23
    • 2018-11-26
    相关资源
    最近更新 更多