如何使用MSAL4J为后台应用程序获取令牌?

huangapple go评论83阅读模式
英文:

How do I use MSAL4J to acquire a token for a daemon?

问题

以下是翻译好的内容:

我有一个用Java编写并在AWS上运行的守护进程。
它使用基于客户端ID、客户端密钥和租户ID的令牌调用多个Microsoft API,以支持我正在支持的数百个用户帐户。使用MS Azure Active Directory Library for Java (ADAL4J),一切都运行正常。但是ADAL4J即将被淘汰,所以我被迫转向MS Authentication Library for Java (MSAL4J)。

基本上,我需要使用客户端ID、密钥和租户来获取用于MS API的访问令牌。

经过对许多示例的漫游(其中许多示例都可以编译),我似乎找到了最接近的代码:

	public static String getToken( String apiUrl, 
			String clientId, 
			String clientSecret,
			String tenantId,
			String authUrl ) {
		
		String token = null ;

		if ( !authUrl.endsWith("/")){
			authUrl = authUrl + "/";
		}

		// 注意:这是从以下来源派生的:
		// https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-desktop-acquire-token?tabs=java
		// 我通过删除了对SilentParameters的支持来简化了代码。

		// 不好:authUrl = authUrl + "organizations/";
		// 不好:authUrl = "https://login.microsoftonline.com/" + tenantId + "/";
		// 不好:authUrl = "https://login.microsoftonline.com/organizations/";
		authUrl = "https://login.microsoftonline.com/organizations/" + tenantId + "/";

		// 不好:Set<String> SCOPE = Collections.singleton("https://graph.microsoft.com/.default");
		// 不好:Set<String> scope = Collections.singleton(clientId);
		Set<String> scope = Collections.singleton("");

		// 从文件加载令牌缓存并初始化令牌缓存方面。令牌缓存将包含虚拟数据,因此acquireTokenSilently调用将失败。
		ITokenCacheAccessAspect tokenCacheAspect = new TokenPersistence("");

		PublicClientApplication pca;
		try {
			pca = PublicClientApplication 
			.builder(clientId)
			.authority(authUrl)
			.setTokenCacheAccessAspect(tokenCacheAspect)
			.build();
		} catch (MalformedURLException e) {
			return null ;
		}

		IAuthenticationResult result;

		/*
		// 不好:ClientCredentialParameters parameters =
		// 不好:ClientCredentialParameters
		// 不好:    .builder(SCOPE)
		// 不好:    .build();
		*/
		UserNamePasswordParameters parameters =
					UserNamePasswordParameters
					.builder(scope, clientId, clientSecret.toCharArray())
					.build();

		result = pca.acquireToken(parameters).join();

		token = result.accessToken() ;
		return token ;
	}

因此,它编译通过(即使坏的注释掉的代码也可以编译通过),并且可以运行,但会生成以下错误:

com.microsoft.aad.msal4j.MsalClientException: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.microsoft.aad.msal4j.InstanceDiscoveryMetadataEntry]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)

上述错误在acquireToken调用(接近底部)时生成。

我无法弄清楚哪些代码需要一个默认构造函数(以使JSON正常)。另一方面,我不知道是否应该使用这些调用;在处理MSAL的各种方法中,似乎有大约47种不同的方法,我一点也不确定是否找到了“正确的路径”。

救救我,奥比万·克诺比。你是我唯一的希望!

英文:

I have a daemon written in Java and running on AWS.
It calls multiple Microsoft APIs using tokens based on client Id, client secret and tenant id for each of 100s of user accounts that I am supporting. All worked fine with MS Azure Active Directory Library for Java (ADAL4J). But that is going bye bye and so I am being forced over to MS Authentication Library for Java (MSAL4J).

Basically, I need to use a client id, secret and tenant to get an accessToken that is required for a MS API.

