我正在使用 MSAL 以单帐户模式将用户登录到 Android 应用程序。这有效。我希望能够使用收到的访问 token 来调用受 Azure AD 保护的 API 终结点。我已注册客户端应用程序和 API,并已授予从 API 到客户端应用程序所需范围的访问权限。
这是我的 build.gradle
中的库引用
implementation "com.microsoft.identity.client:msal:2.0.8"
我们在 Azure 门户中使用应用程序注册体验,并将 v2.0 授权端点与 Postman 的 OAuth2 token acquisition 结合使用。功能,效果很好。这是我的设置
Grant Type : Authorization Code (With PKCE)
Callback URL : "http://localhost"
Authorization URL : "https://login.microsoftonline.com/{{Tenant}}/oauth2/v2.0/authorize"
Token URL : "https://login.microsoftonline.com/{{Tenant}}/oauth2/v2.0/token"
Client ID & Client Secret from portal
Code Challenge Method: SHA-256
Scope : From API Registration
但是,MSAL Android 的 token 没有范围或受众。身份验证失败,日志如下:
Authentication failed: com.microsoft.identity.client.exception.MsalDeclinedScopeException: Some or all requested scopes have been declined by the Server
此行为似乎与使用旧授权端点时发生的情况相当一致。
无论如何,是否有针对此问题的修复/解决方法,或者我可以采取其他措施来使其正常工作?
编辑
以下是 API 应用程序注册中公开 API Blade 的屏幕截图
Expose API from API registration
这是我用来登录用户的 Kotlin 代码
var SCOPES = arrayOf("api://<api-app-id>/<scope-name>","api://<api-app-id>/scope-name>")
PublicClientApplication.createSingleAccountPublicClientApplication(
applicationContext,
R.raw.auth_config_single_account, object : ISingleAccountApplicationCreatedListener {
override fun onCreated(application: ISingleAccountPublicClientApplication) {
mSingleAccountApp = application
loadAccount() //processes the logged in account
}
override fun onError(exception: MsalException) {
}
})
loginButton.setOnClickListener(View.OnClickListener {
if (mSingleAccountApp == null) {
return@OnClickListener
}
getAuthInteractiveCallback()?.let { it1 ->
mSingleAccountApp!!.signIn(
this@MainActivity,
null,
SCOPES,
it1
)
}
})
最佳答案
不确定您提到的自定义范围。您需要使用 api://<client-id>/xxx
更改范围像这样。
请尝试以下代码。
通过 MSAL 获取 token :
String[] SCOPES = {"api://<client-id>/.default"};
PublicClientApplication sampleApp = new PublicClientApplication(
this.getApplicationContext(),
R.raw.auth_config);
// Check if there are any accounts we can sign in silently.
// Result is in the silent callback (success or error).
sampleApp.getAccounts(new PublicClientApplication.AccountsLoadedCallback() {
@Override
public void onAccountsLoaded(final List<IAccount> accounts) {
if (accounts.isEmpty() && accounts.size() == 1) {
// TODO: Create a silent callback to catch successful or failed request.
sampleApp.acquireTokenSilentAsync(SCOPES, accounts.get(0), getAuthSilentCallback());
} else {
/* No accounts or > 1 account. */
}
}
});
[...]
// No accounts found. Interactively request a token.
// TODO: Create an interactive callback to catch successful or failed requests.
sampleApp.acquireToken(getActivity(), SCOPES, getAuthInteractiveCallback());
使用访问 token 调用 API:
RequestQueue queue = Volley.newRequestQueue(this);
JSONObject parameters = new JSONObject();
try {
parameters.put("key", "value");
} catch (Exception e) {
// Error when constructing.
}
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, MSGRAPH_URL,
parameters,new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
// Successfully called Graph. Process data and send to UI.
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// Error.
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
// Put access token in HTTP request.
headers.put("Authorization", "Bearer " + accessToken);
return headers;
}
};
request.setRetryPolicy(new DefaultRetryPolicy(
3000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
queue.add(request);
关于android - 在 Android 上使用 MSAL 获取访问 token 来调用受 Azure AD 保护的 API 会出现 MsalDeclinedScopeException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67160840/