diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/ApplicationContext.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/ApplicationContext.cs
new file mode 100644
index 00000000000..d316446bae7
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/ApplicationContext.cs
@@ -0,0 +1,53 @@
+/*
+Copyright 2011 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using Google.Apis.Logging;
+using System;
+
+namespace Google
+{
+ /// Defines the context in which this library runs. It allows setting up custom loggers.
+ public static class ApplicationContext
+ {
+ private static ILogger logger;
+
+ // For testing
+ internal static void Reset() => logger = null;
+
+ /// Returns the logger used within this application context.
+ /// It creates a if no logger was registered previously
+ public static ILogger Logger
+ {
+ get
+ {
+ // Register the default null-logger if no other one was set.
+ return logger ?? (logger = new NullLogger());
+ }
+ }
+
+ /// Registers a logger with this application context.
+ /// Thrown if a logger was already registered.
+ public static void RegisterLogger(ILogger loggerToRegister)
+ {
+ // TODO(peleyal): Reconsider why the library should contain only one logger. Also consider using Tracing!
+ if (logger != null && !(logger is NullLogger))
+ {
+ throw new InvalidOperationException("A logger was already registered with this context.");
+ }
+ logger = loggerToRegister;
+ }
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/AuthHttpClientFactory.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/AuthHttpClientFactory.cs
new file mode 100644
index 00000000000..a2f25c28735
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/AuthHttpClientFactory.cs
@@ -0,0 +1,16 @@
+using Google.Apis.Http;
+using System;
+
+namespace Google.Apis.Auth.ExistingDependencies;
+
+///
+/// Default implementation of IHttpClientFactory just for auth.
+/// Avoids us requiring the full HttpClientFactory.
+///
+internal class AuthHttpClientFactory : IHttpClientFactory
+{
+ public ConfigurableHttpClient CreateHttpClient(CreateHttpClientArgs args)
+ {
+ throw new NotImplementedException();
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/BackOffHandler.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/BackOffHandler.cs
new file mode 100644
index 00000000000..dc12abfa7dd
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/BackOffHandler.cs
@@ -0,0 +1,186 @@
+/*
+Copyright 2013 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Google.Apis.Logging;
+using Google.Apis.Util;
+
+namespace Google.Apis.Http
+{
+ ///
+ /// A thread-safe back-off handler which handles an abnormal HTTP response or an exception with
+ /// .
+ ///
+ public class BackOffHandler : IHttpUnsuccessfulResponseHandler, IHttpExceptionHandler
+ {
+ private static readonly ILogger Logger = ApplicationContext.Logger.ForType();
+
+ /// An initializer class to initialize a back-off handler.
+ public class Initializer
+ {
+ /// Gets the back-off policy used by this back-off handler.
+ public IBackOff BackOff { get; private set; }
+
+ ///
+ /// Gets or sets the maximum time span to wait. If the back-off instance returns a greater time span than
+ /// this value, this handler returns false to both HandleExceptionAsync and
+ /// HandleResponseAsync. Default value is 16 seconds per a retry request.
+ ///
+ public TimeSpan MaxTimeSpan { get; set; }
+
+ ///
+ /// Gets or sets a delegate function which indicates whether this back-off handler should handle an
+ /// abnormal HTTP response. The default is .
+ ///
+ public Func HandleUnsuccessfulResponseFunc { get; set; }
+
+ ///
+ /// Gets or sets a delegate function which indicates whether this back-off handler should handle an
+ /// exception. The default is .
+ ///
+ public Func HandleExceptionFunc { get; set; }
+
+ /// Default function which handles server errors (503).
+ public static readonly Func DefaultHandleUnsuccessfulResponseFunc =
+ (r) => (int)r.StatusCode == 503;
+
+ ///
+ /// Default function which handles exception which aren't
+ /// or
+ /// . Those exceptions represent a task or an operation
+ /// which was canceled and shouldn't be retried.
+ ///
+ public static readonly Func DefaultHandleExceptionFunc =
+ (ex) => !(ex is TaskCanceledException || ex is OperationCanceledException);
+
+ /// Constructs a new initializer by the given back-off.
+ public Initializer(IBackOff backOff)
+ {
+ BackOff = backOff;
+ HandleExceptionFunc = DefaultHandleExceptionFunc;
+ HandleUnsuccessfulResponseFunc = DefaultHandleUnsuccessfulResponseFunc;
+ MaxTimeSpan = TimeSpan.FromSeconds(16);
+ }
+ }
+
+ /// Gets the back-off policy used by this back-off handler.
+ public IBackOff BackOff { get; private set; }
+
+ ///
+ /// Gets the maximum time span to wait. If the back-off instance returns a greater time span, the handle method
+ /// returns false. Default value is 16 seconds per a retry request.
+ ///
+ public TimeSpan MaxTimeSpan { get; private set; }
+
+ ///
+ /// Gets a delegate function which indicates whether this back-off handler should handle an abnormal HTTP
+ /// response. The default is .
+ ///
+ public Func HandleUnsuccessfulResponseFunc { get; private set; }
+
+ ///
+ /// Gets a delegate function which indicates whether this back-off handler should handle an exception. The
+ /// default is .
+ ///
+ public Func HandleExceptionFunc { get; private set; }
+
+ /// Constructs a new back-off handler with the given back-off.
+ /// The back-off policy.
+ public BackOffHandler(IBackOff backOff)
+ : this(new Initializer(backOff))
+ {
+ }
+
+ /// Constructs a new back-off handler with the given initializer.
+ public BackOffHandler(Initializer initializer)
+ {
+ BackOff = initializer.BackOff;
+ MaxTimeSpan = initializer.MaxTimeSpan;
+ HandleExceptionFunc = initializer.HandleExceptionFunc;
+ HandleUnsuccessfulResponseFunc = initializer.HandleUnsuccessfulResponseFunc;
+ }
+
+ #region IHttpUnsuccessfulResponseHandler
+
+ ///
+ public virtual async Task HandleResponseAsync(HandleUnsuccessfulResponseArgs args)
+ {
+ // if the func returns true try to handle this current failed try
+ if (HandleUnsuccessfulResponseFunc != null && HandleUnsuccessfulResponseFunc(args.Response))
+ {
+ return await HandleAsync(args.SupportsRetry, args.CurrentFailedTry, args.CancellationToken)
+ .ConfigureAwait(false);
+ }
+ return false;
+ }
+
+ #endregion
+
+ #region IHttpExceptionHandler
+
+ ///
+ public virtual async Task HandleExceptionAsync(HandleExceptionArgs args)
+ {
+ // if the func returns true try to handle this current failed try
+ if (HandleExceptionFunc != null && HandleExceptionFunc(args.Exception))
+ {
+ return await HandleAsync(args.SupportsRetry, args.CurrentFailedTry, args.CancellationToken)
+ .ConfigureAwait(false);
+ }
+ return false;
+ }
+
+ #endregion
+
+ ///
+ /// Handles back-off. In case the request doesn't support retry or the back-off time span is greater than the
+ /// maximum time span allowed for a request, the handler returns false. Otherwise the current thread
+ /// will block for x milliseconds (x is defined by the instance), and this handler
+ /// returns true.
+ ///
+ private async Task HandleAsync(bool supportsRetry, int currentFailedTry,
+ CancellationToken cancellationToken)
+ {
+ if (!supportsRetry || BackOff.MaxNumOfRetries < currentFailedTry)
+ {
+ return false;
+ }
+
+ TimeSpan ts = BackOff.GetNextBackOff(currentFailedTry);
+ if (ts > MaxTimeSpan || ts < TimeSpan.Zero)
+ {
+ return false;
+ }
+
+ await Wait(ts, cancellationToken).ConfigureAwait(false);
+ Logger.Debug("Back-Off handled the error. Waited {0}ms before next retry...", ts.TotalMilliseconds);
+ return true;
+ }
+
+ /// Waits the given time span. Overriding this method is recommended for mocking purposes.
+ /// TimeSpan to wait (and block the current thread).
+ /// The cancellation token in case the user wants to cancel the operation in
+ /// the middle.
+ protected virtual async Task Wait(TimeSpan ts, CancellationToken cancellationToken)
+ {
+ await Task.Delay(ts, cancellationToken).ConfigureAwait(false);
+ }
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/ConfigurableHttpClient.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/ConfigurableHttpClient.cs
new file mode 100644
index 00000000000..ed84068e722
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/ConfigurableHttpClient.cs
@@ -0,0 +1,50 @@
+/*
+Copyright 2013 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System.Net.Http;
+
+namespace Google.Apis.Http
+{
+ ///
+ /// Configurable HTTP client inherits from and contains a reference to
+ /// .
+ ///
+ public class ConfigurableHttpClient : HttpClient
+ {
+ /// Gets the configurable message handler.
+ public ConfigurableMessageHandler MessageHandler { get; private set; }
+
+ /// Constructs a new HTTP client.
+ /// This is equivalent to calling ConfigurableHttpClient(handler, true)
+ public ConfigurableHttpClient(ConfigurableMessageHandler handler)
+ : this(handler, true)
+ {
+ }
+
+ ///
+ /// Constructs a new HTTP client.
+ ///
+ /// The handler for this client to use.
+ /// Whether the created
+ /// should dispose of the internal message handler or not when it iself is disposed.
+ public ConfigurableHttpClient(ConfigurableMessageHandler handler, bool disposeHandler)
+ : base (handler, disposeHandler)
+ {
+ MessageHandler = handler;
+ DefaultRequestHeaders.ExpectContinue = false;
+ }
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/ConfigurableMessageHandler.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/ConfigurableMessageHandler.cs
new file mode 100644
index 00000000000..cc12532d571
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/ConfigurableMessageHandler.cs
@@ -0,0 +1,713 @@
+/*
+Copyright 2013 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Google.Apis.Logging;
+using Google.Apis.Testing;
+using System.Net.Http.Headers;
+
+namespace Google.Apis.Http
+{
+ ///
+ /// A message handler which contains the main logic of our HTTP requests. It contains a list of
+ /// s for handling abnormal responses, a list of
+ /// s for handling exception in a request and a list of
+ /// s for intercepting a request before it has been sent to the server.
+ /// It also contains important properties like number of tries, follow redirect, etc.
+ ///
+ public class ConfigurableMessageHandler : DelegatingHandler
+ {
+ private const string QuotaProjectHeaderName = "x-goog-user-project";
+
+ /// The class logger.
+ private static readonly ILogger Logger = ApplicationContext.Logger.ForType();
+
+ /// Maximum allowed number of tries.
+ [VisibleForTestOnly]
+ public const int MaxAllowedNumTries = 20;
+
+ ///
+ /// Key for unsuccessful response handlers in an properties.
+ ///
+ public const string UnsuccessfulResponseHandlerKey = "__UnsuccessfulResponseHandlerKey";
+
+ ///
+ /// Key for exception handlers in an properties.
+ ///
+ public const string ExceptionHandlerKey = "__ExceptionHandlerKey";
+
+ ///
+ /// Key for execute handlers in an properties.
+ ///
+ public const string ExecuteInterceptorKey = "__ExecuteInterceptorKey";
+
+ ///
+ /// Key for a stream response interceptor provider in an properties.
+ ///
+ public const string ResponseStreamInterceptorProviderKey = "__ResponseStreamInterceptorProviderKey";
+
+ ///
+ /// Key for a credential in a properties.
+ ///
+ public const string CredentialKey = "__CredentialKey";
+
+ ///
+ /// Key for request specific max retries.
+ ///
+ public const string MaxRetriesKey = "__MaxRetriesKey";
+
+ /// The current API version of this client library.
+ private static readonly string ApiVersion = Google.Apis.Util.Utilities.GetLibraryVersion();
+
+ /// The User-Agent suffix header which contains the .
+ private static readonly string UserAgentSuffix = "google-api-dotnet-client/" + ApiVersion + " (gzip)";
+
+ #region IHttpUnsuccessfulResponseHandler, IHttpExceptionHandler and IHttpExecuteInterceptor lists
+
+ #region Lock objects
+
+ // The following lock objects are used to lock the list of handlers and interceptors in order to be able to
+ // iterate over them from several threads and to keep this class thread-safe.
+ private readonly object unsuccessfulResponseHandlersLock = new object();
+ private readonly object exceptionHandlersLock = new object();
+ private readonly object executeInterceptorsLock = new object();
+
+ #endregion
+
+ /// A list of .
+ private readonly IList unsuccessfulResponseHandlers =
+ new List();
+
+ /// A list of .
+ private readonly IList exceptionHandlers =
+ new List();
+
+ /// A list of .
+ private readonly IList executeInterceptors =
+ new List();
+
+ ///
+ /// Gets a list of s.
+ ///
+ /// Since version 1.10, and
+ /// were added in order to keep this class thread-safe.
+ /// More information is available on
+ /// #592.
+ ///
+ ///
+ [Obsolete("Use AddUnsuccessfulResponseHandler or RemoveUnsuccessfulResponseHandler instead.")]
+ public IList UnsuccessfulResponseHandlers
+ {
+ get { return unsuccessfulResponseHandlers; }
+ }
+
+ /// Adds the specified handler to the list of unsuccessful response handlers.
+ public void AddUnsuccessfulResponseHandler(IHttpUnsuccessfulResponseHandler handler)
+ {
+ lock (unsuccessfulResponseHandlersLock)
+ {
+ unsuccessfulResponseHandlers.Add(handler);
+ }
+ }
+
+ /// Removes the specified handler from the list of unsuccessful response handlers.
+ public void RemoveUnsuccessfulResponseHandler(IHttpUnsuccessfulResponseHandler handler)
+ {
+ lock (unsuccessfulResponseHandlersLock)
+ {
+ unsuccessfulResponseHandlers.Remove(handler);
+ }
+ }
+
+ ///
+ /// Gets a list of s.
+ ///
+ /// Since version 1.10, and were added
+ /// in order to keep this class thread-safe. More information is available on
+ /// #592.
+ ///
+ ///
+ [Obsolete("Use AddExceptionHandler or RemoveExceptionHandler instead.")]
+ public IList ExceptionHandlers
+ {
+ get { return exceptionHandlers; }
+ }
+
+ /// Adds the specified handler to the list of exception handlers.
+ public void AddExceptionHandler(IHttpExceptionHandler handler)
+ {
+ lock (exceptionHandlersLock)
+ {
+ exceptionHandlers.Add(handler);
+ }
+ }
+
+ /// Removes the specified handler from the list of exception handlers.
+ public void RemoveExceptionHandler(IHttpExceptionHandler handler)
+ {
+ lock (exceptionHandlersLock)
+ {
+ exceptionHandlers.Remove(handler);
+ }
+ }
+
+ ///
+ /// Gets a list of s.
+ ///
+ /// Since version 1.10, and were
+ /// added in order to keep this class thread-safe. More information is available on
+ /// #592.
+ ///
+ ///
+ [Obsolete("Use AddExecuteInterceptor or RemoveExecuteInterceptor instead.")]
+ public IList ExecuteInterceptors
+ {
+ get { return executeInterceptors; }
+ }
+
+ /// Adds the specified interceptor to the list of execute interceptors.
+ public void AddExecuteInterceptor(IHttpExecuteInterceptor interceptor)
+ {
+ lock (executeInterceptorsLock)
+ {
+ executeInterceptors.Add(interceptor);
+ }
+ }
+
+ /// Removes the specified interceptor from the list of execute interceptors.
+ public void RemoveExecuteInterceptor(IHttpExecuteInterceptor interceptor)
+ {
+ lock (executeInterceptorsLock)
+ {
+ executeInterceptors.Remove(interceptor);
+ }
+ }
+
+ #endregion
+
+ private int _loggingRequestId = 0;
+
+ private ILogger _instanceLogger = Logger;
+
+ ///
+ /// For testing only.
+ /// This defaults to the static , but can be overridden for fine-grain testing.
+ ///
+ internal ILogger InstanceLogger
+ {
+ get { return _instanceLogger; }
+ set { _instanceLogger = value.ForType(); }
+ }
+
+ /// Number of tries. Default is 3.
+ private int numTries = 3;
+
+ ///
+ /// Gets or sets the number of tries that will be allowed to execute. Retries occur as a result of either
+ /// or which handles the
+ /// abnormal HTTP response or exception before being terminated.
+ /// Set 1 for not retrying requests. The default value is 3.
+ ///
+ /// The number of allowed redirects (3xx) is defined by . This property defines
+ /// only the allowed tries for >=400 responses, or when an exception is thrown. For example if you set
+ /// to 1 and to 5, the library will send up to five redirect
+ /// requests, but will not send any retry requests due to an error HTTP status code.
+ ///
+ ///
+ public int NumTries
+ {
+ get { return numTries; }
+ set
+ {
+ if (value > MaxAllowedNumTries || value < 1)
+ {
+ throw new ArgumentOutOfRangeException("NumTries");
+ }
+ numTries = value;
+ }
+ }
+
+ /// Number of redirects allowed. Default is 10.
+ private int numRedirects = 10;
+
+ ///
+ /// Gets or sets the number of redirects that will be allowed to execute. The default value is 10.
+ /// See for more information.
+ ///
+ public int NumRedirects
+ {
+ get { return numRedirects; }
+ set
+ {
+ if (value > MaxAllowedNumTries || value < 1)
+ {
+ throw new ArgumentOutOfRangeException("NumRedirects");
+ }
+ numRedirects = value;
+ }
+ }
+
+ ///
+ /// Gets or sets whether the handler should follow a redirect when a redirect response is received. Default
+ /// value is true.
+ ///
+ public bool FollowRedirect { get; set; }
+
+ /// Gets or sets whether logging is enabled. Default value is true.
+ public bool IsLoggingEnabled { get; set; }
+
+ ///
+ /// Specifies the type(s) of request/response events to log.
+ ///
+ [Flags]
+ public enum LogEventType
+ {
+ ///
+ /// Log no request/response information.
+ ///
+ None = 0,
+
+ ///
+ /// Log the request URI.
+ ///
+ RequestUri = 1,
+
+ ///
+ /// Log the request headers.
+ ///
+ RequestHeaders = 2,
+
+ ///
+ /// Log the request body. The body is assumed to be ASCII, and non-printable charaters are replaced by '.'.
+ /// Warning: This causes the body content to be buffered in memory, so use with care for large requests.
+ ///
+ RequestBody = 4,
+
+ ///
+ /// Log the response status.
+ ///
+ ResponseStatus = 8,
+
+ ///
+ /// Log the response headers.
+ ///
+ ResponseHeaders = 16,
+
+ ///
+ /// Log the response body. The body is assumed to be ASCII, and non-printable characters are replaced by '.'.
+ /// Warning: This causes the body content to be buffered in memory, so use with care for large responses.
+ ///
+ ResponseBody = 32,
+
+ ///
+ /// Log abnormal response messages.
+ ///
+ ResponseAbnormal = 64,
+ }
+
+ ///
+ /// The request/response types to log.
+ ///
+ public LogEventType LogEvents { get; set; }
+
+ /// Gets or sets the application name which will be used on the User-Agent header.
+ public string ApplicationName { get; set; }
+
+ /// Gets or sets the value set for the x-goog-api-client header.
+ public string GoogleApiClientHeader { get; set; }
+
+ ///
+ /// The credential to apply to all requests made with this client,
+ /// unless theres a specific call credential set.
+ /// If implements
+ /// then it will also be included as a handler of an unsuccessful response.
+ ///
+ public IHttpExecuteInterceptor Credential { get; set; }
+
+ /// Constructs a new configurable message handler.
+ public ConfigurableMessageHandler(HttpMessageHandler httpMessageHandler)
+ : base(httpMessageHandler)
+ {
+ // set default values
+ FollowRedirect = true;
+ IsLoggingEnabled = true;
+ LogEvents = LogEventType.RequestUri | LogEventType.ResponseStatus | LogEventType.ResponseAbnormal;
+ }
+
+ private void LogHeaders(string initialText, HttpHeaders headers1, HttpHeaders headers2)
+ {
+ var headers = (headers1 ?? Enumerable.Empty>>())
+ .Concat(headers2 ?? Enumerable.Empty>>()).ToList();
+ var args = new object[headers.Count * 2];
+ var fmt = new StringBuilder(headers.Count * 32);
+ fmt.Append(initialText);
+ var argBuilder = new StringBuilder();
+ for (int i = 0; i < headers.Count; i++)
+ {
+ fmt.Append($"\n [{{{i * 2}}}] '{{{1 + i * 2}}}'");
+ args[i * 2] = headers[i].Key;
+ argBuilder.Clear();
+ args[1 + i * 2] = string.Join("; ", headers[i].Value);
+ }
+ InstanceLogger.Debug(fmt.ToString(), args);
+ }
+
+ private async Task LogBody(string fmtText, HttpContent content)
+ {
+ // This buffers the body content within the HttpContent if required.
+ var bodyBytes = content != null ? await content.ReadAsByteArrayAsync().ConfigureAwait(false) : new byte[0];
+ char[] bodyChars = new char[bodyBytes.Length];
+ for (int i = 0; i < bodyBytes.Length; i++)
+ {
+ var b = bodyBytes[i];
+ bodyChars[i] = b >= 32 && b <= 126 ? (char)b : '.';
+ }
+ InstanceLogger.Debug(fmtText, new string(bodyChars));
+ }
+
+ ///
+ /// The main logic of sending a request to the server. This send method adds the User-Agent header to a request
+ /// with and the library version. It also calls interceptors before each attempt,
+ /// and unsuccessful response handler or exception handlers when abnormal response or exception occurred.
+ ///
+ protected override async Task SendAsync(HttpRequestMessage request,
+ CancellationToken cancellationToken)
+ {
+ var loggable = IsLoggingEnabled && InstanceLogger.IsDebugEnabled;
+ string loggingRequestId = "";
+ if (loggable)
+ {
+ loggingRequestId = Interlocked.Increment(ref _loggingRequestId).ToString("X8");
+ }
+
+ int maxRetries = GetEffectiveMaxRetries(request);
+ int triesRemaining = maxRetries;
+ int redirectRemaining = NumRedirects;
+
+ Exception lastException = null;
+
+ // Set User-Agent header.
+ var userAgent = (ApplicationName == null ? "" : ApplicationName + " ") + UserAgentSuffix;
+ // TODO: setting the User-Agent won't work on Silverlight. We may need to create a special callback here to
+ // set it correctly.
+ request.Headers.Add("User-Agent", userAgent);
+ var apiClientHeader = GoogleApiClientHeader;
+ if (apiClientHeader != null)
+ {
+ request.Headers.Add("x-goog-api-client", apiClientHeader);
+ }
+
+ HttpResponseMessage response = null;
+ do // While (triesRemaining > 0)
+ {
+ response?.Dispose();
+ response = null;
+ lastException = null;
+
+ // Check after previous response (if any) has been disposed of.
+ cancellationToken.ThrowIfCancellationRequested();
+
+ // We keep a local list of the interceptors, since we can't call await inside lock.
+ List interceptors;
+ lock (executeInterceptorsLock)
+ {
+ interceptors = executeInterceptors.ToList();
+ }
+ if (request.Properties.TryGetValue(ExecuteInterceptorKey, out var interceptorsValue) &&
+ interceptorsValue is List perCallinterceptors)
+ {
+ interceptors.AddRange(perCallinterceptors);
+ }
+
+ // Intercept the request.
+ foreach (var interceptor in interceptors)
+ {
+ await interceptor.InterceptAsync(request, cancellationToken).ConfigureAwait(false);
+ }
+
+ // Before having the credential intercept the call, check that quota project hasn't
+ // been added as a header. Quota project cannot be added except through the credential.
+ CheckValidAfterInterceptors(request);
+
+ await CredentialInterceptAsync(request, cancellationToken).ConfigureAwait(false);
+
+ if (loggable)
+ {
+ if ((LogEvents & LogEventType.RequestUri) != 0)
+ {
+ InstanceLogger.Debug("Request[{0}] (triesRemaining={1}) URI: '{2}'", loggingRequestId, triesRemaining, request.RequestUri);
+ }
+ if ((LogEvents & LogEventType.RequestHeaders) != 0)
+ {
+ LogHeaders($"Request[{loggingRequestId}] Headers:", request.Headers, request.Content?.Headers);
+ }
+ if ((LogEvents & LogEventType.RequestBody) != 0)
+ {
+ await LogBody($"Request[{loggingRequestId}] Body: '{{0}}'", request.Content).ConfigureAwait(false);
+ }
+ }
+ try
+ {
+ // Send the request!
+ response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ lastException = ex;
+ }
+
+ // Decrease the number of retries.
+ if (response == null || ((int)response.StatusCode >= 400 || (int)response.StatusCode < 200))
+ {
+ triesRemaining--;
+ }
+
+ // Exception was thrown, try to handle it.
+ if (response == null)
+ {
+ var exceptionHandled = false;
+
+ // We keep a local list of the handlers, since we can't call await inside lock.
+ List handlers;
+ lock (exceptionHandlersLock)
+ {
+ handlers = exceptionHandlers.ToList();
+ }
+ if (request.Properties.TryGetValue(ExceptionHandlerKey, out var handlersValue) &&
+ handlersValue is List perCallHandlers)
+ {
+ handlers.AddRange(perCallHandlers);
+ }
+
+ // Try to handle the exception with each handler.
+ foreach (var handler in handlers)
+ {
+ exceptionHandled |= await handler.HandleExceptionAsync(new HandleExceptionArgs
+ {
+ Request = request,
+ Exception = lastException,
+ TotalTries = maxRetries,
+ CurrentFailedTry = maxRetries - triesRemaining,
+ CancellationToken = cancellationToken
+ }).ConfigureAwait(false);
+ }
+
+ if (!exceptionHandled)
+ {
+ InstanceLogger.Error(lastException,
+ "Response[{0}] Exception was thrown while executing a HTTP request and it wasn't handled", loggingRequestId);
+ throw lastException;
+ }
+ else if (loggable && (LogEvents & LogEventType.ResponseAbnormal) != 0)
+ {
+ InstanceLogger.Debug("Response[{0}] Exception {1} was thrown, but it was handled by an exception handler",
+ loggingRequestId, lastException.Message);
+ }
+ }
+ else
+ {
+ if (loggable)
+ {
+ if ((LogEvents & LogEventType.ResponseStatus) != 0)
+ {
+ InstanceLogger.Debug("Response[{0}] Response status: {1} '{2}'", loggingRequestId, response.StatusCode, response.ReasonPhrase);
+ }
+ if ((LogEvents & LogEventType.ResponseHeaders) != 0)
+ {
+ LogHeaders($"Response[{loggingRequestId}] Headers:", response.Headers, response.Content?.Headers);
+ }
+ if ((LogEvents & LogEventType.ResponseBody) != 0)
+ {
+ await LogBody($"Response[{loggingRequestId}] Body: '{{0}}'", response.Content).ConfigureAwait(false);
+ }
+ }
+ if (response.IsSuccessStatusCode)
+ {
+ // No need to retry, the response was successful.
+ triesRemaining = 0;
+ }
+ else
+ {
+ bool errorHandled = false;
+
+ // We keep a local list of the handlers, since we can't call await inside lock.
+ List handlers;
+ lock (unsuccessfulResponseHandlersLock)
+ {
+ handlers = unsuccessfulResponseHandlers.ToList();
+ }
+ if (request.Properties.TryGetValue(UnsuccessfulResponseHandlerKey, out var handlersValue) &&
+ handlersValue is List perCallHandlers)
+ {
+ handlers.AddRange(perCallHandlers);
+ }
+
+ var handlerArgs = new HandleUnsuccessfulResponseArgs
+ {
+ Request = request,
+ Response = response,
+ TotalTries = maxRetries,
+ CurrentFailedTry = maxRetries - triesRemaining,
+ CancellationToken = cancellationToken
+ };
+
+ // Try to handle the abnormal HTTP response with each handler.
+ foreach (var handler in handlers)
+ {
+ try
+ {
+ errorHandled |= await handler.HandleResponseAsync(handlerArgs).ConfigureAwait(false);
+ }
+ catch when (DisposeAndReturnFalse(response)) { }
+
+ bool DisposeAndReturnFalse(IDisposable disposable)
+ {
+ disposable.Dispose();
+ return false;
+ }
+ }
+
+ errorHandled |= await CredentialHandleResponseAsync(handlerArgs).ConfigureAwait(false);
+
+ if (!errorHandled)
+ {
+ if (FollowRedirect && HandleRedirect(response))
+ {
+ if (redirectRemaining-- == 0)
+ {
+ triesRemaining = 0;
+ }
+
+ errorHandled = true;
+ if (loggable && (LogEvents & LogEventType.ResponseAbnormal) != 0)
+ {
+ InstanceLogger.Debug("Response[{0}] Redirect response was handled successfully. Redirect to {1}",
+ loggingRequestId, response.Headers.Location);
+ }
+ }
+ else
+ {
+ if (loggable && (LogEvents & LogEventType.ResponseAbnormal) != 0)
+ {
+ InstanceLogger.Debug("Response[{0}] An abnormal response wasn't handled. Status code is {1}",
+ loggingRequestId, response.StatusCode);
+ }
+
+ // No need to retry, because no handler handled the abnormal response.
+ triesRemaining = 0;
+ }
+ }
+ else if (loggable && (LogEvents & LogEventType.ResponseAbnormal) != 0)
+ {
+ InstanceLogger.Debug("Response[{0}] An abnormal response was handled by an unsuccessful response handler. " +
+ "Status Code is {1}", loggingRequestId, response.StatusCode);
+ }
+ }
+ }
+ } while (triesRemaining > 0); // Not a successful status code but it was handled.
+
+ // If the response is null, we should throw the last exception.
+ if (response == null)
+ {
+ InstanceLogger.Error(lastException, "Request[{0}] Exception was thrown while executing a HTTP request", loggingRequestId);
+ throw lastException;
+ }
+ else if (!response.IsSuccessStatusCode && loggable && (LogEvents & LogEventType.ResponseAbnormal) != 0)
+ {
+ InstanceLogger.Debug("Response[{0}] Abnormal response is being returned. Status Code is {1}", loggingRequestId, response.StatusCode);
+ }
+
+ return response;
+ }
+
+ private void CheckValidAfterInterceptors(HttpRequestMessage request)
+ {
+ if (request.Headers.Contains(QuotaProjectHeaderName))
+ {
+ throw new InvalidOperationException($"{QuotaProjectHeaderName} header can only be added through the credential or through the ClientBuilder.");
+ }
+ }
+
+ private async Task CredentialInterceptAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+ {
+ var effectiveCredential = GetEffectiveCredential(request);
+ if (effectiveCredential != null)
+ {
+ await effectiveCredential.InterceptAsync(request, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ private async Task CredentialHandleResponseAsync(HandleUnsuccessfulResponseArgs args)
+ {
+ var effectiveCredential = GetEffectiveCredential(args.Request);
+ if (effectiveCredential is IHttpUnsuccessfulResponseHandler handler)
+ {
+ return await handler.HandleResponseAsync(args).ConfigureAwait(false);
+ }
+
+ return false;
+ }
+
+ private IHttpExecuteInterceptor GetEffectiveCredential(HttpRequestMessage request) =>
+ (request.Properties.TryGetValue(CredentialKey, out var cred) && cred is IHttpExecuteInterceptor callCredential)
+ ? callCredential : Credential;
+
+ private int GetEffectiveMaxRetries(HttpRequestMessage request) =>
+ (request.Properties.TryGetValue(MaxRetriesKey, out var maxRetries) && maxRetries is int perRequestMaxRetries)
+ ? perRequestMaxRetries : NumTries;
+
+ ///
+ /// Handles redirect if the response's status code is redirect, redirects are turned on, and the header has
+ /// a location.
+ /// When the status code is 303 the method on the request is changed to a GET as per the RFC2616
+ /// specification. On a redirect, it also removes the Authorization and all If-* request headers.
+ ///
+ /// Whether this method changed the request and handled redirect successfully.
+ private bool HandleRedirect(HttpResponseMessage message)
+ {
+ // TODO(peleyal): think if it's better to move that code to RedirectUnsucessfulResponseHandler
+ var uri = message.Headers.Location;
+ if (!message.IsRedirectStatusCode() || uri == null)
+ {
+ return false;
+ }
+
+ var request = message.RequestMessage;
+ request.RequestUri = new Uri(request.RequestUri, uri);
+ // Status code for a resource that has moved to a new URI and should be retrieved using GET.
+ if (message.StatusCode == HttpStatusCode.SeeOther)
+ {
+ request.Method = HttpMethod.Get;
+ }
+ // Clear Authorization and If-* headers.
+ request.Headers.Remove("Authorization");
+ request.Headers.IfMatch.Clear();
+ request.Headers.IfNoneMatch.Clear();
+ request.Headers.IfModifiedSince = null;
+ request.Headers.IfUnmodifiedSince = null;
+ request.Headers.Remove("If-Range");
+ return true;
+ }
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/ExponentialBackOff.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/ExponentialBackOff.cs
new file mode 100644
index 00000000000..7160fdf608f
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/ExponentialBackOff.cs
@@ -0,0 +1,99 @@
+/*
+Copyright 2013 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System;
+
+namespace Google.Apis.Util
+{
+ ///
+ /// Implementation of that increases the back-off period for each retry attempt using a
+ /// randomization function that grows exponentially. In addition, it also adds a randomize number of milliseconds
+ /// for each attempt.
+ ///
+ public class ExponentialBackOff : IBackOff
+ {
+ /// The maximum allowed number of retries.
+ private const int MaxAllowedNumRetries = 20;
+
+ private readonly TimeSpan deltaBackOff;
+ ///
+ /// Gets the delta time span used to generate a random milliseconds to add to the next back-off.
+ /// If the value is then the generated back-off will be exactly 1, 2, 4,
+ /// 8, 16, etc. seconds. A valid value is between zero and one second. The default value is 250ms, which means
+ /// that the generated back-off will be [0.75-1.25]sec, [1.75-2.25]sec, [3.75-4.25]sec, and so on.
+ ///
+ public TimeSpan DeltaBackOff
+ {
+ get { return deltaBackOff; }
+ }
+
+ private readonly int maxNumOfRetries;
+ /// Gets the maximum number of retries. Default value is 10.
+ public int MaxNumOfRetries
+ {
+ get { return maxNumOfRetries; }
+ }
+
+ /// The random instance which generates a random number to add the to next back-off.
+ private Random random = new Random();
+
+ /// Constructs a new exponential back-off with default values.
+ public ExponentialBackOff()
+ : this(TimeSpan.FromMilliseconds(250))
+ {
+ }
+
+ /// Constructs a new exponential back-off with the given delta and maximum retries.
+ public ExponentialBackOff(TimeSpan deltaBackOff, int maximumNumOfRetries = 10)
+ {
+ if (deltaBackOff < TimeSpan.Zero || deltaBackOff > TimeSpan.FromSeconds(1))
+ {
+ throw new ArgumentOutOfRangeException("deltaBackOff");
+ }
+ if (maximumNumOfRetries < 0 || maximumNumOfRetries > MaxAllowedNumRetries)
+ {
+ throw new ArgumentOutOfRangeException("deltaBackOff");
+ }
+
+ this.deltaBackOff = deltaBackOff;
+ this.maxNumOfRetries = maximumNumOfRetries;
+ }
+
+ #region IBackOff Members
+
+ ///
+ public TimeSpan GetNextBackOff(int currentRetry)
+ {
+ if (currentRetry <= 0)
+ {
+ throw new ArgumentOutOfRangeException("currentRetry");
+ }
+ if (currentRetry > MaxNumOfRetries)
+ {
+ return TimeSpan.MinValue;
+ }
+
+ // Generate a random number of milliseconds and add it to the current exponential number.
+ var randomMilli = (double)random.Next(
+ (int)(DeltaBackOff.TotalMilliseconds * -1),
+ (int)(DeltaBackOff.TotalMilliseconds * 1));
+ int backOffMilli = (int)(Math.Pow(2.0, (double)currentRetry - 1) * 1000 + randomMilli);
+ return TimeSpan.FromMilliseconds(backOffMilli);
+ }
+
+ #endregion
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/ExponentialBackOffInitializer.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/ExponentialBackOffInitializer.cs
new file mode 100644
index 00000000000..4d6fff2aa8d
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/ExponentialBackOffInitializer.cs
@@ -0,0 +1,80 @@
+/*
+Copyright 2013 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System;
+
+// ExponentialBackOffInitializer could be internal to Google.Apis.Auth (with code duplication).
+// We add it to the AuthorizationCodeFlow and ServiceCredential, but we don't expose it.
+// ExponentialBackOffPolicy is exposed via the DefaultExponentialBackOffPolicy propert in AuthorizationCodeFlow and ExternalAccountCredential.
+
+namespace Google.Apis.Http
+{
+ ///
+ /// Indicates if exponential back-off is used automatically on exceptions in a service requests and \ or when 503
+ /// responses is returned form the server.
+ ///
+ [Flags]
+ public enum ExponentialBackOffPolicy
+ {
+ /// Exponential back-off is disabled.
+ None = 0,
+ /// Exponential back-off is enabled only for exceptions.
+ Exception = 1,
+ /// Exponential back-off is enabled only for 503 HTTP Status code.
+ UnsuccessfulResponse503 = 2
+ }
+
+ ///
+ /// An initializer which adds exponential back-off as exception handler and \ or unsuccessful response handler by
+ /// the given .
+ ///
+ public class ExponentialBackOffInitializer : IConfigurableHttpClientInitializer
+ {
+ /// Gets or sets the used back-off policy.
+ private ExponentialBackOffPolicy Policy { get; set; }
+
+ /// Gets or sets the back-off handler creation function.
+ private Func CreateBackOff { get; set; }
+
+ ///
+ /// Constructs a new back-off initializer with the given policy and back-off handler create function.
+ ///
+ public ExponentialBackOffInitializer(ExponentialBackOffPolicy policy, Func createBackOff)
+ {
+ Policy = policy;
+ CreateBackOff = createBackOff;
+ }
+
+ ///
+ public void Initialize(ConfigurableHttpClient httpClient)
+ {
+ var backOff = CreateBackOff();
+
+ // Add exception handler and \ or unsuccessful response handler.
+ if ((Policy & ExponentialBackOffPolicy.Exception) == ExponentialBackOffPolicy.Exception)
+ {
+ httpClient.MessageHandler.AddExceptionHandler(backOff);
+ }
+
+ if ((Policy & ExponentialBackOffPolicy.UnsuccessfulResponse503) ==
+ ExponentialBackOffPolicy.UnsuccessfulResponse503)
+ {
+ httpClient.MessageHandler.AddUnsuccessfulResponseHandler(backOff);
+ }
+ }
+ }
+
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/GoogleApiException.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/GoogleApiException.cs
new file mode 100644
index 00000000000..7e3c3e064bd
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/GoogleApiException.cs
@@ -0,0 +1,103 @@
+/*
+Copyright 2010 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Note: the only reference to this is in ServiceAccountCredential. If we throw a different exception,
+// e.g. InvalidOperationException, we could remove GoogleApiException, SingleError and RequestError.
+
+using System;
+using System.Net;
+
+using Google.Apis.Requests;
+using Google.Apis.Util;
+
+namespace Google
+{
+ /// Represents an exception thrown by an API Service.
+ public class GoogleApiException : Exception
+ {
+ private readonly bool _hasMessage;
+
+ /// Gets the service name which related to this exception.
+ public string ServiceName { get; }
+
+ /// Creates an API Service exception.
+ public GoogleApiException(string serviceName, string message, Exception inner)
+ : base(message, inner)
+ {
+ ServiceName = serviceName.ThrowIfNull(nameof(serviceName));
+ _hasMessage = message is object;
+ }
+
+ /// Creates an API Service exception.
+ public GoogleApiException(string serviceName, string message) : this(serviceName, message, null)
+ { }
+
+ ///
+ /// Creates an API Service exception with no message.
+ ///
+ ///
+ /// may still contain useful information if the
+ /// and/or properties are set.
+ ///
+ public GoogleApiException(string serviceName) : this(serviceName, null, null)
+ { }
+
+ /// The Error which was returned from the server, or null if unavailable.
+ public RequestError Error { get; set; }
+
+ private string ErrorMessage =>
+ Error?.Message ?? "No error message was specified.";
+
+ private string ContentMessage =>
+ Error is null
+ ? "No error details were specified."
+ : (Error.IsOnlyRawContent
+ ? $"No JSON error details were specified.{Environment.NewLine}" +
+ (string.IsNullOrWhiteSpace(Error.ErrorResponseContent)
+ ? "Raw error details are empty or white spaces only."
+ : $"Raw error details are: {Error.ErrorResponseContent}")
+ : $"{Error}");
+
+ /// The HTTP status code which was returned along with this error, or 0 if unavailable.
+ public HttpStatusCode HttpStatusCode { get; set; }
+
+ private string HttpStatusCodeMessage =>
+ HttpStatusCode > 0
+ ? $"HttpStatusCode is {HttpStatusCode}."
+ : "No HttpStatusCode was specified.";
+
+ private string ServiceNameMessage => $"The service {ServiceName} has thrown an exception.";
+
+ private string CombinedMessage => $"{ServiceNameMessage} {HttpStatusCodeMessage} {ErrorMessage}";
+
+ ///
+ public override string Message =>
+ // We just override the default message which is very generic in Exception
+ _hasMessage ? base.Message : CombinedMessage;
+
+ ///
+ /// Returns a summary of this exception.
+ ///
+ /// A summary of this exception.
+ public override string ToString() =>
+ // base.ToString() prints Message, and if we have overwritten Message with DefaultMessage
+ // then ToString() will contain some duplicate information. But that's OK.
+ $"{ServiceNameMessage}{Environment.NewLine}" +
+ $"{HttpStatusCodeMessage}{Environment.NewLine}" +
+ $"{ContentMessage}{Environment.NewLine}" +
+ $"{base.ToString()}";
+ }
+}
\ No newline at end of file
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/HttpExtenstions.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/HttpExtenstions.cs
new file mode 100644
index 00000000000..461f2ba1e62
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/HttpExtenstions.cs
@@ -0,0 +1,43 @@
+/*
+Copyright 2013 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System.Net;
+using System.Net.Http;
+
+namespace Google.Apis.Http
+{
+ ///
+ /// Extension methods to and
+ /// .
+ ///
+ internal static class HttpExtensions
+ {
+ /// Returns true if the response contains one of the redirect status codes.
+ internal static bool IsRedirectStatusCode(this HttpResponseMessage message)
+ {
+ switch (message.StatusCode)
+ {
+ case HttpStatusCode.Moved:
+ case HttpStatusCode.Redirect:
+ case HttpStatusCode.RedirectMethod:
+ case HttpStatusCode.TemporaryRedirect:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/IBackOff.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/IBackOff.cs
new file mode 100644
index 00000000000..32528c4bae4
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/IBackOff.cs
@@ -0,0 +1,33 @@
+/*
+Copyright 2013 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System;
+
+namespace Google.Apis.Util
+{
+ /// Strategy interface to control back-off between retry attempts.
+ public interface IBackOff
+ {
+ ///
+ /// Gets the a time span to wait before next retry. If the current retry reached the maximum number of retries,
+ /// the returned value is .
+ ///
+ TimeSpan GetNextBackOff(int currentRetry);
+
+ /// Gets the maximum number of retries.
+ int MaxNumOfRetries { get; }
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/IClock.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/IClock.cs
new file mode 100644
index 00000000000..6848b0c1514
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/IClock.cs
@@ -0,0 +1,56 @@
+/*
+Copyright 2013 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System;
+
+namespace Google.Apis.Util
+{
+ /// Clock wrapper for getting the current time.
+ public interface IClock
+ {
+ ///
+ /// Gets a object that is set to the current date and time on this computer,
+ /// expressed as the local time.
+ ///
+ [Obsolete("System local time is almost always inappropriate to use. If you really need this, call UtcNow and then call ToLocalTime on the result")]
+ DateTime Now { get; }
+
+ ///
+ /// Gets a object that is set to the current date and time on this computer,
+ /// expressed as UTC time.
+ ///
+ DateTime UtcNow { get; }
+ }
+
+ ///
+ /// A default clock implementation that wraps the
+ /// and properties.
+ ///
+ public class SystemClock : IClock
+ {
+ /// Constructs a new system clock.
+ protected SystemClock() { }
+
+ /// The default instance.
+ public static readonly IClock Default = new SystemClock();
+
+ ///
+ public DateTime Now => DateTime.Now;
+
+ ///
+ public DateTime UtcNow => DateTime.UtcNow;
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/IConfigurableHttpClientInitializer.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/IConfigurableHttpClientInitializer.cs
new file mode 100644
index 00000000000..96eb729beed
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/IConfigurableHttpClientInitializer.cs
@@ -0,0 +1,33 @@
+/*
+Copyright 2013 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Google.Apis.Http
+{
+ ///
+ /// HTTP client initializer for changing the default behavior of HTTP client.
+ /// Use this initializer to change default values like timeout and number of tries.
+ ///
+ public interface IConfigurableHttpClientInitializer
+ {
+ /// Initializes a HTTP client after it was created.
+ void Initialize(ConfigurableHttpClient httpClient);
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/ICredentialedRequest.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/ICredentialedRequest.cs
new file mode 100644
index 00000000000..67c58f8f7d9
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/ICredentialedRequest.cs
@@ -0,0 +1,17 @@
+using Google.Apis.Http;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Google.Apis.Auth.ExistingDependencies;
+
+///
+/// TODO: Document this.
+///
+public interface ICredentialedRequest
+{
+ ///
+ /// Credential to use for this request.
+ ///
+ public IHttpExecuteInterceptor Credential { get; set; }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/IDataStore.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/IDataStore.cs
new file mode 100644
index 00000000000..6e440bd2923
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/IDataStore.cs
@@ -0,0 +1,53 @@
+/*
+Copyright 2013 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System;
+using System.Threading.Tasks;
+
+namespace Google.Apis.Util.Store
+{
+ ///
+ /// Stores and manages data objects, where the key is a string and the value is an object.
+ ///
+ /// null keys are not allowed.
+ ///
+ ///
+ public interface IDataStore
+ {
+ /// Asynchronously stores the given value for the given key (replacing any existing value).
+ /// The type to store in the data store.
+ /// The key.
+ /// The value to store.
+ Task StoreAsync(string key, T value);
+
+ ///
+ /// Asynchronously deletes the given key. The type is provided here as well because the "real" saved key should
+ /// contain type information as well, so the data store will be able to store the same key for different types.
+ ///
+ /// The type to delete from the data store.
+ /// The key to delete.
+ Task DeleteAsync(string key);
+
+ /// Asynchronously returns the stored value for the given key or null if not found.
+ /// The type to retrieve from the data store.
+ /// The key to retrieve its value.
+ /// The stored object.
+ Task GetAsync(string key);
+
+ /// Asynchronously clears all values in the data store.
+ Task ClearAsync();
+ }
+}
\ No newline at end of file
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/IHttpClientFactory.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/IHttpClientFactory.cs
new file mode 100644
index 00000000000..f1cad0dc81a
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/IHttpClientFactory.cs
@@ -0,0 +1,53 @@
+/*
+Copyright 2013 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System.Collections.Generic;
+
+// TODO: Remove entirely for the sake of
+
+namespace Google.Apis.Http
+{
+ /// Arguments for creating a HTTP client.
+ public class CreateHttpClientArgs
+ {
+ /// Gets or sets whether GZip is enabled.
+ public bool GZipEnabled { get; set; }
+
+ /// Gets or sets the application name that is sent in the User-Agent header.
+ public string ApplicationName { get; set; }
+
+ /// Gets a list of initializers to initialize the HTTP client instance.
+ public IList Initializers { get; private set; }
+
+ /// Gets or sets the value for the x-goog-api-client header
+ public string GoogleApiClientHeader { get; set; }
+
+ /// Constructs a new argument instance.
+ public CreateHttpClientArgs()
+ {
+ Initializers = new List();
+ }
+ }
+
+ ///
+ /// HTTP client factory creates configurable HTTP clients. A unique HTTP client should be created for each service.
+ ///
+ public interface IHttpClientFactory
+ {
+ /// Creates a new configurable HTTP client.
+ ConfigurableHttpClient CreateHttpClient(CreateHttpClientArgs args);
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/IHttpExceptionHandler.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/IHttpExceptionHandler.cs
new file mode 100644
index 00000000000..2ad9cf11502
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/IHttpExceptionHandler.cs
@@ -0,0 +1,63 @@
+/*
+Copyright 2013 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Google.Apis.Http
+{
+ /// Argument class to .
+ public class HandleExceptionArgs
+ {
+ /// Gets or sets the sent request.
+ public HttpRequestMessage Request { get; set; }
+
+ /// Gets or sets the exception which occurred during sending the request.
+ public Exception Exception { get; set; }
+
+ /// Gets or sets the total number of tries to send the request.
+ public int TotalTries { get; set; }
+
+ /// Gets or sets the current failed try.
+ public int CurrentFailedTry { get; set; }
+
+ /// Gets an indication whether a retry will occur if the handler returns true.
+ public bool SupportsRetry
+ {
+ get { return TotalTries - CurrentFailedTry > 0; }
+ }
+
+ /// Gets or sets the request's cancellation token.
+ public CancellationToken CancellationToken { get; set; }
+ }
+
+ /// Exception handler is invoked when an exception is thrown during a HTTP request.
+ public interface IHttpExceptionHandler
+ {
+ ///
+ /// Handles an exception thrown when sending a HTTP request.
+ /// A simple rule must be followed, if you modify the request object in a way that the exception can be
+ /// resolved, you must return true.
+ ///
+ ///
+ /// Handle exception argument which properties such as the request, exception, current failed try.
+ ///
+ /// Whether this handler has made a change that requires the request to be resent.
+ Task HandleExceptionAsync(HandleExceptionArgs args);
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/IHttpExecuteInterceptor.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/IHttpExecuteInterceptor.cs
new file mode 100644
index 00000000000..3ffcbaa4080
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/IHttpExecuteInterceptor.cs
@@ -0,0 +1,36 @@
+/*
+Copyright 2013 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Google.Apis.Http
+{
+ ///
+ /// HTTP request execute interceptor to intercept a before it has
+ /// been sent. Sample usage is attaching "Authorization" header to a request.
+ ///
+ public interface IHttpExecuteInterceptor
+ {
+ ///
+ /// Invoked before the request is being sent.
+ ///
+ /// The HTTP request message.
+ /// Cancellation token to cancel the operation.
+ Task InterceptAsync(HttpRequestMessage request, CancellationToken cancellationToken);
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/IHttpUnsuccessfulResponseHandler.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/IHttpUnsuccessfulResponseHandler.cs
new file mode 100644
index 00000000000..3c0b9a11347
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/IHttpUnsuccessfulResponseHandler.cs
@@ -0,0 +1,65 @@
+/*
+Copyright 2013 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Google.Apis.Http
+{
+ /// Argument class to .
+ public class HandleUnsuccessfulResponseArgs
+ {
+ /// Gets or sets the sent request.
+ public HttpRequestMessage Request { get; set; }
+
+ /// Gets or sets the abnormal response.
+ public HttpResponseMessage Response { get; set; }
+
+ /// Gets or sets the total number of tries to send the request.
+ public int TotalTries { get; set; }
+
+ /// Gets or sets the current failed try.
+ public int CurrentFailedTry { get; set; }
+
+ /// Gets an indication whether a retry will occur if the handler returns true.
+ public bool SupportsRetry
+ {
+ get { return TotalTries - CurrentFailedTry > 0; }
+ }
+
+ /// Gets or sets the request's cancellation token.
+ public CancellationToken CancellationToken { get; set; }
+ }
+
+ ///
+ /// Unsuccessful response handler which is invoked when an abnormal HTTP response is returned when sending a HTTP
+ /// request.
+ ///
+ public interface IHttpUnsuccessfulResponseHandler
+ {
+ ///
+ /// Handles an abnormal response when sending a HTTP request.
+ /// A simple rule must be followed, if you modify the request object in a way that the abnormal response can
+ /// be resolved, you must return true.
+ ///
+ ///
+ /// Handle response argument which contains properties such as the request, response, current failed try.
+ ///
+ /// Whether this handler has made a change that requires the request to be resent.
+ Task HandleResponseAsync(HandleUnsuccessfulResponseArgs args);
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/ILogger.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/ILogger.cs
new file mode 100644
index 00000000000..dbdbbd2d8e5
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/ILogger.cs
@@ -0,0 +1,62 @@
+/*
+Copyright 2011 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System;
+
+namespace Google.Apis.Logging
+{
+ /// Describes a logging interface which is used for outputting messages.
+ public interface ILogger
+ {
+ /// Gets an indication whether debug output is logged or not.
+ bool IsDebugEnabled { get; }
+
+ /// Returns a logger which will be associated with the specified type.
+ /// Type to which this logger belongs.
+ /// A type-associated logger.
+ ILogger ForType(Type type);
+
+ /// Returns a logger which will be associated with the specified type.
+ /// A type-associated logger.
+ ILogger ForType();
+
+ /// Logs a debug message.
+ /// The message to log.
+ /// String.Format arguments (if applicable).
+ void Debug(string message, params object[] formatArgs);
+
+ /// Logs an info message.
+ /// The message to log.
+ /// String.Format arguments (if applicable).
+ void Info(string message, params object[] formatArgs);
+
+ /// Logs a warning.
+ /// The message to log.
+ /// String.Format arguments (if applicable).
+ void Warning(string message, params object[] formatArgs);
+
+ /// Logs an error message resulting from an exception.
+ ///
+ /// The message to log.
+ /// String.Format arguments (if applicable).
+ void Error(Exception exception, string message, params object[] formatArgs);
+
+ /// Logs an error message.
+ /// The message to log.
+ /// String.Format arguments (if applicable).
+ void Error(string message, params object[] formatArgs);
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/NullLogger.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/NullLogger.cs
new file mode 100644
index 00000000000..79ba38475f8
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/NullLogger.cs
@@ -0,0 +1,59 @@
+/*
+Copyright 2011 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System;
+
+namespace Google.Apis.Logging
+{
+ ///
+ /// Represents a NullLogger which does not do any logging.
+ ///
+ public class NullLogger : ILogger
+ {
+ ///
+ public bool IsDebugEnabled
+ {
+ get { return false; }
+ }
+
+ ///
+ public ILogger ForType(Type type)
+ {
+ return new NullLogger();
+ }
+
+ ///
+ public ILogger ForType()
+ {
+ return new NullLogger();
+ }
+
+ ///
+ public void Info(string message, params object[] formatArgs) {}
+
+ ///
+ public void Warning(string message, params object[] formatArgs) {}
+
+ ///
+ public void Debug(string message, params object[] formatArgs) {}
+
+ ///
+ public void Error(Exception exception, string message, params object[] formatArgs) {}
+
+ ///
+ public void Error(string message, params object[] formatArgs) {}
+ }
+}
\ No newline at end of file
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/ReplacementSerializer.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/ReplacementSerializer.cs
new file mode 100644
index 00000000000..d01e0d3f126
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/ReplacementSerializer.cs
@@ -0,0 +1,19 @@
+using Google.Apis.Auth.OAuth2;
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Google.Apis.Auth.ExistingDependencies;
+
+// The replacement for NewtonsoftJsonSerializer
+internal class ReplacementSerializer
+{
+ internal static string Serialize(T value) => default;
+
+ internal static T Deserialize(string json) => default;
+
+ public static Task DeserializeAsync(Stream stream, CancellationToken cancellationToken) => default;
+
+ public static T Deserialize(Stream stream) => default;
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/RequestError.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/RequestError.cs
new file mode 100644
index 00000000000..eca7f1480d6
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/RequestError.cs
@@ -0,0 +1,95 @@
+/*
+Copyright 2011 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System.Collections.Generic;
+using System.Text;
+
+using Google.Apis.Util;
+
+namespace Google.Apis.Requests
+{
+ ///
+ /// Collection of server errors
+ ///
+ public class RequestError
+ {
+ ///
+ /// Enumeration of known error codes which may occur during a request.
+ ///
+ public enum ErrorCodes
+ {
+ ///
+ /// The ETag condition specified caused the ETag verification to fail.
+ /// Depending on the ETagAction of the request this either means that a change to the object has been
+ /// made on the server, or that the object in question is still the same and has not been changed.
+ ///
+ ETagConditionFailed = 412
+ }
+
+ ///
+ /// Contains a list of all errors
+ ///
+ public IList Errors { get; set; }
+
+ ///
+ /// The error code returned
+ ///
+ public int Code { get; set; }
+
+ ///
+ /// The error message returned
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// The full content of the error response that
+ /// this instance was created from.
+ ///
+ ///
+ /// The response may contain custom information that is not represented
+ /// by any of the properties in .
+ ///
+ public string ErrorResponseContent { get; set; }
+
+ internal bool IsOnlyRawContent =>
+ Message is null && Code == 0 && Errors.IsNullOrEmpty();
+
+ ///
+ /// Returns a string summary of this error
+ ///
+ /// A string summary of this error
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.AppendLine(GetType().FullName).Append(Message).AppendFormat(" [{0}]", Code).AppendLine();
+ if (Errors.IsNullOrEmpty())
+ {
+ sb.AppendLine("No individual errors");
+ }
+ else
+ {
+ sb.AppendLine("Errors [");
+ foreach (SingleError err in Errors)
+ {
+ sb.Append('\t').AppendLine(err.ToString());
+ }
+ sb.AppendLine("]");
+ }
+
+ return sb.ToString();
+ }
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/SingleError.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/SingleError.cs
new file mode 100644
index 00000000000..d1581055430
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/SingleError.cs
@@ -0,0 +1,60 @@
+/*
+Copyright 2011 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+namespace Google.Apis.Requests
+{
+ ///
+ /// A single server error
+ ///
+ public class SingleError
+ {
+ ///
+ /// The domain in which the error occured
+ ///
+ public string Domain { get; set; }
+
+ ///
+ /// The reason the error was thrown
+ ///
+ public string Reason { get; set; }
+
+ ///
+ /// The error message
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// Type of the location
+ ///
+ public string LocationType { get; set; }
+
+ ///
+ /// Location where the error was thrown
+ ///
+ public string Location { get; set; }
+
+ ///
+ /// Returns a string summary of this error
+ ///
+ /// A string summary of this error
+ public override string ToString()
+ {
+ return string.Format(
+ "Message[{0}] Location[{1} - {2}] Reason[{3}] Domain[{4}]", Message, Location, LocationType, Reason,
+ Domain);
+ }
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/TaskExtensions.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/TaskExtensions.cs
new file mode 100644
index 00000000000..dd456ca2bb0
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/TaskExtensions.cs
@@ -0,0 +1,51 @@
+/*
+Copyright 2020 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Google.Apis.Util
+{
+ // Note: this is duplicated between Google.Apis.Auth and Google.Apis.Core so it can stay internal. Please
+ // change both at the same time.
+ internal static class TaskExtensions
+ {
+ ///
+ /// Returns a task which can be cancelled by the given cancellation token, but otherwise observes the original
+ /// task's state. This does *not* cancel any work that the original task was doing, and should be used carefully.
+ ///
+ internal static Task WithCancellationToken(this Task task, CancellationToken cancellationToken)
+ {
+ if (!cancellationToken.CanBeCanceled)
+ {
+ return task;
+ }
+
+ return ImplAsync();
+
+ // Separate async method to allow the above optimization to avoid creating any new state machines etc.
+ async Task ImplAsync()
+ {
+ var cts = new TaskCompletionSource();
+ using (cancellationToken.Register(() => cts.TrySetCanceled()))
+ {
+ var completedTask = await Task.WhenAny(task, cts.Task).ConfigureAwait(false);
+ return await completedTask.ConfigureAwait(false);
+ }
+ }
+ }
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/Utilities.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/Utilities.cs
new file mode 100644
index 00000000000..71ff29894a8
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/Utilities.cs
@@ -0,0 +1,102 @@
+/*
+Copyright 2010 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Reflection;
+
+namespace Google.Apis.Util
+{
+ /// A utility class which contains helper methods and extension methods.
+ internal static class Utilities
+ {
+ /// Returns the version of the core library.
+ public static string GetLibraryVersion()
+ {
+ return Regex.Match(typeof(Utilities).GetTypeInfo().Assembly.FullName, "Version=([\\d\\.]+)").Groups[1].ToString();
+ }
+
+ ///
+ /// A Google.Apis utility method for throwing an if the object is
+ /// null.
+ ///
+ public static T ThrowIfNull(this T obj, string paramName)
+ {
+ if (obj == null)
+ {
+ throw new ArgumentNullException(paramName);
+ }
+
+ return obj;
+ }
+
+ ///
+ /// A Google.Apis utility method for throwing an if the string is
+ /// null or empty.
+ ///
+ /// The original string.
+ public static string ThrowIfNullOrEmpty(this string str, string paramName)
+ {
+ if (string.IsNullOrEmpty(str))
+ {
+ throw new ArgumentException("Parameter was empty", paramName);
+ }
+ return str;
+ }
+
+ /// Returns true in case the enumerable is null or empty.
+ internal static bool IsNullOrEmpty(this IEnumerable coll)
+ {
+ return coll == null || coll.Count() == 0;
+ }
+
+ ///
+ /// Checks that the given value is in fact defined in the enum used as the type argument of the method.
+ ///
+ /// The enum type to check the value within.
+ /// The value to check.
+ /// The name of the parameter whose value is being tested.
+ /// if it was a defined value
+ public static T CheckEnumValue(T value, string paramName) where T : struct
+ {
+ CheckArgument(
+ Enum.IsDefined(typeof(T), value),
+ paramName,
+ "Value {0} not defined in enum {1}", value, typeof(T).Name);
+ return value;
+ }
+
+ ///
+ /// Checks that given argument-based condition is met, throwing an otherwise.
+ ///
+ /// The (already evaluated) condition to check.
+ /// The name of the parameter whose value is being tested.
+ /// The format string to use to create the exception message if the
+ /// condition is not met.
+ /// The first argument to the format string.
+ /// The second argument to the format string.
+ public static void CheckArgument(bool condition, string paramName, string format, T1 arg0, T2 arg1)
+ {
+ if (!condition)
+ {
+ throw new ArgumentException(string.Format(format, arg0, arg1), paramName);
+ }
+ }
+
+ }
+}
diff --git a/Src/Support/Google.Apis.Auth/ExistingDependencies/VisibleForTestOnly.cs b/Src/Support/Google.Apis.Auth/ExistingDependencies/VisibleForTestOnly.cs
new file mode 100644
index 00000000000..b45d2d68915
--- /dev/null
+++ b/Src/Support/Google.Apis.Auth/ExistingDependencies/VisibleForTestOnly.cs
@@ -0,0 +1,29 @@
+/*
+Copyright 2010 Google Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+using System;
+
+namespace Google.Apis.Testing
+{
+ ///
+ /// Marker Attribute to indicate a Method/Class/Property has been made more visible for purpose of testing.
+ /// Mark the member as internal and make the testing assembly a friend using
+ /// [assembly: InternalsVisibleTo("Full.Name.Of.Testing.Assembly")]
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property |
+ AttributeTargets.Field)]
+ public class VisibleForTestOnly : Attribute { }
+}
\ No newline at end of file
diff --git a/Src/Support/Google.Apis.Auth/Google.Apis.Auth.csproj b/Src/Support/Google.Apis.Auth/Google.Apis.Auth.csproj
index 75b2cc61ff0..c26b87d1053 100644
--- a/Src/Support/Google.Apis.Auth/Google.Apis.Auth.csproj
+++ b/Src/Support/Google.Apis.Auth/Google.Apis.Auth.csproj
@@ -26,9 +26,9 @@ Supported Platforms:
-
-
-
+
+
+
@@ -37,6 +37,8 @@ Supported Platforms:
+
+
diff --git a/Src/Support/Google.Apis.Auth/JsonWebSignature.cs b/Src/Support/Google.Apis.Auth/JsonWebSignature.cs
index 3c767624413..c7a5bf526c0 100644
--- a/Src/Support/Google.Apis.Auth/JsonWebSignature.cs
+++ b/Src/Support/Google.Apis.Auth/JsonWebSignature.cs
@@ -14,7 +14,6 @@ You may obtain a copy of the License at
limitations under the License.
*/
-using Google.Apis.Json;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -51,7 +50,7 @@ public static Task VerifySignedTokenAsync(
/// If the token is invalid or expired.
/// The type of the payload to return, so user code can validate
/// additional claims. Should extend . Payload information will be deserialized
- /// using .
+ /// using the default serializer.
public async static Task VerifySignedTokenAsync(
string signedJwt, SignedTokenVerificationOptions options = null, CancellationToken cancellationToken = default)
where TPayload : Payload
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/AwsExternalAccountCredential.AwsSecurityCredential.cs b/Src/Support/Google.Apis.Auth/OAuth2/AwsExternalAccountCredential.AwsSecurityCredential.cs
index 1e541ede3df..2319880ee0a 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/AwsExternalAccountCredential.AwsSecurityCredential.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/AwsExternalAccountCredential.AwsSecurityCredential.cs
@@ -14,7 +14,7 @@ You may obtain a copy of the License at
limitations under the License.
*/
-using Google.Apis.Json;
+using Google.Apis.Auth.ExistingDependencies;
using Newtonsoft.Json;
using System;
using System.IO;
@@ -97,7 +97,7 @@ internal static async Task MaybeFromMetadataAsync(AwsMet
&& credentialJson != "")
{
// Deserialize the credentials
- var deserializedCredentials = NewtonsoftJsonSerializer.Instance.Deserialize(credentialJson);
+ var deserializedCredentials = ReplacementSerializer.Deserialize(credentialJson);
if (deserializedCredentials.IsSuccess
&& !string.IsNullOrEmpty(deserializedCredentials.AccessKeyId)
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/AwsExternalAccountCredential.cs b/Src/Support/Google.Apis.Auth/OAuth2/AwsExternalAccountCredential.cs
index aa2cba3e6eb..d65feb37549 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/AwsExternalAccountCredential.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/AwsExternalAccountCredential.cs
@@ -14,8 +14,8 @@ You may obtain a copy of the License at
limitations under the License.
*/
+using Google.Apis.Auth.ExistingDependencies;
using Google.Apis.Http;
-using Google.Apis.Json;
using Google.Apis.Util;
using System;
using System.Collections.Generic;
@@ -140,7 +140,7 @@ protected async override Task GetSubjectTokenAsyncImpl(CancellationToken
var subjectToken = AwsSignedSubjectToken.Create(awsSecurityCredentials, awsRegion, new Uri(regionalizedVerificationUrl), Audience, Clock);
- return Uri.EscapeDataString(NewtonsoftJsonSerializer.Instance.Serialize(subjectToken));
+ return Uri.EscapeDataString(ReplacementSerializer.Serialize(subjectToken));
}
///
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/DefaultCredentialProvider.cs b/Src/Support/Google.Apis.Auth/OAuth2/DefaultCredentialProvider.cs
index 55f0e8417bd..eec81cd8efd 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/DefaultCredentialProvider.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/DefaultCredentialProvider.cs
@@ -14,16 +14,15 @@ You may obtain a copy of the License at
limitations under the License.
*/
-using System;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-
+using Google.Apis.Auth.ExistingDependencies;
using Google.Apis.Auth.OAuth2.Flows;
using Google.Apis.Auth.OAuth2.Responses;
-using Google.Apis.Json;
using Google.Apis.Logging;
using Google.Apis.Util;
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
namespace Google.Apis.Auth.OAuth2
{
@@ -165,7 +164,7 @@ internal GoogleCredential CreateDefaultCredentialFromStream(Stream stream)
JsonCredentialParameters credentialParameters;
try
{
- credentialParameters = NewtonsoftJsonSerializer.Instance.Deserialize(stream);
+ credentialParameters = ReplacementSerializer.Deserialize(stream);
}
catch (Exception e)
{
@@ -180,8 +179,7 @@ internal async Task CreateDefaultCredentialFromStreamAsync(Str
JsonCredentialParameters credentialParameters;
try
{
- credentialParameters = await NewtonsoftJsonSerializer.Instance
- .DeserializeAsync(stream, cancellationToken)
+ credentialParameters = await ReplacementSerializer.DeserializeAsync(stream, cancellationToken)
.ConfigureAwait(false);
}
catch (Exception e)
@@ -197,7 +195,7 @@ internal GoogleCredential CreateDefaultCredentialFromJson(string json)
JsonCredentialParameters credentialParameters;
try
{
- credentialParameters = NewtonsoftJsonSerializer.Instance.Deserialize(json);
+ credentialParameters = ReplacementSerializer.Deserialize(json);
}
catch (Exception e)
{
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/FileSourcedExternalAccountCredential.cs b/Src/Support/Google.Apis.Auth/OAuth2/FileSourcedExternalAccountCredential.cs
index cd12981387b..0ccae405dcc 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/FileSourcedExternalAccountCredential.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/FileSourcedExternalAccountCredential.cs
@@ -14,8 +14,8 @@ You may obtain a copy of the License at
limitations under the License.
*/
+using Google.Apis.Auth.ExistingDependencies;
using Google.Apis.Http;
-using Google.Apis.Json;
using System.Collections.Generic;
using System.IO;
using System.Threading;
@@ -98,7 +98,7 @@ protected override async Task GetSubjectTokenAsyncImpl(CancellationToken
}
else
{
- var jsonResponse = NewtonsoftJsonSerializer.Instance.Deserialize>(fileContent);
+ var jsonResponse = ReplacementSerializer.Deserialize>(fileContent);
subjectToken = jsonResponse[SubjectTokenJsonFieldName];
}
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Flows/AuthorizationCodeFlow.cs b/Src/Support/Google.Apis.Auth/OAuth2/Flows/AuthorizationCodeFlow.cs
index 1f2ed326249..e80a3f06895 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Flows/AuthorizationCodeFlow.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Flows/AuthorizationCodeFlow.cs
@@ -14,6 +14,7 @@ You may obtain a copy of the License at
limitations under the License.
*/
+using Google.Apis.Auth.ExistingDependencies;
using Google.Apis.Auth.OAuth2.Requests;
using Google.Apis.Auth.OAuth2.Responses;
using Google.Apis.Http;
@@ -203,7 +204,7 @@ public AuthorizationCodeFlow(Initializer initializer)
// Set the HTTP client.
DefaultExponentialBackOffPolicy = initializer.DefaultExponentialBackOffPolicy;
- HttpClientFactory = initializer.HttpClientFactory ?? new HttpClientFactory();
+ HttpClientFactory = initializer.HttpClientFactory ?? new AuthHttpClientFactory();
var httpArgs = new CreateHttpClientArgs();
// Add exponential back-off initializer if necessary.
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Flows/GoogleAuthorizationCodeFlow.cs b/Src/Support/Google.Apis.Auth/OAuth2/Flows/GoogleAuthorizationCodeFlow.cs
index 09e5b89f416..e3be9f277f0 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Flows/GoogleAuthorizationCodeFlow.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Flows/GoogleAuthorizationCodeFlow.cs
@@ -14,11 +14,10 @@ You may obtain a copy of the License at
limitations under the License.
*/
+using Google.Apis.Auth.ExistingDependencies;
using Google.Apis.Auth.OAuth2.Requests;
using Google.Apis.Auth.OAuth2.Responses;
using Google.Apis.Http;
-using Google.Apis.Json;
-using Google.Apis.Util;
using System;
using System.Collections.Generic;
using System.Net.Http;
@@ -120,7 +119,7 @@ public override async Task RevokeTokenAsync(string userId, string token,
if (!response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
- var error = NewtonsoftJsonSerializer.Instance.Deserialize(content);
+ var error = ReplacementSerializer.Deserialize(content);
throw new TokenResponseException(error, response.StatusCode);
}
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Flows/IHttpAuthorizationFlow.cs b/Src/Support/Google.Apis.Auth/OAuth2/Flows/IHttpAuthorizationFlow.cs
index b08ff294c8f..c26d7fdfced 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Flows/IHttpAuthorizationFlow.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Flows/IHttpAuthorizationFlow.cs
@@ -27,7 +27,7 @@ internal interface IHttpAuthorizationFlow : IAuthorizationCodeFlow
/// given HTTP client factory.
///
/// The http client factory to be used by the new instance.
- /// May be null, in which case the default will be used.
+ /// May be null, in which case the default will be used.
/// A new instance with the same type as this but that will use
/// to obtain an to be used for token related operations.
IHttpAuthorizationFlow WithHttpClientFactory(IHttpClientFactory httpClientFactory);
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/GoogleClientSecrets.cs b/Src/Support/Google.Apis.Auth/OAuth2/GoogleClientSecrets.cs
index 105e41cd649..4ca2f41672d 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/GoogleClientSecrets.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/GoogleClientSecrets.cs
@@ -14,7 +14,7 @@ You may obtain a copy of the License at
limitations under the License.
*/
-using Google.Apis.Json;
+using Google.Apis.Auth.ExistingDependencies;
using System;
using System.IO;
using System.Threading;
@@ -58,11 +58,11 @@ public static GoogleClientSecrets Load(Stream stream) =>
/// Loads the Google client secret from the input stream.
public static GoogleClientSecrets FromStream(Stream stream) =>
- NewtonsoftJsonSerializer.Instance.Deserialize(stream);
+ ReplacementSerializer.Deserialize(stream);
/// Asynchronously loads the Google client secret from the input stream.
public static Task FromStreamAsync(Stream stream, CancellationToken cancellationToken = default) =>
- NewtonsoftJsonSerializer.Instance.DeserializeAsync(stream, cancellationToken);
+ ReplacementSerializer.DeserializeAsync(stream, cancellationToken);
/// Loads the Google client secret from a JSON file.
public static GoogleClientSecrets FromFile(string clientSecretsFilePath)
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/GoogleCredential.cs b/Src/Support/Google.Apis.Auth/OAuth2/GoogleCredential.cs
index 1a53e28fcdc..b2af0fe26c9 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/GoogleCredential.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/GoogleCredential.cs
@@ -327,7 +327,7 @@ GoogleAuthConsts.EnvironmentQuotaProject is string environmentQuotaProject
/// Creates a copy of this credential with the specified HTTP client factory.
///
/// The HTTP client factory to be used by the new credential.
- /// May be null, in which case the default will be used.
+ /// May be null, in which case the default will be used.
public virtual GoogleCredential CreateWithHttpClientFactory(IHttpClientFactory factory) =>
new GoogleCredential(credential.WithHttpClientFactory(factory));
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/GoogleWebAuthorizationBroker.cs b/Src/Support/Google.Apis.Auth/OAuth2/GoogleWebAuthorizationBroker.cs
index 0d795f151fc..ccf86f93fa9 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/GoogleWebAuthorizationBroker.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/GoogleWebAuthorizationBroker.cs
@@ -21,6 +21,7 @@ limitations under the License.
using System.Threading.Tasks;
using Google.Apis.Auth.OAuth2.Flows;
+using Google.Apis.Util;
using Google.Apis.Util.Store;
namespace Google.Apis.Auth.OAuth2
@@ -34,22 +35,10 @@ namespace Google.Apis.Auth.OAuth2
///
public class GoogleWebAuthorizationBroker
{
- // It's unforunate this is a public field. But it cannot be changed due to backward compatibility.
- /// The folder which is used by the .
- ///
- /// The reason that this is not 'private const' is that a user can change it and store the credentials in a
- /// different location.
- ///
- public static string Folder = "Google.Apis.Auth";
-
///
/// Asynchronously authorizes the specified user.
/// Requires user interaction; see remarks for more details.
///
- ///
- /// In case no data store is specified, will be used by
- /// default.
- ///
/// The client secrets.
///
/// The scopes which indicate the Google API access your application is requesting.
@@ -75,10 +64,6 @@ public static async Task AuthorizeAsync(ClientSecrets clientSecr
/// Asynchronously authorizes the specified user.
/// Requires user interaction; see remarks for more details.
///
- ///
- /// In case no data store is specified, will be used by
- /// default.
- ///
///
/// The client secrets stream. The authorization code flow constructor is responsible for disposing the stream.
///
@@ -87,12 +72,12 @@ public static async Task AuthorizeAsync(ClientSecrets clientSecr
///
/// The user to authorize.
/// Cancellation token to cancel an operation.
- /// The data store, if not specified a file data store will be used.
+ /// The data store.
/// The code receiver, if not specified a local server code receiver will be used.
/// User credential.
public static async Task AuthorizeAsync(Stream clientSecretsStream,
IEnumerable scopes, string user, CancellationToken taskCancellationToken,
- IDataStore dataStore = null, ICodeReceiver codeReceiver = null)
+ IDataStore dataStore, ICodeReceiver codeReceiver = null)
{
var initializer = new GoogleAuthorizationCodeFlow.Initializer
{
@@ -136,16 +121,15 @@ public static async Task ReauthorizeAsync(UserCredential userCredential,
///
/// The user to authorize.
/// Cancellation token to cancel an operation.
- /// The data store, if not specified a file data store will be used.
+ /// The data store. Must not be null.
/// The code receiver, if not specified a local server code receiver will be used.
/// User credential.
public static async Task AuthorizeAsync(
GoogleAuthorizationCodeFlow.Initializer initializer, IEnumerable scopes, string user,
- CancellationToken taskCancellationToken, IDataStore dataStore = null,
- ICodeReceiver codeReceiver = null)
+ CancellationToken taskCancellationToken, IDataStore dataStore, ICodeReceiver codeReceiver = null)
{
initializer.Scopes = scopes;
- initializer.DataStore = dataStore ?? new FileDataStore(Folder);
+ initializer.DataStore = dataStore.ThrowIfNull(nameof(dataStore));
var flow = new GoogleAuthorizationCodeFlow(initializer);
codeReceiver = codeReceiver ?? new LocalServerCodeReceiver();
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/IGoogleCredential.cs b/Src/Support/Google.Apis.Auth/OAuth2/IGoogleCredential.cs
index 9b86708e62b..d4191854548 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/IGoogleCredential.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/IGoogleCredential.cs
@@ -76,7 +76,7 @@ internal interface IGoogleCredential : ICredential, ITokenAccessWithHeaders
/// given HTTP client factory.
///
/// The http client factory to be used by the new instance.
- /// May be null in which case the default will be used.
+ /// May be null in which case the default will be used.
/// A new instance with the same type as this but that will use
/// to obtain an to be used for token and other operations.
IGoogleCredential WithHttpClientFactory(IHttpClientFactory httpClientFactory);
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/ITokenAccess.cs b/Src/Support/Google.Apis.Auth/OAuth2/ITokenAccess.cs
index e66b4279745..5ecdb538a3e 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/ITokenAccess.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/ITokenAccess.cs
@@ -17,14 +17,12 @@ limitations under the License.
using System.Threading;
using System.Threading.Tasks;
-using Google.Apis.Auth.OAuth2.Responses;
-
namespace Google.Apis.Auth.OAuth2
{
///
/// Allows direct retrieval of access tokens to authenticate requests.
/// This is necessary for workflows where you don't want to use
- /// to access the API.
+ /// BaseClientService to access the API.
/// (e.g. gRPC that implemenents the entire HTTP2 stack internally).
///
public interface ITokenAccess
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/RequestExtensions.cs b/Src/Support/Google.Apis.Auth/OAuth2/RequestExtensions.cs
index 6b1dc8c06e3..4841e8c33af 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/RequestExtensions.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/RequestExtensions.cs
@@ -14,8 +14,8 @@ You may obtain a copy of the License at
limitations under the License.
*/
+using Google.Apis.Auth.ExistingDependencies;
using Google.Apis.Http;
-using Google.Apis.Requests;
using Google.Apis.Util;
using System;
@@ -36,7 +36,7 @@ public static class RequestExtensions
/// The request which requires a credential. Must not be null.
/// The credential to use for this request only. Must not be null.
///
- public static T AddCredential(this T request, ICredential credential) where T : ClientServiceRequest
+ public static T AddCredential(this T request, ICredential credential) where T : ICredentialedRequest
{
request.ThrowIfNull(nameof(request));
credential.ThrowIfNull(nameof(credential));
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/AuthorizationCodeRequestUrl.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/AuthorizationCodeRequestUrl.cs
index d608f991981..997bc1c3b31 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/AuthorizationCodeRequestUrl.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/AuthorizationCodeRequestUrl.cs
@@ -14,13 +14,8 @@ You may obtain a copy of the License at
limitations under the License.
*/
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
using Google.Apis.Requests;
-using Google.Apis.Requests.Parameters;
+using System;
namespace Google.Apis.Auth.OAuth2.Requests
{
@@ -43,12 +38,8 @@ public AuthorizationCodeRequestUrl(Uri authorizationServerUrl)
/// Creates a which is used to request the authorization code.
public Uri Build()
{
- var builder = new RequestBuilder()
- {
- BaseUri = AuthorizationServerUrl
- };
- ParameterUtils.InitParameters(builder, this);
- return builder.BuildUri();
+ // FIXME: Implement the code without using common RequestBuilder stuff.
+ return null;
}
}
}
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/AuthorizationCodeTokenRequest.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/AuthorizationCodeTokenRequest.cs
index 2adaa41cd7e..82aa1f6765a 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/AuthorizationCodeTokenRequest.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/AuthorizationCodeTokenRequest.cs
@@ -14,7 +14,7 @@ You may obtain a copy of the License at
limitations under the License.
*/
-using System;
+// FIXME: Write code to create an HttpRequestMessage for this.
namespace Google.Apis.Auth.OAuth2.Requests
{
@@ -25,13 +25,11 @@ namespace Google.Apis.Auth.OAuth2.Requests
public class AuthorizationCodeTokenRequest : TokenRequest
{
/// Gets or sets the authorization code received from the authorization server.
- [Google.Apis.Util.RequestParameterAttribute("code")]
public string Code { get; set; }
///
/// Gets or sets the redirect URI parameter matching the redirect URI parameter in the authorization request.
///
- [Google.Apis.Util.RequestParameterAttribute("redirect_uri")]
public string RedirectUri { get; set; }
///
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/AuthorizationRequestUrl.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/AuthorizationRequestUrl.cs
index 712797f1c2e..a20e6799c13 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/AuthorizationRequestUrl.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/AuthorizationRequestUrl.cs
@@ -29,11 +29,9 @@ public class AuthorizationRequestUrl
/// token for requesting an access token (implicit grant), or space separated registered extension
/// values. See http://tools.ietf.org/html/rfc6749#section-3.1.1 for more details
///
- [Google.Apis.Util.RequestParameterAttribute("response_type", Google.Apis.Util.RequestParameterType.Query)]
public string ResponseType { get; set; }
/// Gets or sets the client identifier.
- [Google.Apis.Util.RequestParameterAttribute("client_id", Google.Apis.Util.RequestParameterType.Query)]
public string ClientId { get; set; }
///
@@ -41,21 +39,18 @@ public class AuthorizationRequestUrl
/// client after a successful authorization grant, as specified in
/// http://tools.ietf.org/html/rfc6749#section-3.1.2 or null for none.
///
- [Google.Apis.Util.RequestParameterAttribute("redirect_uri", Google.Apis.Util.RequestParameterType.Query)]
public string RedirectUri { get; set; }
///
/// Gets or sets space-separated list of scopes, as specified in http://tools.ietf.org/html/rfc6749#section-3.3
/// or null for none.
///
- [Google.Apis.Util.RequestParameterAttribute("scope", Google.Apis.Util.RequestParameterType.Query)]
public string Scope { get; set; }
///
/// Gets or sets the state (an opaque value used by the client to maintain state between the request and
/// callback, as mentioned in http://tools.ietf.org/html/rfc6749#section-3.1.2.2 or null for none.
///
- [Google.Apis.Util.RequestParameterAttribute("state", Google.Apis.Util.RequestParameterType.Query)]
public string State { get; set; }
private readonly Uri authorizationServerUrl;
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/GoogleAssertionTokenRequest.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/GoogleAssertionTokenRequest.cs
index 57154e6da4f..3b38b66b4be 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/GoogleAssertionTokenRequest.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/GoogleAssertionTokenRequest.cs
@@ -15,6 +15,8 @@ limitations under the License.
*/
+// FIXME: Write code to create an HttpRequestMessage for this.
+
namespace Google.Apis.Auth.OAuth2.Requests
{
///
@@ -24,7 +26,6 @@ namespace Google.Apis.Auth.OAuth2.Requests
public class GoogleAssertionTokenRequest : TokenRequest
{
/// Gets or sets the JWT (including signature).
- [Google.Apis.Util.RequestParameterAttribute("assertion")]
public string Assertion { get; set; }
///
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/GoogleAuthorizationCodeRequestUrl.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/GoogleAuthorizationCodeRequestUrl.cs
index 54fbcf62df1..8fdd4a29260 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/GoogleAuthorizationCodeRequestUrl.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/GoogleAuthorizationCodeRequestUrl.cs
@@ -17,6 +17,8 @@ limitations under the License.
using System;
using System.Collections.Generic;
+// FIXME: Write code to create an HttpRequestMessage for this.
+
namespace Google.Apis.Auth.OAuth2.Requests
{
///
@@ -30,7 +32,6 @@ public class GoogleAuthorizationCodeRequestUrl : AuthorizationCodeRequestUrl
/// Gets or sets the access type. Set online to request on-line access or offline to request
/// off-line access or null for the default behavior. The default value is offline.
///
- [Google.Apis.Util.RequestParameterAttribute("access_type", Google.Apis.Util.RequestParameterType.Query)]
public string AccessType { get; set; }
///
@@ -39,14 +40,12 @@ public class GoogleAuthorizationCodeRequestUrl : AuthorizationCodeRequestUrl
/// See OpenIDConnect documentation
/// for details.
///
- [Google.Apis.Util.RequestParameterAttribute("prompt", Google.Apis.Util.RequestParameterType.Query)]
public string Prompt { get; set; }
///
/// Gets or sets prompt for consent behavior auto to request auto-approval orforce to force the
/// approval UI to show, or null for the default behavior.
///
- [Google.Apis.Util.RequestParameterAttribute("approval_prompt", Google.Apis.Util.RequestParameterType.Query)]
[Obsolete("Unused for Google OpenID; use the 'Prompt' property instead.")]
public string ApprovalPrompt { get; set; }
@@ -56,7 +55,6 @@ public class GoogleAuthorizationCodeRequestUrl : AuthorizationCodeRequestUrl
/// hint to the Authentication Server. Passing this hint will either pre-fill the email box on the sign-in form
/// or select the proper multi-login session, thereby simplifying the login flow.
///
- [Google.Apis.Util.RequestParameterAttribute("login_hint", Google.Apis.Util.RequestParameterType.Query)]
public string LoginHint { get; set; }
///
@@ -66,8 +64,6 @@ public class GoogleAuthorizationCodeRequestUrl : AuthorizationCodeRequestUrl
/// authorizations granted to this user/application combination for other scopes.
///
/// Currently unsupported for installed apps.
- [Google.Apis.Util.RequestParameterAttribute("include_granted_scopes",
- Google.Apis.Util.RequestParameterType.Query)]
public string IncludeGrantedScopes { get; set; }
///
@@ -75,7 +71,6 @@ public class GoogleAuthorizationCodeRequestUrl : AuthorizationCodeRequestUrl
/// a random value generated by your app that enables replay protection.
/// See https://developers.google.com/identity/protocols/OpenIDConnect for more details.
///
- [Google.Apis.Util.RequestParameterAttribute("nonce", Google.Apis.Util.RequestParameterType.Query)]
public string Nonce { get; set; }
///
@@ -86,8 +81,6 @@ public class GoogleAuthorizationCodeRequestUrl : AuthorizationCodeRequestUrl
/// The name of this parameter is used only for the constructor and will not end up in the resultant query
/// string.
///
- [Google.Apis.Util.RequestParameterAttribute("user_defined_query_params",
- Google.Apis.Util.RequestParameterType.UserDefinedQueries)]
public IEnumerable> UserDefinedQueryParams { get; set; }
///
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/GoogleRevokeTokenRequest.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/GoogleRevokeTokenRequest.cs
index a6be5caedf9..c1ce461d379 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/GoogleRevokeTokenRequest.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/GoogleRevokeTokenRequest.cs
@@ -16,8 +16,7 @@ limitations under the License.
using System;
-using Google.Apis.Requests;
-using Google.Apis.Requests.Parameters;
+// FIXME: Write code to create an HttpRequestMessage for this.
namespace Google.Apis.Auth.OAuth2.Requests
{
@@ -35,7 +34,6 @@ public Uri RevokeTokenUrl
}
/// Gets or sets the token to revoke.
- [Google.Apis.Util.RequestParameterAttribute("token")]
public string Token { get; set; }
public GoogleRevokeTokenRequest(Uri revokeTokenUrl)
@@ -46,12 +44,8 @@ public GoogleRevokeTokenRequest(Uri revokeTokenUrl)
/// Creates a which is used to request the authorization code.
public Uri Build()
{
- var builder = new RequestBuilder()
- {
- BaseUri = revokeTokenUrl
- };
- ParameterUtils.InitParameters(builder, this);
- return builder.BuildUri();
+ // FIXME: Implement the code without using common RequestBuilder stuff.
+ return null;
}
}
}
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/IamSignBlobRequest.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/IamSignBlobRequest.cs
index 5a916aaefb8..ac9fc5d60ee 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/IamSignBlobRequest.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/IamSignBlobRequest.cs
@@ -17,6 +17,8 @@ limitations under the License.
using Newtonsoft.Json;
using System.Collections.Generic;
+// FIXME: Write code to create an HttpRequestMessage for this.
+
namespace Google.Apis.Auth.OAuth2.Requests
{
internal class IamSignBlobRequest
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/ImpersonationAccessTokenRequest.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/ImpersonationAccessTokenRequest.cs
index 14f167ff271..c5219ea9a49 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/ImpersonationAccessTokenRequest.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/ImpersonationAccessTokenRequest.cs
@@ -17,6 +17,8 @@ limitations under the License.
using Newtonsoft.Json;
using System.Collections.Generic;
+// FIXME: Write code to create an HttpRequestMessage for this.
+
namespace Google.Apis.Auth.OAuth2.Requests
{
///
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/ImpersonationOIdCTokenRequest.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/ImpersonationOIdCTokenRequest.cs
index 1b3293d779b..43a74e26c6e 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/ImpersonationOIdCTokenRequest.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/ImpersonationOIdCTokenRequest.cs
@@ -16,6 +16,8 @@ limitations under the License.
using Newtonsoft.Json;
+// FIXME: Write code to create an HttpRequestMessage for this.
+
namespace Google.Apis.Auth.OAuth2.Requests
{
///
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/ImpersonationRequest.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/ImpersonationRequest.cs
index 9b7714e2733..539f4224424 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/ImpersonationRequest.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/ImpersonationRequest.cs
@@ -17,6 +17,8 @@ limitations under the License.
using Newtonsoft.Json;
using System.Collections.Generic;
+// FIXME: Write code to create an HttpRequestMessage for this.
+
namespace Google.Apis.Auth.OAuth2.Requests
{
internal abstract class ImpersonationRequest
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/RefreshTokenRequest.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/RefreshTokenRequest.cs
index 6456406400a..6fb27334d6a 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/RefreshTokenRequest.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/RefreshTokenRequest.cs
@@ -14,6 +14,8 @@ You may obtain a copy of the License at
limitations under the License.
*/
+// FIXME: Write code to create an HttpRequestMessage for this.
+
namespace Google.Apis.Auth.OAuth2.Requests
{
///
@@ -23,7 +25,6 @@ namespace Google.Apis.Auth.OAuth2.Requests
public class RefreshTokenRequest : TokenRequest
{
/// Gets or sets the Refresh token issued to the client.
- [Google.Apis.Util.RequestParameterAttribute("refresh_token")]
public string RefreshToken { get; set; }
///
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/RequestExtensions.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/RequestExtensions.cs
index dbf3f1b37ad..c57bec59077 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/RequestExtensions.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/RequestExtensions.cs
@@ -14,10 +14,9 @@ You may obtain a copy of the License at
limitations under the License.
*/
+using Google.Apis.Auth.ExistingDependencies;
using Google.Apis.Auth.OAuth2.Responses;
-using Google.Apis.Json;
using Google.Apis.Logging;
-using Google.Apis.Requests.Parameters;
using Google.Apis.Util;
using System.Net.Http;
using System.Net.Http.Headers;
@@ -37,7 +36,7 @@ internal static async Task PostJsonAsync(
{
var httpRequest = new HttpRequestMessage(HttpMethod.Post, url)
{
- Content = new StringContent(NewtonsoftJsonSerializer.Instance.Serialize(request), Encoding.UTF8, "application/json")
+ Content = new StringContent(ReplacementSerializer.Serialize(request), Encoding.UTF8, "application/json")
};
return await httpClient.SendAsync(httpRequest, cancellationToken).ConfigureAwait(false);
@@ -52,7 +51,7 @@ internal static async Task PostJsonAsync(
{
var response = await request.PostJsonAsync(httpClient, url, cancellationToken).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
- return await NewtonsoftJsonSerializer.Instance.DeserializeAsync(
+ return await ReplacementSerializer.DeserializeAsync(
await response.Content.ReadAsStreamAsync().ConfigureAwait(false), cancellationToken).ConfigureAwait(false);
}
@@ -82,9 +81,10 @@ internal static async Task PostFormAsync(this object request, Htt
string url, AuthenticationHeaderValue authenticationHeaderValue,
IClock clock, ILogger logger, CancellationToken taskCancellationToken)
{
+ // TODO: Reimplement without the common parameter code we had before.
var httpRequest = new HttpRequestMessage(HttpMethod.Post, url)
{
- Content = ParameterUtils.CreateFormUrlEncodedContent(request)
+ Content = new StringContent("FIXME")
};
if (authenticationHeaderValue is not null)
{
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/StsRequestTokenBuilder.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/StsRequestTokenBuilder.cs
index e30b5914055..d36b4809891 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/StsRequestTokenBuilder.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/StsRequestTokenBuilder.cs
@@ -14,7 +14,7 @@ You may obtain a copy of the License at
limitations under the License.
*/
-using Google.Apis.Json;
+using Google.Apis.Auth.ExistingDependencies;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -88,7 +88,7 @@ public StsTokenRequest Build()
: null;
var options = (authenticationHeader is null && WorkforcePoolUserProject is string)
- ? NewtonsoftJsonSerializer.Instance.Serialize(new { userProject = WorkforcePoolUserProject })
+ ? ReplacementSerializer.Serialize(new { userProject = WorkforcePoolUserProject })
: null;
var scope = Scopes?.Any() == true ? string.Join(" ", Scopes) : null;
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/StsTokenRequest.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/StsTokenRequest.cs
index f941a5c688b..5617eb01486 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/StsTokenRequest.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/StsTokenRequest.cs
@@ -14,7 +14,6 @@ You may obtain a copy of the License at
limitations under the License.
*/
-using Google.Apis.Util;
using System.Net.Http.Headers;
namespace Google.Apis.Auth.OAuth2.Requests
@@ -45,47 +44,40 @@ internal StsTokenRequest(
/// Gets the grant type for this request.
/// Only urn:ietf:params:oauth:grant-type:token-exchange is currently supported.
///
- [RequestParameter("grant_type")]
public string GrantType { get; }
///
/// The audience for which the requested token is intended. For instance:
/// "//iam.googleapis.com/projects/my-project-id/locations/global/workloadIdentityPools/my-pool-id/providers/my-provider-id"
///
- [RequestParameter("audience")]
public string Audience { get; }
///
/// The space-delimited list of desired scopes for the requested token as defined in
/// http://tools.ietf.org/html/rfc6749#section-3.3.
///
- [RequestParameter("scope")]
public string Scope { get; }
///
/// The type of the requested security token.
/// Only urn:ietf:params:oauth:token-type:access_token is currently supported.
///
- [RequestParameter("requested_token_type")]
public string RequestedTokenType { get; }
///
/// In terms of Google 3PI support, this is the 3PI credential.
///
- [RequestParameter("subject_token")]
public string SubjectToken { get; }
///
/// The subject token type.
///
- [RequestParameter("subject_token_type")]
public string SubjectTokenType { get; }
///
/// Google specific STS token request options.
/// May be null.
///
- [RequestParameter("options")]
public string GoogleOptions { get; }
///
@@ -93,5 +85,7 @@ internal StsTokenRequest(
/// May be null.
///
public AuthenticationHeaderValue AuthenticationHeader { get; }
+
+ // FIXME: Probably hand-write code to create an appropriate HttpRequestMessage.
}
}
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/TokenRequest.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/TokenRequest.cs
index f18c97420ff..2f4e3167b90 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/TokenRequest.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/TokenRequest.cs
@@ -14,13 +14,10 @@ You may obtain a copy of the License at
limitations under the License.
*/
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
namespace Google.Apis.Auth.OAuth2.Requests
{
+ // FIXME: Write code to create an HttpRequestMessage for this.
+
///
/// OAuth 2.0 request for an access token as specified in http://tools.ietf.org/html/rfc6749#section-4.
///
@@ -29,22 +26,18 @@ public class TokenRequest
///
/// Gets or sets space-separated list of scopes as specified in http://tools.ietf.org/html/rfc6749#section-3.3.
///
- [Google.Apis.Util.RequestParameterAttribute("scope")]
public string Scope { get; set; }
///
/// Gets or sets the Grant type. Sets authorization_code or password or client_credentials
/// or refresh_token or absolute URI of the extension grant type.
///
- [Google.Apis.Util.RequestParameterAttribute("grant_type")]
public string GrantType { get; set; }
/// Gets or sets the client Identifier.
- [Google.Apis.Util.RequestParameterAttribute("client_id")]
public string ClientId { get; set; }
/// Gets or sets the client Secret.
- [Google.Apis.Util.RequestParameterAttribute("client_secret")]
public string ClientSecret { get; set; }
}
}
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Requests/TokenRequestExtenstions.cs b/Src/Support/Google.Apis.Auth/OAuth2/Requests/TokenRequestExtenstions.cs
index 90b089c0456..64356552081 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Requests/TokenRequestExtenstions.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Requests/TokenRequestExtenstions.cs
@@ -22,8 +22,10 @@ limitations under the License.
namespace Google.Apis.Auth.OAuth2.Requests
{
+ // TODO: Only use this if we really need to...
+
/// Extension methods to .
- public static class TokenRequestExtenstions
+ public static class TokenRequestExtensions
{
///
/// Executes the token request in order to receive a
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/Responses/TokenResponse.cs b/Src/Support/Google.Apis.Auth/OAuth2/Responses/TokenResponse.cs
index 0ff798b4376..b2e81cf3e92 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/Responses/TokenResponse.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/Responses/TokenResponse.cs
@@ -14,7 +14,7 @@ You may obtain a copy of the License at
limitations under the License.
*/
-using Google.Apis.Json;
+using Google.Apis.Auth.ExistingDependencies;
using Google.Apis.Logging;
using Google.Apis.Util;
using System;
@@ -159,7 +159,7 @@ public static async Task FromHttpResponseAsync(HttpResponseMessag
// "{"error": {"code": 404, "message": "...", "errors": [{"message": "...", ...}], "status": "NOT_FOUND"}}"
var error = response.RequestMessage?.RequestUri?.AbsoluteUri.StartsWith(GoogleAuthConsts.IamServiceAccountEndpointCommonPrefix) == true ?
new TokenErrorResponse { Error = content } :
- NewtonsoftJsonSerializer.Instance.Deserialize(content);
+ ReplacementSerializer.Deserialize(content);
throw new TokenResponseException(error, response.StatusCode);
}
@@ -176,7 +176,7 @@ public static async Task FromHttpResponseAsync(HttpResponseMessag
else
{
typeName = nameof(TokenResponse);
- newToken = NewtonsoftJsonSerializer.Instance.Deserialize(content);
+ newToken = ReplacementSerializer.Deserialize(content);
}
// We make some modifications to the token before returning, to guarantee consistency
// for our code across endpoint usage.
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/ServiceAccountCredential.cs b/Src/Support/Google.Apis.Auth/OAuth2/ServiceAccountCredential.cs
index 362f7baf926..61c657d7d7b 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/ServiceAccountCredential.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/ServiceAccountCredential.cs
@@ -23,9 +23,9 @@ limitations under the License.
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.Auth.OAuth2.Requests;
-using Google.Apis.Json;
using Google.Apis.Util;
using Google.Apis.Http;
+using Google.Apis.Auth.ExistingDependencies;
#if NETSTANDARD1_3 || NETSTANDARD2_0 || NET461
using RsaKey = System.Security.Cryptography.RSA;
@@ -439,7 +439,7 @@ private string CreateJwtAccessTokenForOidc(OidcTokenOptions options, DateTime is
private string CreateAssertionFromPayload(JsonWebSignature.Payload payload)
{
string serializedHeader = CreateSerializedHeader();
- string serializedPayload = NewtonsoftJsonSerializer.Instance.Serialize(payload);
+ string serializedPayload = ReplacementSerializer.Serialize(payload);
var assertion = new StringBuilder();
assertion.Append(TokenEncodingHelpers.UrlSafeBase64Encode(serializedHeader))
@@ -490,7 +490,7 @@ private string CreateSerializedHeader()
KeyId = KeyId
};
- return NewtonsoftJsonSerializer.Instance.Serialize(header);
+ return ReplacementSerializer.Serialize(header);
}
///
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/ServiceCredential.cs b/Src/Support/Google.Apis.Auth/OAuth2/ServiceCredential.cs
index bd0d8a925e6..fb0c2ab8783 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/ServiceCredential.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/ServiceCredential.cs
@@ -14,6 +14,7 @@ You may obtain a copy of the License at
limitations under the License.
*/
+using Google.Apis.Auth.ExistingDependencies;
using Google.Apis.Auth.OAuth2.Responses;
using Google.Apis.Http;
using Google.Apis.Logging;
@@ -215,7 +216,7 @@ public ServiceCredential(Initializer initializer)
DefaultExponentialBackOffPolicy = initializer.DefaultExponentialBackOffPolicy;
HttpClientInitializers = new List(initializer.HttpClientInitializers).AsReadOnly();
- HttpClientFactory = initializer.HttpClientFactory ?? new HttpClientFactory();
+ HttpClientFactory = initializer.HttpClientFactory ?? new AuthHttpClientFactory();
HttpClient = HttpClientFactory.CreateHttpClient(BuildCreateHttpClientArgs());
_refreshManager = new TokenRefreshManager(RequestAccessTokenAsync, Clock, Logger);
diff --git a/Src/Support/Google.Apis.Auth/OAuth2/UrlSourcedExternalAccountCredential.cs b/Src/Support/Google.Apis.Auth/OAuth2/UrlSourcedExternalAccountCredential.cs
index cce70374742..b0add0b4396 100644
--- a/Src/Support/Google.Apis.Auth/OAuth2/UrlSourcedExternalAccountCredential.cs
+++ b/Src/Support/Google.Apis.Auth/OAuth2/UrlSourcedExternalAccountCredential.cs
@@ -14,8 +14,8 @@ You may obtain a copy of the License at
limitations under the License.
*/
+using Google.Apis.Auth.ExistingDependencies;
using Google.Apis.Http;
-using Google.Apis.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -124,7 +124,7 @@ protected async override Task GetSubjectTokenAsyncImpl(CancellationToken
return responseText;
}
- var jsonResponse = NewtonsoftJsonSerializer.Instance.Deserialize>(responseText);
+ var jsonResponse = ReplacementSerializer.Deserialize>(responseText);
return jsonResponse[SubjectTokenJsonFieldName];
}
diff --git a/Src/Support/Google.Apis.Auth/SignedToken.cs b/Src/Support/Google.Apis.Auth/SignedToken.cs
index e0c85bcc545..d9a239e9f12 100644
--- a/Src/Support/Google.Apis.Auth/SignedToken.cs
+++ b/Src/Support/Google.Apis.Auth/SignedToken.cs
@@ -14,7 +14,7 @@ You may obtain a copy of the License at
limitations under the License.
*/
-using Google.Apis.Json;
+using Google.Apis.Auth.ExistingDependencies;
using Google.Apis.Util;
using System;
using System.Security.Cryptography;
@@ -76,8 +76,8 @@ internal static SignedToken FromSignedToken(string sign
var encodedPayload = parts[1];
// Decode the three parts of the JWT: header.payload.signature
- var headerValue = NewtonsoftJsonSerializer.Instance.Deserialize(TokenEncodingHelpers.Base64UrlToString(encodedHeader));
- var payloadValue = NewtonsoftJsonSerializer.Instance.Deserialize(TokenEncodingHelpers.Base64UrlToString(encodedPayload));
+ var headerValue = ReplacementSerializer.Deserialize(TokenEncodingHelpers.Base64UrlToString(encodedHeader));
+ var payloadValue = ReplacementSerializer.Deserialize(TokenEncodingHelpers.Base64UrlToString(encodedPayload));
var signature = TokenEncodingHelpers.Base64UrlDecode(parts[2]);
return new SignedToken(encodedHeader, encodedPayload, headerValue, payloadValue, signature);
diff --git a/Src/Support/GoogleApisClient.sln b/Src/Support/GoogleApisClient.sln
index e1f2f1c9901..418f74e47d9 100644
--- a/Src/Support/GoogleApisClient.sln
+++ b/Src/Support/GoogleApisClient.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.29613.14
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33530.505
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Apis.Core", "Google.Apis.Core\Google.Apis.Core.csproj", "{556BEB88-1F3B-4EFA-B912-828C90AC3BEB}"
EndProject