After much meandering through the examples (many of which compile), it seems that this is the closest code I can get to:

	public static String getToken( String apiUrl, 
String clientId, 
String clientSecret,
String tenantId,
String authUrl ) {
String token = null ;
if ( !authUrl.endsWith(&quot;/&quot;)){
authUrl = authUrl + &quot;/&quot; ;
}
/*
NOTE: This is derived from the following:
https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-desktop-acquire-token?tabs=java
I simplified the code by taking out the SilentParameters support.
*/
// BAD:  authUrl = authUrl + &quot;organizations/&quot;;
// BAD:  authUrl = &quot;https://login.microsoftonline.com/&quot; + tenantId + &quot;/&quot;;
// BAD:  authUrl = &quot;https://login.microsoftonline.com/organizations/&quot;;
authUrl = &quot;https://login.microsoftonline.com/organizations/&quot; + tenantId + &quot;/&quot; ;
// BAD:  Set&lt;String&gt; SCOPE = Collections.singleton(&quot;https://graph.microsoft.com/.default&quot;);
// BAD:  Set&lt;String&gt; scope = Collections.singleton(clientId);
Set&lt;String&gt; scope = Collections.singleton(&quot;&quot;);
// Load token cache from file and initialize token cache aspect. The token cache will have
// dummy data, so the acquireTokenSilently call will fail.
ITokenCacheAccessAspect tokenCacheAspect = new TokenPersistence(&quot;&quot;);
PublicClientApplication pca;
try {
pca = PublicClientApplication 
.builder(clientId)
.authority(authUrl)
.setTokenCacheAccessAspect(tokenCacheAspect)
.build();
} catch (MalformedURLException e) {
return null ;
}
IAuthenticationResult result;
/*
BAD:  ClientCredentialParameters parameters =
BAD:     ClientCredentialParameters
BAD:         .builder(SCOPE)
BAD:         .build();
*/
UserNamePasswordParameters parameters =
UserNamePasswordParameters
.builder(scope, clientId, clientSecret.toCharArray())
.build();
result = pca.acquireToken(parameters).join();
token = result.accessToken() ;
return token ;
}

So, it compiles (even the BAD commented out code compiles), and it runs but it generates:

com.microsoft.aad.msal4j.MsalClientException: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.microsoft.aad.msal4j.InstanceDiscoveryMetadataEntry]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)

The above is generated on the acquireToken call (near the bottom).

I can't figure out what code needs a default constructor (to make the JSON happy).
OTOH, I don't know if these are the calls that I should even be making; there seem to be about 47 different ways through and around this MSAL stuff and I am not at ALL sure if I have found "the right path".

Help Me, Obi-Wan Kenobi. You're My Only Hope!

答案1

得分: 3

查看 ms-identity-java-daemon 示例:https://github.com/Azure-Samples/ms-identity-java-daemon。

英文:

Checkout the ms-identity-java-daemon sample: https://github.com/Azure-Samples/ms-identity-java-daemon.

答案2

得分: 3

不使用 TokenCacheAccessAspect,看看是否起作用?就像这样:

IClientCredential credential = ClientCredentialFactory.createFromSecret(clientSecret);    
ConfidentialClientApplication cca = ConfidentialClientApplication.builder(clientId, credential)
.authority(authUrl)
.build();
Set<String> scope = ImmutableSet.of();
ClientCredentialParameters parameters =
ClientCredentialParameters.builder(scope)
.build();
result = cca.acquireToken(parameters).join();

其中 authUrl 应该类似于 https://login.microsoftonline.com/<tenantId>

参考:https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-daemon-acquire-token?tabs=java

英文:

Try not using TokenCacheAccessAspect at all and see if that works? I.e. something like:

IClientCredential credential = ClientCredentialFactory.createFromSecret(clientSecret);    
ConfidentialClientApplication cca = ConfidentialClientApplication.builder(clientId, credential)
.authority(authUrl)
.build();
Set&lt;String&gt; scope = ImmutableSet.of();
ClientCredentialParameters parameters =
ClientCredentialParameters.builder(scope)
.build();
result = cca.acquireToken(parameters).join();

Where authUrl should look like https://login.microsoftonline.com/&lt;tenantId&gt;

See: https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-daemon-acquire-token?tabs=java

huangapple
  • 本文由 发表于 2020年4月11日 07:21:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/61150094.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定