use of com.microsoft.identity.common.internal.commands.parameters.SilentTokenCommandParameters in project microsoft-authentication-library-common-for-android by AzureAD.
the class CommandDispatcher method submitSilentReturningFuture.
/**
* submitSilent - Run a command using the silent thread pool, and return the future governing it.
*
* @param command
*/
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
public static FinalizableResultFuture<CommandResult> submitSilentReturningFuture(@SuppressWarnings(WarningType.rawtype_warning) @NonNull final BaseCommand command) {
final String methodName = ":submitSilent";
final CommandParameters commandParameters = command.getParameters();
final String correlationId = initializeDiagnosticContext(commandParameters.getCorrelationId(), commandParameters.getSdkType() == null ? SdkType.UNKNOWN.getProductName() : commandParameters.getSdkType().getProductName(), commandParameters.getSdkVersion());
// set correlation id on parameters as it may not already be set
commandParameters.setCorrelationId(correlationId);
logParameters(TAG + methodName, correlationId, commandParameters, command.getPublicApiId());
final Handler handler = new Handler(Looper.getMainLooper());
synchronized (mapAccessLock) {
final FinalizableResultFuture<CommandResult> finalFuture;
if (command.isEligibleForCaching()) {
FinalizableResultFuture<CommandResult> future = sExecutingCommandMap.get(command);
if (null == future) {
future = new FinalizableResultFuture<>();
final FinalizableResultFuture<CommandResult> putValue = sExecutingCommandMap.putIfAbsent(command, future);
if (null == putValue) {
// our value was inserted.
future.whenComplete(getCommandResultConsumer(command, handler));
} else {
// Our value was not inserted, grab the one that was and hang a new listener off it
putValue.whenComplete(getCommandResultConsumer(command, handler));
return putValue;
}
} else {
future.whenComplete(getCommandResultConsumer(command, handler));
return future;
}
finalFuture = future;
} else {
finalFuture = new FinalizableResultFuture<>();
finalFuture.whenComplete(getCommandResultConsumer(command, handler));
}
sSilentExecutor.execute(new Runnable() {
@Override
public void run() {
try {
// initializing again since the request is transferred to a different thread pool
initializeDiagnosticContext(correlationId, commandParameters.getSdkType() == null ? SdkType.UNKNOWN.getProductName() : commandParameters.getSdkType().getProductName(), commandParameters.getSdkVersion());
EstsTelemetry.getInstance().initTelemetryForCommand(command);
EstsTelemetry.getInstance().emitApiId(command.getPublicApiId());
CommandResult commandResult = null;
// Log operation parameters
if (command.getParameters() instanceof SilentTokenCommandParameters) {
EstsTelemetry.getInstance().emitForceRefresh(((SilentTokenCommandParameters) command.getParameters()).isForceRefresh());
}
// If nothing in cache, execute the command and cache the result
if (commandResult == null) {
commandResult = executeCommand(command);
// Disabling throttling ADO:1383033
// cacheCommandResult(command, commandResult);
Logger.info(TAG + methodName, "Completed silent request as owner for correlation id : **" + correlationId + ", with the status : " + commandResult.getStatus().getLogStatus() + " is cacheable : " + command.isEligibleForCaching());
} else {
Logger.info(TAG + methodName, "Silent command result returned from cache for correlation id : " + correlationId + " having status : " + commandResult.getStatus().getLogStatus());
// Added to keep the original correlation id intact, and to not let it mutate with the cascading requests hitting the cache.
commandResult = new CommandResult(commandResult.getStatus(), commandResult.getResult(), commandResult.getCorrelationId());
}
// TODO 1309671 : change required to stop the LocalAuthenticationResult object from mutating in cases of cached command.
// set correlation id on Local Authentication Result
setCorrelationIdOnResult(commandResult, correlationId);
Telemetry.getInstance().flush(correlationId);
EstsTelemetry.getInstance().flush(command, commandResult);
finalFuture.setResult(commandResult);
} catch (final Throwable t) {
Logger.info(TAG + methodName, "Request encountered an exception with correlation id : **" + correlationId);
finalFuture.setException(new ExecutionException(t));
} finally {
synchronized (mapAccessLock) {
if (command.isEligibleForCaching()) {
final FinalizableResultFuture mapFuture = sExecutingCommandMap.remove(command);
if (mapFuture == null) {
// If this has happened, the command that we started with has mutated. We will
// examine every entry in the map, find the one with the same object identity
// and remove it.
// ADO:TODO:1153495 - Rekey this map with stable string keys.
Logger.error(TAG, "The command in the map has mutated " + command.getClass().getCanonicalName() + " the calling application was " + command.getParameters().getApplicationName(), null);
cleanMap(command);
}
}
finalFuture.setCleanedUp();
}
DiagnosticContext.clear();
}
}
});
return finalFuture;
}
}
use of com.microsoft.identity.common.internal.commands.parameters.SilentTokenCommandParameters in project microsoft-authentication-library-common-for-android by AzureAD.
the class LocalMSALController method acquireTokenSilent.
@Override
public AcquireTokenResult acquireTokenSilent(@NonNull final SilentTokenCommandParameters parameters) throws IOException, ClientException, ArgumentException, ServiceException {
final String methodName = ":acquireTokenSilent";
Logger.verbose(TAG + methodName, "Acquiring token silently...");
Telemetry.emit(new ApiStartEvent().putProperties(parameters).putApiId(TelemetryEventStrings.Api.LOCAL_ACQUIRE_TOKEN_SILENT));
final AcquireTokenResult acquireTokenSilentResult = new AcquireTokenResult();
// Validate MSAL Parameters
parameters.validate();
// Add default scopes
final Set<String> mergedScopes = addDefaultScopes(parameters);
final SilentTokenCommandParameters parametersWithScopes = parameters.toBuilder().scopes(mergedScopes).build();
@SuppressWarnings(WarningType.rawtype_warning) final OAuth2TokenCache tokenCache = parametersWithScopes.getOAuth2TokenCache();
final AccountRecord targetAccount = getCachedAccountRecord(parametersWithScopes);
// Build up params for Strategy construction
final AbstractAuthenticationScheme authScheme = parametersWithScopes.getAuthenticationScheme();
final OAuth2StrategyParameters strategyParameters = new OAuth2StrategyParameters();
strategyParameters.setContext(parametersWithScopes.getAndroidApplicationContext());
@SuppressWarnings(WarningType.rawtype_warning) final OAuth2Strategy strategy = parametersWithScopes.getAuthority().createOAuth2Strategy(strategyParameters);
// Suppressing unchecked warning of converting List<ICacheRecord> to List due to generic type not provided for tokenCache
@SuppressWarnings(WarningType.unchecked_warning) final List<ICacheRecord> cacheRecords = tokenCache.loadWithAggregatedAccountData(parametersWithScopes.getClientId(), TextUtils.join(" ", parametersWithScopes.getScopes()), targetAccount, authScheme);
// The first element is the 'fully-loaded' CacheRecord which may contain the AccountRecord,
// AccessTokenRecord, RefreshTokenRecord, and IdTokenRecord... (if all of those artifacts exist)
// subsequent CacheRecords represent other profiles (projections) of this principal in
// other tenants. Those tokens will be 'sparse', meaning that their AT/RT will not be loaded
final ICacheRecord fullCacheRecord = cacheRecords.get(0);
if (accessTokenIsNull(fullCacheRecord) || refreshTokenIsNull(fullCacheRecord) || parametersWithScopes.isForceRefresh() || !isRequestAuthorityRealmSameAsATRealm(parametersWithScopes.getAuthority(), fullCacheRecord.getAccessToken()) || !strategy.validateCachedResult(authScheme, fullCacheRecord)) {
if (!refreshTokenIsNull(fullCacheRecord)) {
// No AT found, but the RT checks out, so we'll use it
Logger.verbose(TAG + methodName, "No access token found, but RT is available.");
renewAccessToken(parametersWithScopes, acquireTokenSilentResult, tokenCache, strategy, fullCacheRecord);
} else {
// TODO need the refactor, should just throw the ui required exception, rather than
// wrap the exception later in the exception wrapper.
final ClientException exception = new ClientException(ErrorStrings.NO_TOKENS_FOUND, "No refresh token was found. ");
Telemetry.emit(new ApiEndEvent().putException(exception).putApiId(TelemetryEventStrings.Api.LOCAL_ACQUIRE_TOKEN_SILENT));
throw exception;
}
} else if (fullCacheRecord.getAccessToken().isExpired()) {
Logger.warn(TAG + methodName, "Access token is expired. Removing from cache...");
// Remove the expired token
tokenCache.removeCredential(fullCacheRecord.getAccessToken());
Logger.verbose(TAG + methodName, "Renewing access token...");
// Request a new AT
renewAccessToken(parametersWithScopes, acquireTokenSilentResult, tokenCache, strategy, fullCacheRecord);
} else {
Logger.verbose(TAG + methodName, "Returning silent result");
// the result checks out, return that....
acquireTokenSilentResult.setLocalAuthenticationResult(new LocalAuthenticationResult(finalizeCacheRecordForResult(fullCacheRecord, parametersWithScopes.getAuthenticationScheme()), cacheRecords, SdkType.MSAL, true));
}
Telemetry.emit(new ApiEndEvent().putResult(acquireTokenSilentResult).putApiId(TelemetryEventStrings.Api.LOCAL_ACQUIRE_TOKEN_SILENT));
return acquireTokenSilentResult;
}
use of com.microsoft.identity.common.internal.commands.parameters.SilentTokenCommandParameters in project microsoft-authentication-library-common-for-android by AzureAD.
the class SilentTokenCommand method execute.
@Override
public AcquireTokenResult execute() throws Exception {
AcquireTokenResult result = null;
final String methodName = ":execute";
for (int ii = 0; ii < this.getControllers().size(); ii++) {
final BaseController controller = this.getControllers().get(ii);
try {
com.microsoft.identity.common.internal.logging.Logger.verbose(TAG + methodName, "Executing with controller: " + controller.getClass().getSimpleName());
result = controller.acquireTokenSilent((SilentTokenCommandParameters) getParameters());
if (result.getSucceeded()) {
com.microsoft.identity.common.internal.logging.Logger.verbose(TAG + methodName, "Executing with controller: " + controller.getClass().getSimpleName() + ": Succeeded");
return result;
}
} catch (UiRequiredException | ClientException e) {
if (// was invalid_grant
e.getErrorCode().equals(AuthenticationConstants.OAuth2ErrorCode.INVALID_GRANT) && this.getControllers().size() > ii + 1) {
// isn't the last controller we can try
continue;
} else if ((e.getErrorCode().equals(ErrorStrings.NO_TOKENS_FOUND) || e.getErrorCode().equals(ErrorStrings.NO_ACCOUNT_FOUND)) && this.getControllers().size() > ii + 1) {
// if no token or account for this silent call, we should continue to the next silent call.
continue;
} else {
throw e;
}
}
}
return result;
}
use of com.microsoft.identity.common.internal.commands.parameters.SilentTokenCommandParameters in project microsoft-authentication-library-common-for-android by AzureAD.
the class ApiStartEvent method putProperties.
public ApiStartEvent putProperties(@Nullable final CommandParameters parameters) {
if (parameters == null) {
return this;
}
if (parameters.getSdkType() != null) {
put(Key.SDK_NAME, parameters.getSdkType().name());
}
put(Key.SDK_VERSION, parameters.getSdkVersion());
// Pii
put(Key.REDIRECT_URI, parameters.getRedirectUri());
// Pii
put(Key.CLIENT_ID, parameters.getClientId());
put(Key.BROKER_PROTOCOL_VERSION, String.valueOf(parameters.getRequiredBrokerProtocolVersion()));
if (parameters instanceof TokenCommandParameters) {
final TokenCommandParameters tokenCommandParameters = (TokenCommandParameters) parameters;
final Authority authority = tokenCommandParameters.getAuthority();
if (authority != null) {
if (authority.getAuthorityURL() != null) {
// Pii
put(Key.AUTHORITY, authority.getAuthorityURL().getAuthority());
}
put(Key.AUTHORITY_TYPE, authority.getAuthorityTypeString());
}
put(Key.CLAIM_REQUEST, StringUtil.isEmpty(tokenCommandParameters.getClaimsRequestJson()) ? Value.FALSE : Value.TRUE);
if (tokenCommandParameters.getScopes() != null) {
put(Key.SCOPE_SIZE, String.valueOf(tokenCommandParameters.getScopes().size()));
// Pii
put(Key.SCOPE, tokenCommandParameters.getScopes().toString());
}
final AbstractAuthenticationScheme authScheme = tokenCommandParameters.getAuthenticationScheme();
if (null != authScheme) {
put(Key.AUTHENTICATION_SCHEME, authScheme.getName());
}
}
if (parameters instanceof InteractiveTokenCommandParameters) {
final InteractiveTokenCommandParameters atOperationParameters = (InteractiveTokenCommandParameters) parameters;
if (atOperationParameters.getAuthorizationAgent() != null) {
put(Key.USER_AGENT, atOperationParameters.getAuthorizationAgent().name());
}
put(// Pii
Key.LOGIN_HINT, atOperationParameters.getLoginHint());
if (atOperationParameters.getExtraQueryStringParameters() != null) {
put(// Pii
Key.REQUEST_QUERY_PARAMS, String.valueOf(atOperationParameters.getExtraQueryStringParameters().size()));
}
if (atOperationParameters.getPrompt() != null) {
put(Key.PROMPT_BEHAVIOR, atOperationParameters.getPrompt().toString());
}
}
if (parameters instanceof SilentTokenCommandParameters) {
final SilentTokenCommandParameters silentParameters = (SilentTokenCommandParameters) parameters;
if (silentParameters.getAccount() != null) {
// Pii
put(Key.USER_ID, silentParameters.getAccount().getHomeAccountId());
}
put(Key.IS_FORCE_REFRESH, String.valueOf(silentParameters.isForceRefresh()));
}
if (parameters instanceof BrokerInteractiveTokenCommandParameters) {
// TODO when integrate the telemetry with broker.
}
if (parameters instanceof BrokerSilentTokenCommandParameters) {
// TODO when integrate the telemetry with broker.
}
return this;
}
Aggregations