【问题标题】:OneDrive authentication using ADAL4J使用 ADAL4J 的 OneDrive 身份验证
【发布时间】:2019-07-31 13:40:50
【问题描述】:

Active Directory Authentication Library for Java (ADAL4J) 允许通过对Microsoft Graph API 的访问令牌进行身份验证,使用以下(简化)代码:

public String authenticate(String authorizationUrl, String clientId, String clientSecret) throws Exception {
    ExecutorService service = Executors.newFixedThreadPool(1);
    AuthenticationContext context = new AuthenticationContext(authorizationUrl, false, service);
    ClientCredential credential = new ClientCredential(clientId, clientSecret);
    Future<AuthenticationResult> future = context.acquireToken(“https://graph.microsoft.com”, credential, null);
    return future.get().getAccessToken();
}

以上内容适用于 Graph 的某些部分(例如,用于访问 Office 365 帐户),但不适用于 OneDrive,它返回一个没有适当授权的访问令牌。

通过POSTMAN 获取访问令牌按预期工作,使用以下参数:

authorizationUrl: https://login.microsoftonline.com/common/oauth2/v2.0/authorize
accessTokenUrl: https://login.microsoftonline.com/common/oauth2/v2.0/token
clientId: <the clientId for the application>
clientSecret: <the clientSecret for the application> 
scope: https://graph.microsoft.com/.default
state: <empty>

更具体地说,在POSTMAN 中运行上述内容会返回一个具有其他范围的访问令牌,包括https://graph.microsoft.com/Files.ReadWrite.All。在调用上述authenticate() 方法的Java 应用程序中使用该访问令牌确实有效,例如它使用/me/drive/root/children 作为 REST 路径列出了根目录的内容。

但是,如果使用authenticate() 方法返回的访问令牌,则OneDrive 会返回错误。如果在 authenticationUrl 中使用特定租户 ID 而不是 common,则从路径中删除用户名 (me) 仅返回 1 个文件名。

似乎无法在 ADAL4J 中添加范围值,并且许多其他变体要么导致错误,要么导致返回 1 个文件(可能来自不同的上下文)。

有没有办法通过 ADAL4J 为 OneDrive 获取完全授权的访问令牌?

【问题讨论】:

    标签: java authentication onedrive adal adal4j


    【解决方案1】:

    有两种不同的权限:一种是应用权限,另一种是委托权限。

    “委托”权限​​(使用来自已登录资源所有者的委托授权指定基于范围的访问)在运行时作为客户端访问令牌中的“scp”声明呈现给资源。 em>

    “应用程序”权限使用客户端应用程序的凭据/身份指定基于角色的访问,在运行时作为客户端访问令牌中的“角色”声明呈现给资源。

    当您第一次从 POSTMAN 获得令牌时,系统会要求您提供您的凭据。这样,您将获得一个具有委托权限的令牌,该令牌代表该帐户。这样,您就可以调用 /me 下的 Graph API。

    但是,你用来获取token的java代码只能获取应用权限的访问token。该应用程序没有用户身份,因此在调用 /me 下的 Graph API 时会出错。有应用权限,只能以 /users/{user-id}

    调用 Graph API

    解决方案:

    您可以在 Java 中获得具有委派权限的访问令牌,如下所示:

    A) 使用公共客户端平台创建应用

    B) 添加必要的 Graph API 权限,并为您的租户授予管理员同意

    C) 获取令牌

    ExecutorService service = Executors.newFixedThreadPool(1);
    AuthenticationContext context = null;
    try {
        context = new AuthenticationContext("https://login.microsoftonline.com/" + "TENANT_ID", false, service);
        Future<AuthenticationResult> future = context.acquireToken("https://graph.microsoft.com", "client_id", "username", "password",null);
        System.out.println( future.get().getAccessToken());
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }finally {
        service.shutdown();
    }
    

    【讨论】:

    • 我以各种组合方式完成了所有这些工作,包括“授予管理员同意”。无论如何,我再次尝试使用具有特定tenantId(而不是“common”,尽管我也尝试过)的授权URL,对于同一个应用程序,使用相同的clientId和clientSecret(而不是用户名和密码)在我在上面发布的 authenticate() 方法,它有效。不知道发生了什么,但你应该得到大部分的功劳,所以 +1 并接受了答案。谢谢! :-)
    • 问题是“普通”租户引用的驱动器与特定租户不同,因此与结果存在差异。
    猜你喜欢
    • 1970-01-01
    • 2019-01-01
    • 1970-01-01
    • 2014-05-25
    • 1970-01-01
    • 2017-11-27
    • 2014-11-30
    • 2016-03-23
    • 1970-01-01
    相关资源
    最近更新 更多