2using System.Collections.Specialized;
3using System.Diagnostics.CodeAnalysis;
6using System.Security.Authentication;
18 public static partial class API
20 private const string AUTH_HEADER =
"Authorization";
31 string RequestedAuthentication);
43 [SuppressMessage(
"Microsoft.Design",
"CA1009:DeclareEventHandlersCorrectly")]
83 int sequentialAttempts = 0)
87 if (response.ResponseStatus != ResponseStatus.Completed)
92 if (response.ErrorException is WebException &&
93 response.ErrorException.Message.Contains(
"Could not create SSL/TLS secure channel"))
98 throw new AuthenticationException(response.ErrorMessage, response.ErrorException);
104 bool success = (int)response.StatusCode >= 200 && (
int)response.StatusCode < 300;
116 string requestAuthenticationToken = response.Request.Parameters.Where(
117 p => p.Type == ParameterType.HttpHeader &&
118 p.Name.Equals(AUTH_HEADER, StringComparison.OrdinalIgnoreCase))
119 .Select(p => p.Value.ToString()).FirstOrDefault();
123 bool usedDefaultAuth = requestAuthenticationToken == defaultAuthToken;
131 else if (response.StatusCode == HttpStatusCode.Unauthorized)
137 if (response.StatusCode != HttpStatusCode.Unauthorized)
144 throw new AuthenticationException(
"Request failed after " +
158 Parameter authenticateHeader =
159 response.Headers.FirstOrDefault(h => h.Name ==
"WWW-Authenticate");
160 string strAuthenticateHeader = authenticateHeader?.Value?.ToString();
163 InvokeAuthenticationRequested(requestAuthenticationToken, strAuthenticateHeader);
171 string exceptionMessage =
"The current request included an authentication token (" +
172 requestAuthenticationToken +
") which was rejected by the server";
175 if (defaultAuthToken !=
null)
177 exceptionMessage +=
", and which differs from the currently configured default " +
178 "authentication token (" + defaultAuthToken +
"). Either correct the \"" +
179 AUTH_HEADER +
"\" header parameter supplied to this request, or exclude it " +
180 "entirely and the default authentication token will be used.";
185 exceptionMessage +=
". Either correct the \"" + AUTH_HEADER +
"\" header parameter " +
186 "supplied to this request, or exclude it entirely and use the " +
187 "'API.AuthenticationRequested' event or 'API.AuthenticationToken' " +
188 "to automatically handle authentication for Analyze Re API requests.";
190 throw new AuthenticationException(exceptionMessage);
194 private static readonly
object InvokeAuthenticationRequestedLock =
new object();
205 private static void InvokeAuthenticationRequested(
206 string authenticationTokenUsed,
207 string RequestedAuthentication)
209 if (RequestedAuthentication ==
null)
211 throw new AuthenticationException(
"Authentication requested, but no " +
212 "authentication type was specified. This is a server error.");
215 bool lockTaken =
false;
220 Monitor.TryEnter(InvokeAuthenticationRequestedLock, 30000, ref lockTaken);
230 throw new AuthenticationException(
231 "Timed out while waiting for another thread to complete authentication.");
240 throw new AuthenticationException(
"The server requires authentication, " +
241 "and the current authentication token (" +
243 "Please verify the credentials supplied.");
247 throw new AuthenticationException(
"The server requires authorization, " +
248 "but no authentication settings have been configured. Please either " +
249 "handle the API.AuthenticationRequested event appropriately, " +
250 "or set the global default API.AuthenticationToken directly.");
256 if (RequestedAuthentication.Trim().StartsWith(
"Basic",
257 StringComparison.InvariantCultureIgnoreCase))
261 else if (RequestedAuthentication.Trim().StartsWith(
"OAuth",
262 StringComparison.InvariantCultureIgnoreCase))
268 throw new AuthenticationException(
269 "Unrecognized authentication type requested: " + RequestedAuthentication);
278 throw new AuthenticationException(
"Error while invoking the " +
279 "AuthenticationRequested event: " + ex.Message, ex);
282 if (newAuthenticationToken?.access_token ==
null)
284 throw new AuthenticationException(
"The server requires authentication.");
288 CacheAuthentication();
293 Monitor.Exit(InvokeAuthenticationRequestedLock);
299 private static void CacheAuthentication()
307 TrySaveLibrarySettings(() =>
313 .FirstOrDefault(s => s.StartsWith(
ServerURL));
319 AuthenticationToken is BasicAuthenticationToken ?
"Basic" :
"OAuth",
320 AuthenticationToken.access_token
326 throw new Exception(
"Error storing authentication credentials: " + e.Message, e);
331 private static void RestoreCachedAuthentication()
335 StringCollection cachedCredentials =
338 if (cachedCredentials ==
null)
return;
340 string found = cachedCredentials.Cast<
string>()
341 .FirstOrDefault(s => s.StartsWith(
ServerURL +
"|"));
342 if (found ==
null)
return;
343 string[] credentials = found.Split(
'|');
348 AuthenticationToken.access_token = credentials[2];
361 TrySaveLibrarySettings(() =>
396 IRestResponse response;
406 if (response.ResponseStatus != ResponseStatus.Completed)
409 if (response.StatusCode == HttpStatusCode.Unauthorized)
417 if (((
int)response.StatusCode) / 100 == 2)
440 TrySaveLibrarySettings(() =>
451 .FirstOrDefault(s => s.StartsWith(server +
"|"));
452 if (found ==
null)
return;
API methods / requests made available to the user.
delegate void AuthenticationRequestedHandler(ref IAccessToken ToAuthenticate, string RequestedAuthentication)
A handler that can respond to a AuthenticationRequestedHandler event.
static AuthenticationRequestedHandler AuthenticationRequested
An event that fires whenever authentication is requested by the server. This event can be used to pro...
static IAccessToken AuthenticationToken
The AccessToken storing authentication information for requests made to the server.
static volatile int MaxRequestRetries
When a temporary communication failure occurs (such as a socket error or an authentication failure fo...
static bool IsAReServerActive(string checkServerURL, int? timeout=null)
Determines if the provided URL is a valid running Analyze Re server.
static void TryPromptForAuthentication()
Invoke the AuthenticationRequested event, which requests authentication credentials for the server....
static bool TryHandleAuthenticationErrors(IRestResponse response, int sequentialAttempts=0)
Checks an IRestResponse object for authentication errors, then invokes configured authentication dele...
static AuthenticationStatus GetAuthenticationStatus(bool force_request=false)
Determines whether we are currently authenticated against the server with the global default Authenti...
static string GetCurrentAuthorizationString()
Return the Authorization header string formed by the current AuthenticationToken.
static string ServerURL
The default server URL to be used for all API requests. On change, voids the current cached authentic...
static void ClearCachedAuthenticationCredentials(string server=null)
The Analyze Re API .NET Client Library caches authentication tokens that have been validated via the ...
static IRestResponse ExecuteRestRequest(string resource, Method method, IEnumerable< Parameter > requestParameters=null, int? timeout=null, bool returnRawResponse=false, Action< Stream > responseStreamReader=null)
Perform a REST request on the server.
An AccessToken storing basic authentication information for requests made to the server.
An AccessToken storing OAuth authentication information for requests made to the server.
This part of the Settings class is not generated from the Settings.settings designer,...
static Settings Default
The default settings used by the static Analyze Re API client library.
global::System.Collections.Specialized.StringCollection CachedCredentials
A collection of cached authentication tokens which can be used to restore a previous connection betwe...
An AccessToken storing authentication information for requests made to the server.
string access_token
The AccessToken identifier.
AccessTokenStatus status
The AccessToken's current AccessTokenStatus (unauthorized / valid).
AccessTokenStatus
An AccessToken's status (unauthorized / valid).
AuthenticationStatus
The status of authentication against the current server.