@@ -36,7 +36,9 @@ import com.microsoft.identity.client.exception.MsalException
3636import com.microsoft.identity.client.internal.CommandParametersAdapter
3737import com.microsoft.identity.common.internal.commands.RemoveCurrentAccountCommand
3838import com.microsoft.identity.common.internal.controllers.LocalMSALController
39+ import com.microsoft.identity.common.java.AuthenticationConstants
3940import com.microsoft.identity.common.java.commands.CommandCallback
41+ import com.microsoft.identity.common.java.commands.SilentTokenCommand
4042import com.microsoft.identity.common.java.controllers.CommandDispatcher
4143import com.microsoft.identity.common.java.controllers.ExceptionAdapter
4244import com.microsoft.identity.common.java.dto.AccountRecord
@@ -46,7 +48,7 @@ import com.microsoft.identity.common.java.exception.ServiceException
4648import com.microsoft.identity.common.java.logging.LogSession
4749import com.microsoft.identity.common.java.logging.Logger
4850import com.microsoft.identity.common.java.result.ILocalAuthenticationResult
49- import com.microsoft.identity.common.nativeauth.internal.commands.AcquireTokenNoFixedScopesCommand
51+ import com.microsoft.identity.common.java.result.LocalAuthenticationResult
5052import com.microsoft.identity.common.nativeauth.internal.controllers.NativeAuthMsalController
5153import com.microsoft.identity.nativeauth.NativeAuthPublicClientApplication
5254import com.microsoft.identity.nativeauth.NativeAuthPublicClientApplicationConfiguration
@@ -60,6 +62,7 @@ import com.microsoft.identity.nativeauth.utils.serializable
6062import kotlinx.coroutines.Dispatchers
6163import kotlinx.coroutines.launch
6264import kotlinx.coroutines.withContext
65+ import java.util.UUID
6366
6467/* *
6568 * AccountState returned as part of a successful completion of sign in flow [com.microsoft.identity.nativeauth.statemachine.results.SignInResult.Complete].
@@ -207,13 +210,11 @@ class AccountState private constructor(
207210 interface GetAccessTokenCallback : Callback <GetAccessTokenResult >
208211
209212 /* *
210- * Retrieves the access token for the currently signed in account from the cache.
213+ * Retrieves the access token for the default OIDC (openid, offline_access, profile) scopes from the cache
211214 * If the access token is expired, it will be attempted to be refreshed using the refresh token that's stored in the cache;
212215 * callback variant.
213216 *
214217 * @return [com.microsoft.identity.client.IAuthenticationResult] If successful.
215- * @throws [MsalClientException] If the the account doesn't exist in the cache.
216- * @throws [ServiceException] If the refresh token doesn't exist in the cache/is expired, or the refreshing fails.
217218 */
218219 fun getAccessToken (forceRefresh : Boolean = false, callback : GetAccessTokenCallback ) {
219220 LogSession .logMethodCall(
@@ -233,18 +234,70 @@ class AccountState private constructor(
233234 }
234235
235236 /* *
236- * Retrieves the access token for the currently signed in account from the cache.
237+ * Retrieves the access token for the default OIDC (openid, offline_access, profile) scopes from the cache.
237238 * If the access token is expired, it will be attempted to be refreshed using the refresh token that's stored in the cache;
238239 * Kotlin coroutines variant.
239240 *
240241 * @return [com.microsoft.identity.nativeauth.statemachine.results.GetAccessTokenResult] The result of the getAccessToken action
241242 */
242243 suspend fun getAccessToken (forceRefresh : Boolean = false): GetAccessTokenResult {
244+ return getAccessTokenInternal(forceRefresh, AuthenticationConstants .DEFAULT_SCOPES .toList());
245+ }
246+
247+ /* *
248+ * Retrieves the access token for the currently signed in account from the cache such that
249+ * the scope of retrieved access token is a superset of requested scopes. If the access token
250+ * has expired, it will be refreshed using the refresh token that's stored in the cache. If no
251+ * access token matching the requested scopes is found in cache then a new access token is fetched.
252+ * Kotlin coroutines variant.
253+ *
254+ * @return [com.microsoft.identity.nativeauth.statemachine.results.GetAccessTokenResult] The result of the getAccessToken action
255+ */
256+ suspend fun getAccessToken (forceRefresh : Boolean = false, scopes : List <String >): GetAccessTokenResult {
257+ if (scopes.isEmpty()) {
258+ return GetAccessTokenError (
259+ errorType = GetAccessTokenErrorTypes .INVALID_SCOPES ,
260+ errorMessage = " Empty or invalid scopes" ,
261+ correlationId = correlationId
262+ )
263+ }
264+
265+ return getAccessTokenInternal(forceRefresh, scopes)
266+ }
267+
268+ /* *
269+ * Retrieves the access token for the currently signed in account from the cache such that
270+ * the scope of retrieved access token is a superset of requested scopes. If the access token
271+ * has expired, it will be refreshed using the refresh token that's stored in the cache. If no
272+ * access token matching the requested scopes is found in cache then a new access token is fetched.
273+ * callback variant.
274+ *
275+ * @return [com.microsoft.identity.client.IAuthenticationResult] If successful.
276+ */
277+ fun getAccessToken (forceRefresh : Boolean = false, scopes : List <String >, callback : GetAccessTokenCallback ) {
278+ LogSession .logMethodCall(
279+ tag = TAG ,
280+ correlationId = null ,
281+ methodName = " $TAG .getAccessToken"
282+ )
283+ NativeAuthPublicClientApplication .pcaScope.launch {
284+ try {
285+ val result = getAccessToken(forceRefresh, scopes)
286+ callback.onResult(result)
287+ } catch (e: MsalException ) {
288+ Logger .error(TAG , " Exception thrown in getAccessToken" , e)
289+ callback.onError(e)
290+ }
291+ }
292+ }
293+
294+ private suspend fun getAccessTokenInternal (forceRefresh : Boolean , scopes : List <String >): GetAccessTokenResult {
243295 LogSession .logMethodCall(
244296 tag = TAG ,
245297 correlationId = null ,
246298 methodName = " $TAG .getAccessToken(forceRefresh: Boolean)"
247299 )
300+
248301 return withContext(Dispatchers .IO ) {
249302 try {
250303 val currentAccount =
@@ -253,31 +306,45 @@ class AccountState private constructor(
253306 errorType = GetAccessTokenErrorTypes .NO_ACCOUNT_FOUND ,
254307 error = MsalClientException .NO_CURRENT_ACCOUNT ,
255308 errorMessage = MsalClientException .NO_CURRENT_ACCOUNT_ERROR_MESSAGE ,
256- correlationId = " UNSET "
309+ correlationId = correlationId
257310 )
258311
259312 val acquireTokenSilentParameters = AcquireTokenSilentParameters .Builder ()
260313 .forAccount(currentAccount)
261314 .fromAuthority(currentAccount.authority)
315+ .withCorrelationId(UUID .fromString(correlationId))
316+ .forceRefresh(forceRefresh)
317+ .withScopes(scopes)
262318 .build()
263319
264- val accountToBeUsed = PublicClientApplication .selectAccountRecordForTokenRequest(
320+ val accountRecord = PublicClientApplication .selectAccountRecordForTokenRequest(
265321 config,
266322 acquireTokenSilentParameters
267323 )
324+ acquireTokenSilentParameters.accountRecord = accountRecord
268325
269- val params =
270- CommandParametersAdapter .createAcquireTokenNoFixedScopesCommandParameters(
271- config,
272- config.oAuth2TokenCache,
273- accountToBeUsed,
274- forceRefresh,
275- correlationId
276- )
326+ val params = CommandParametersAdapter .createSilentTokenCommandParameters(
327+ config,
328+ config.oAuth2TokenCache,
329+ acquireTokenSilentParameters
330+ )
277331
278- val command = AcquireTokenNoFixedScopesCommand (
332+ val command = SilentTokenCommand (
279333 params,
280- NativeAuthMsalController (),
334+ NativeAuthMsalController ().asControllerFactory(),
335+ object : CommandCallback <LocalAuthenticationResult ?, BaseException ?> {
336+ override fun onError (error : BaseException ? ) {
337+ // Do nothing, handled by CommandDispatcher.submitSilentReturningFuture()
338+ }
339+
340+ override fun onTaskCompleted (result : LocalAuthenticationResult ? ) {
341+ // Do nothing, handled by CommandDispatcher.submitSilentReturningFuture()
342+ }
343+
344+ override fun onCancel () {
345+ // Do nothing
346+ }
347+ },
281348 PublicApiId .NATIVE_AUTH_ACCOUNT_GET_ACCESS_TOKEN
282349 )
283350
@@ -288,14 +355,14 @@ class AccountState private constructor(
288355 is ServiceException -> {
289356 GetAccessTokenError (
290357 exception = ExceptionAdapter .convertToNativeAuthException(commandResult),
291- correlationId = " UNSET "
358+ correlationId = commandResult.correlationId ? : correlationId
292359 )
293360 }
294361
295362 is Exception -> {
296363 GetAccessTokenError (
297364 exception = commandResult,
298- correlationId = " UNSET "
365+ correlationId = correlationId
299366 )
300367 }
301368
0 commit comments