public DefaultRequestExecutor( IHttpClient httpClient, IClientApiKey apiKey, AuthenticationScheme authenticationScheme, ILogger logger, IBackoffStrategy defaultBackoffStrategy, IBackoffStrategy throttlingBackoffStrategy) { if (!apiKey.IsValid()) { throw new ApplicationException("API Key is invalid."); } this.httpClient = httpClient; this.syncHttpClient = httpClient as ISynchronousHttpClient; this.asyncHttpClient = httpClient as IAsynchronousHttpClient; this.apiKey = apiKey; this.authenticationScheme = authenticationScheme; IRequestAuthenticatorFactory requestAuthenticatorFactory = new DefaultRequestAuthenticatorFactory(); this.requestAuthenticator = requestAuthenticatorFactory.Create(authenticationScheme); this.logger = logger; this.defaultBackoffStrategy = defaultBackoffStrategy; this.throttlingBackoffStrategy = throttlingBackoffStrategy; }
void IRequestAuthenticator.Authenticate(IHttpRequest request, IClientApiKey apiKey) { var now = DateTimeOffset.UtcNow; var nonce = Guid.NewGuid().ToString(); this.AuthenticateCore(request, apiKey, now, nonce); }
public DefaultRequestExecutor( IHttpClient httpClient, IClientApiKey apiKey, AuthenticationScheme authenticationScheme, ILogger logger, IBackoffStrategy defaultBackoffStrategy, IBackoffStrategy throttlingBackoffStrategy) { if (!apiKey.IsValid()) { throw new ApplicationException("API Key is invalid."); } this.httpClient = httpClient; this.syncHttpClient = httpClient as ISynchronousHttpClient; this.asyncHttpClient = httpClient as IAsynchronousHttpClient; this.apiKey = apiKey; this.authenticationScheme = authenticationScheme; IRequestAuthenticatorFactory requestAuthenticatorFactory = new DefaultRequestAuthenticatorFactory(); this.requestAuthenticator = requestAuthenticatorFactory.Create(authenticationScheme); this.logger = logger; this.defaultBackoffStrategy = defaultBackoffStrategy; this.throttlingBackoffStrategy = throttlingBackoffStrategy; }
public DefaultRequestExecutor( IHttpClient httpClient, IClientApiKey apiKey, AuthenticationScheme authenticationScheme, ILogger logger) : this(httpClient, apiKey, authenticationScheme, logger, new DefaultBackoffStrategy(MaxBackoffMilliseconds), new ThrottlingBackoffStrategy(MaxBackoffMilliseconds)) { }
internal void AuthenticateCore(IHttpRequest request, IClientApiKey apiKey, DateTimeOffset now) { request.Headers.Add(StormpathDateHeaderName, Iso8601.Format(now, withSeparators: false)); var authorizationHeaderContent = $"{apiKey.GetId()}:{apiKey.GetSecret()}"; var authorizationHeaderEncrypted = Base64.Encode(authorizationHeaderContent, Encoding.UTF8); request.Headers.Authorization = new AuthorizationHeaderValue("Basic", authorizationHeaderEncrypted); }
public DefaultRequestExecutor( IHttpClient httpClient, IClientApiKey apiKey, AuthenticationScheme authenticationScheme, ILogger logger) : this(httpClient, apiKey, authenticationScheme, logger, new DefaultBackoffStrategy(MaxBackoffMilliseconds), new ThrottlingBackoffStrategy(MaxBackoffMilliseconds)) { }
internal void AuthenticateCore(IHttpRequest request, IClientApiKey apiKey, DateTimeOffset now) { request.Headers.Add(StormpathDateHeaderName, Iso8601.Format(now, withSeparators: false)); var authorizationHeaderContent = $"{apiKey.GetId()}:{apiKey.GetSecret()}"; var authorizationHeaderEncrypted = Base64.Encode(authorizationHeaderContent, Encoding.UTF8); request.Headers.Authorization = new AuthorizationHeaderValue("Basic", authorizationHeaderEncrypted); }
internal static void ThrowIfJwtSignatureInvalid(string jwtApiKey, IClientApiKey clientApiKey, IJwt jwt) { if (!clientApiKey.GetId().Equals(jwtApiKey, StringComparison.InvariantCultureIgnoreCase)) { throw new JwtSignatureException("The client used to sign the response is different than the one used in this DataStore."); } var signingKey = Encoding.UTF8.GetBytes(clientApiKey.GetSecret()); if (!new JwtSignatureValidator(signingKey).IsValid(jwt)) { throw new JwtSignatureException("The JWT signature is invalid."); } }
IClientBuilder IClientBuilder.SetApiKey(IClientApiKey apiKey) { if (apiKey == null) { throw new ArgumentNullException("API Key cannot be null."); } if (!apiKey.IsValid()) { throw new ArgumentException("API Key is not valid."); } this.apiKey = apiKey; return(this); }
public DefaultClient( IClientApiKey apiKey, string baseUrl, AuthenticationScheme authenticationScheme, int connectionTimeout, IWebProxy proxy, IHttpClient httpClient, IJsonSerializer serializer, ICacheProvider cacheProvider, IUserAgentBuilder userAgentBuilder, ILogger logger, TimeSpan identityMapExpiration) { if (apiKey == null || !apiKey.IsValid()) { throw new ArgumentException("API Key is not valid."); } if (string.IsNullOrEmpty(baseUrl)) { throw new ArgumentNullException("Base URL cannot be empty."); } if (connectionTimeout < 0) { throw new ArgumentException("Timeout cannot be negative."); } this.logger = logger; this.apiKey = apiKey; this.baseUrl = baseUrl; this.connectionTimeout = connectionTimeout; this.proxy = proxy; this.cacheProvider = cacheProvider; this.authenticationScheme = authenticationScheme; this.serializer = serializer; this.httpClient = httpClient; var requestExecutor = new DefaultRequestExecutor(httpClient, apiKey, authenticationScheme, this.logger); this.dataStore = new DefaultDataStore(this as IClient, requestExecutor, baseUrl, this.serializer, this.logger, userAgentBuilder, cacheProvider, identityMapExpiration); this.dataStoreAsync = this.dataStore as IInternalAsyncDataStore; this.dataStoreSync = this.dataStore as IInternalSyncDataStore; }
public DefaultClient( IClientApiKey apiKey, string baseUrl, AuthenticationScheme authenticationScheme, int connectionTimeout, IWebProxy proxy, IHttpClient httpClient, IJsonSerializer serializer, ICacheProvider cacheProvider, IUserAgentBuilder userAgentBuilder, ILogger logger, TimeSpan identityMapExpiration) { if (apiKey == null || !apiKey.IsValid()) { throw new ArgumentException("API Key is not valid."); } if (string.IsNullOrEmpty(baseUrl)) { throw new ArgumentNullException("Base URL cannot be empty."); } if (connectionTimeout < 0) { throw new ArgumentException("Timeout cannot be negative."); } this.logger = logger; this.apiKey = apiKey; this.baseUrl = baseUrl; this.connectionTimeout = connectionTimeout; this.proxy = proxy; this.cacheProvider = cacheProvider; this.authenticationScheme = authenticationScheme; this.serializer = serializer; this.httpClient = httpClient; var requestExecutor = new DefaultRequestExecutor(httpClient, apiKey, authenticationScheme, this.logger); this.dataStore = new DefaultDataStore(this as IClient, requestExecutor, baseUrl, this.serializer, this.logger, userAgentBuilder, cacheProvider, identityMapExpiration); this.dataStoreAsync = this.dataStore as IInternalAsyncDataStore; this.dataStoreSync = this.dataStore as IInternalSyncDataStore; }
public StubRequestExecutor(string resourceJson, IClientApiKey clientApiKey = null) { this.resourceJson = resourceJson; this.fakeRequestExecutor = Substitute.For<IRequestExecutor>(); // API Key this.fakeRequestExecutor.ApiKey.Returns(clientApiKey); // All GETs return 200 OK this.fakeRequestExecutor .ExecuteAsync( Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any<CancellationToken>()) .Returns( Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), resourceJson, "application/json", transportError: false) as IHttpResponse)); this.fakeRequestExecutor .Execute( Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Get)) .Returns(new DefaultHttpResponse(200, "OK", new HttpHeaders(), resourceJson, "application/json", transportError: false)); // All POSTs return 201 Created this.fakeRequestExecutor .ExecuteAsync( Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any<CancellationToken>()) .Returns( Task.FromResult(new DefaultHttpResponse(201, "Created", new HttpHeaders(), resourceJson, "application/json", transportError: false) as IHttpResponse)); this.fakeRequestExecutor .Execute( Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Post)) .Returns(new DefaultHttpResponse(201, "Created", new HttpHeaders(), resourceJson, "application/json", transportError: false)); // All DELETEs return 204 No Content this.fakeRequestExecutor .ExecuteAsync( Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Delete), Arg.Any<CancellationToken>()) .Returns( Task.FromResult(new DefaultHttpResponse(204, "No Content", new HttpHeaders(), null, null, transportError: false) as IHttpResponse)); this.fakeRequestExecutor .Execute( Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Delete)) .Returns(new DefaultHttpResponse(204, "No Content", new HttpHeaders(), null, null, transportError: false)); }
public StubRequestExecutor(string resourceJson, IClientApiKey clientApiKey = null) { this.resourceJson = resourceJson; this.fakeRequestExecutor = Substitute.For <IRequestExecutor>(); // API Key this.fakeRequestExecutor.ApiKey.Returns(clientApiKey); // All GETs return 200 OK this.fakeRequestExecutor .ExecuteAsync( Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any <CancellationToken>()) .Returns( Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), resourceJson, "application/json", transportError: false) as IHttpResponse)); this.fakeRequestExecutor .Execute( Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get)) .Returns(new DefaultHttpResponse(200, "OK", new HttpHeaders(), resourceJson, "application/json", transportError: false)); // All POSTs return 201 Created this.fakeRequestExecutor .ExecuteAsync( Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>()) .Returns( Task.FromResult(new DefaultHttpResponse(201, "Created", new HttpHeaders(), resourceJson, "application/json", transportError: false) as IHttpResponse)); this.fakeRequestExecutor .Execute( Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post)) .Returns(new DefaultHttpResponse(201, "Created", new HttpHeaders(), resourceJson, "application/json", transportError: false)); // All DELETEs return 204 No Content this.fakeRequestExecutor .ExecuteAsync( Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Delete), Arg.Any <CancellationToken>()) .Returns( Task.FromResult(new DefaultHttpResponse(204, "No Content", new HttpHeaders(), null, null, transportError: false) as IHttpResponse)); this.fakeRequestExecutor .Execute( Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Delete)) .Returns(new DefaultHttpResponse(204, "No Content", new HttpHeaders(), null, null, transportError: false)); }
internal void AuthenticateCore(IHttpRequest request, IClientApiKey apiKey, DateTimeOffset now, string nonce) { if (request == null) { throw new RequestAuthenticationException("Request must not be null."); } if (string.IsNullOrEmpty(request.CanonicalUri?.ToString())) { throw new RequestAuthenticationException("URL must not be empty."); } var uri = request.CanonicalUri.ToUri(); if (!uri.IsAbsoluteUri) { throw new RequestAuthenticationException("URL must be an absolute path."); } var relativeResourcePath = uri.AbsolutePath; var timestamp = Iso8601.Format(now, withSeparators: false); var dateStamp = now.ToString("yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture); // Add HOST header before signing var hostHeader = uri.Host; if (!uri.IsDefaultPort) { hostHeader = $"{hostHeader}:{uri.Port}"; } request.Headers.Host = hostHeader; // Add X-Stormpath-Date before signing request.Headers.Add(StormpathDateHeaderName, timestamp); var requestBody = request.Body.Nullable() ?? string.Empty; var requestBodyHash = ToHex(Hash(requestBody, Encoding.UTF8)); var sortedHeaderKeys = GetSortedHeaderNames(request.Headers); var canonicalRequest = new StringBuilder() .Append(request.Method.ToString().ToUpper()) .Append(Newline) .Append(CanonicalizeResourcePath(relativeResourcePath)) .Append(Newline) .Append(request.CanonicalUri.QueryString.ToString(canonical: true)) .Append(Newline) .Append(CanonicalizeHeaders(request)) .Append(Newline) .Append(sortedHeaderKeys) .Append(Newline) .Append(requestBodyHash) .ToString(); var id = new StringBuilder() .Append(apiKey.GetId()).Append("/") .Append(dateStamp).Append("/") .Append(nonce).Append("/") .Append(IDTerminator) .ToString(); var canonicalRequestHash = ToHex(Hash(canonicalRequest, Encoding.UTF8)); var stringToSign = new StringBuilder() .Append(Algorithm) .Append(Newline) .Append(timestamp) .Append(Newline) .Append(id) .Append(Newline) .Append(canonicalRequestHash) .ToString(); var secretFormat = $"{AuthenticationScheme}{apiKey.GetSecret()}"; byte[] secret = Encoding.UTF8.GetBytes(secretFormat); byte[] signedDate = SignHmac256(dateStamp, secret, Encoding.UTF8); byte[] signedNonce = SignHmac256(nonce, signedDate, Encoding.UTF8); byte[] signedTerminator = SignHmac256(IDTerminator, signedNonce, Encoding.UTF8); byte[] signature = SignHmac256(stringToSign, signedTerminator, Encoding.UTF8); var signatureHex = ToHex(signature); var authorizationHeaderValue = new StringBuilder() .Append(SAUTHC1Id).Append("=").Append(id).Append(", ") .Append(SAUTHC1SignedHeaders).Append("=").Append(sortedHeaderKeys).Append(", ") .Append(SAUTHC1Signature).Append("=").Append(signatureHex) .ToString(); request.Headers.Authorization = new AuthorizationHeaderValue(AuthenticationScheme, authorizationHeaderValue); }
void IRequestAuthenticator.Authenticate(IHttpRequest request, IClientApiKey apiKey) { var now = DateTimeOffset.UtcNow; var nonce = Guid.NewGuid().ToString(); this.AuthenticateCore(request, apiKey, now, nonce); }
void IRequestAuthenticator.Authenticate(IHttpRequest request, IClientApiKey apiKey) { var now = DateTimeOffset.UtcNow; this.AuthenticateCore(request, apiKey, now); }
internal void AuthenticateCore(IHttpRequest request, IClientApiKey apiKey, DateTimeOffset now, string nonce) { if (request == null) { throw new RequestAuthenticationException("Request must not be null."); } if (string.IsNullOrEmpty(request.CanonicalUri?.ToString())) { throw new RequestAuthenticationException("URL must not be empty."); } var uri = request.CanonicalUri.ToUri(); if (!uri.IsAbsoluteUri) { throw new RequestAuthenticationException("URL must be an absolute path."); } var relativeResourcePath = uri.AbsolutePath; var timestamp = Iso8601.Format(now, withSeparators: false); var dateStamp = now.ToString("yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture); // Add HOST header before signing var hostHeader = uri.Host; if (!uri.IsDefaultPort) { hostHeader = $"{hostHeader}:{uri.Port}"; } request.Headers.Host = hostHeader; // Add X-Stormpath-Date before signing request.Headers.Add(StormpathDateHeaderName, timestamp); var requestBody = request.Body.Nullable() ?? string.Empty; var requestBodyHash = ToHex(Hash(requestBody, Encoding.UTF8)); var sortedHeaderKeys = GetSortedHeaderNames(request.Headers); var canonicalRequest = new StringBuilder() .Append(request.Method.ToString().ToUpper()) .Append(Newline) .Append(CanonicalizeResourcePath(relativeResourcePath)) .Append(Newline) .Append(request.CanonicalUri.QueryString.ToString(canonical: true)) .Append(Newline) .Append(CanonicalizeHeaders(request)) .Append(Newline) .Append(sortedHeaderKeys) .Append(Newline) .Append(requestBodyHash) .ToString(); var id = new StringBuilder() .Append(apiKey.GetId()).Append("/") .Append(dateStamp).Append("/") .Append(nonce).Append("/") .Append(IDTerminator) .ToString(); var canonicalRequestHash = ToHex(Hash(canonicalRequest, Encoding.UTF8)); var stringToSign = new StringBuilder() .Append(Algorithm) .Append(Newline) .Append(timestamp) .Append(Newline) .Append(id) .Append(Newline) .Append(canonicalRequestHash) .ToString(); var secretFormat = $"{AuthenticationScheme}{apiKey.GetSecret()}"; byte[] secret = Encoding.UTF8.GetBytes(secretFormat); byte[] signedDate = SignHmac256(dateStamp, secret, Encoding.UTF8); byte[] signedNonce = SignHmac256(nonce, signedDate, Encoding.UTF8); byte[] signedTerminator = SignHmac256(IDTerminator, signedNonce, Encoding.UTF8); byte[] signature = SignHmac256(stringToSign, signedTerminator, Encoding.UTF8); var signatureHex = ToHex(signature); var authorizationHeaderValue = new StringBuilder() .Append(SAUTHC1Id).Append("=").Append(id).Append(", ") .Append(SAUTHC1SignedHeaders).Append("=").Append(sortedHeaderKeys).Append(", ") .Append(SAUTHC1Signature).Append("=").Append(signatureHex) .ToString(); request.Headers.Authorization = new AuthorizationHeaderValue(AuthenticationScheme, authorizationHeaderValue); }
IClient IClientBuilder.Build() { if (this.apiKey == null) { if (this.clientApiKeyBuilder != null) { this.apiKey = this.clientApiKeyBuilder.Build(); } else { throw new ApplicationException("No valid API Key and Secret could be found."); } } var logger = this.logger ?? new NullLogger(); IJsonSerializer serializer = null; if (this.overrideSerializer != null) { serializer = this.overrideSerializer; } else { if (this.serializerBuilder == null) { this.logger.Info("No serializer plugin specified, using default."); this.serializerBuilder = Serializers.Create().AutoDetect(); } serializer = this.serializerBuilder.Build(); } IHttpClient httpClient = null; if (this.overrideHttpClient != null) { httpClient = this.overrideHttpClient; } else { if (this.httpClientBuilder == null) { this.logger.Info("No HTTP client plugin specified, using default."); this.httpClientBuilder = HttpClients.Create().AutoDetect(); } this.httpClientBuilder .SetBaseUrl(this.baseUrl) .SetConnectionTimeout(this.connectionTimeout) .SetProxy(this.proxy) .SetLogger(this.logger); httpClient = this.httpClientBuilder.Build(); } if (this.cacheProvider == null) { this.logger.Info("No CacheProvider configured. Defaulting to in-memory CacheProvider with default TTL and TTI of one hour."); this.cacheProvider = Caches .NewInMemoryCacheProvider() .WithDefaultTimeToIdle(TimeSpan.FromHours(1)) .WithDefaultTimeToLive(TimeSpan.FromHours(1)) .Build(); } else { var injectableWithSerializer = this.cacheProvider as ISerializerConsumer <ICacheProvider>; if (injectableWithSerializer != null) { injectableWithSerializer.SetSerializer(serializer); } var injectableWithLogger = this.cacheProvider as ILoggerConsumer <ICacheProvider>; if (injectableWithLogger != null) { injectableWithLogger.SetLogger(this.logger); } } return(new DefaultClient( this.apiKey, this.baseUrl, this.authenticationScheme, this.connectionTimeout, this.proxy, httpClient, serializer, this.cacheProvider, this.userAgentBuilder, logger, DefaultIdentityMapSlidingExpiration)); }
internal static void ThrowIfJwtSignatureInvalid(string jwtApiKey, IClientApiKey clientApiKey, IJwt jwt) { if (!clientApiKey.GetId().Equals(jwtApiKey, StringComparison.InvariantCultureIgnoreCase)) { throw new JwtSignatureException("The client used to sign the response is different than the one used in this DataStore."); } var signingKey = Encoding.UTF8.GetBytes(clientApiKey.GetSecret()); if (!new JwtSignatureValidator(signingKey).IsValid(jwt)) { throw new JwtSignatureException("The JWT signature is invalid."); } }
public BasicRequestAuthenticator_tests() { this.uriQualifier = new UriQualifier(this.fakeBaseHref); this.authenticator = new BasicRequestAuthenticator(); this.apiKey = new DefaultClientApiKey(this.fakeApiKeyId, this.fakeApiKeySecret); }
void IRequestAuthenticator.Authenticate(IHttpRequest request, IClientApiKey apiKey) { var now = DateTimeOffset.UtcNow; this.AuthenticateCore(request, apiKey, now); }
public BasicRequestAuthenticator_tests() { this.uriQualifier = new UriQualifier(this.fakeBaseHref); this.authenticator = new BasicRequestAuthenticator(); this.apiKey = new DefaultClientApiKey(this.fakeApiKeyId, this.fakeApiKeySecret); }