public void Handle_error(string id_, string jwtResponse, Type expectedExceptionType, int expectedCode, int expectedStatus, string expectedMessage, string expectedDeveloperMessage)
        {
            var testApiKey = ClientApiKeys.Builder()
                .SetId("2EV70AHRTYF0JOA7OEFO3SM29")
                .SetSecret("goPUHQMkS4dlKwl5wtbNd91I+UrRehCsEDJrIrMruK8")
                .Build();
            var fakeRequestExecutor = Substitute.For<IRequestExecutor>();
            fakeRequestExecutor.ApiKey.Returns(testApiKey);

            this.dataStore = TestDataStore.Create(fakeRequestExecutor, Caches.NewInMemoryCacheProvider().Build());

            var request = new DefaultHttpRequest(HttpMethod.Get, new CanonicalUri($"https://foo.bar?{IdSiteClaims.JwtResponse}={jwtResponse}"));

            IIdSiteSyncCallbackHandler callbackHandler = new DefaultIdSiteSyncCallbackHandler(this.dataStore, request);

            try
            {
                var accountResult = callbackHandler.GetAccountResult();

                throw new Exception("Should not reach here. Proper exception was not thrown.");
            }
            catch (IdSiteRuntimeException e) when (expectedExceptionType.IsAssignableFrom(e.GetType()))
            {
                e.Code.ShouldBe(expectedCode);
                e.HttpStatus.ShouldBe(expectedStatus);
                e.Message.ShouldBe(expectedMessage);
                e.DeveloperMessage.ShouldBe(expectedDeveloperMessage);
            }
            catch (Exception e) when (expectedExceptionType.IsAssignableFrom(e.GetType()))
            {
                e.Message.ShouldStartWith(expectedMessage);
            }
        }
        public async Task Handle_error(string id_, string jwtResponse, Type expectedExceptionType, int expectedCode, int expectedStatus, string expectedMessage, string expectedDeveloperMessage)
        {
            var testApiKey = ClientApiKeys.Builder()
                             .SetId("2EV70AHRTYF0JOA7OEFO3SM29")
                             .SetSecret("goPUHQMkS4dlKwl5wtbNd91I+UrRehCsEDJrIrMruK8")
                             .Build();
            var fakeRequestExecutor = Substitute.For <IRequestExecutor>();

            fakeRequestExecutor.ApiKey.Returns(testApiKey);

            this.dataStore = TestDataStore.Create(fakeRequestExecutor, Caches.NewInMemoryCacheProvider().Build());

            var request = new DefaultHttpRequest(HttpMethod.Get, new CanonicalUri($"https://foo.bar?{IdSiteClaims.JwtResponse}={jwtResponse}"));

            IIdSiteAsyncCallbackHandler callbackHandler = new DefaultIdSiteAsyncCallbackHandler(this.dataStore, request);

            try
            {
                var accountResult = await callbackHandler.GetAccountResultAsync(CancellationToken.None);

                throw new Exception("Should not reach here. Proper exception was not thrown.");
            }
            catch (IdSiteRuntimeException e) when(expectedExceptionType.IsAssignableFrom(e.GetType()))
            {
                e.Code.ShouldBe(expectedCode);
                e.HttpStatus.ShouldBe(expectedStatus);
                e.Message.ShouldBe(expectedMessage);
                e.DeveloperMessage.ShouldBe(expectedDeveloperMessage);
            }
            catch (Exception e) when(expectedExceptionType.IsAssignableFrom(e.GetType()))
            {
                e.Message.ShouldStartWith(expectedMessage);
            }
        }
        public DefaultIdSiteUrlBuilder(IInternalDataStore internalDataStore, string applicationHref, IIdSiteJtiProvider jtiProvider, IClock clock)
        {
            if (internalDataStore == null)
            {
                throw new ArgumentNullException(nameof(internalDataStore));
            }

            if (string.IsNullOrEmpty(applicationHref))
            {
                throw new ArgumentNullException(nameof(applicationHref));
            }

            if (jtiProvider == null)
            {
                throw new ArgumentNullException(nameof(jtiProvider));
            }

            if (clock == null)
            {
                throw new ArgumentNullException(nameof(clock));
            }

            this.internalDataStore = internalDataStore;
            this.jtiProvider = jtiProvider;
            this.clock = clock;
            this.applicationHref = applicationHref;
            this.ssoEndpoint = GetBaseUrl(applicationHref) + "/sso";
        }
예제 #4
0
        public void Does_not_cache_password_reset_tokens()
        {
            var cacheProvider   = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            var passwordResetTokenResponse = @"
{
    ""href"": ""https://api.stormpath.com/v1/applications/foo/passwordResetTokens/bar"",
    ""email"": ""*****@*****.**"",
    ""account"": {
        ""href"": ""https://api.stormpath.com/v1/accounts/cJoiwcorTTmkDDBsf02bAb""
    }
}
";

            // POST returns token response
            requestExecutor
            .Execute(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post))
            .Returns(new DefaultHttpResponse(200, "OK", new HttpHeaders(), passwordResetTokenResponse, "application/json", transportError: false));

            // GET also returns token response
            requestExecutor
            .Execute(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get))
            .Returns(new DefaultHttpResponse(200, "OK", new HttpHeaders(), passwordResetTokenResponse, "application/json", transportError: false));

            this.dataStore.GetResource <IPasswordResetToken>("https://api.stormpath.com/v1/applications/foo/passwordResetTokens/bar");
            this.dataStore.GetResource <IPasswordResetToken>("https://api.stormpath.com/v1/applications/foo/passwordResetTokens/bar");

            // Not cached
            this.dataStore.RequestExecutor.Received(2).Execute(
                Arg.Any <IHttpRequest>());
        }
        public async Task Updating_resource_updates_cache()
        {
            var cacheProvider   = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            // GET returns original
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false) as IHttpResponse));

            // Save returns update data
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(201, "Created", new HttpHeaders(), FakeJson.Account.Replace("*****@*****.**", "*****@*****.**"), "application/json", transportError: false) as IHttpResponse));

            var account1 = await this.dataStore.GetResourceAsync <IAccount>("/accounts/foobarAccount");

            account1.Email.ShouldBe("*****@*****.**");

            account1.SetEmail("*****@*****.**");
            await account1.SaveAsync();

            account1.Email.ShouldBe("*****@*****.**");

            var account2 = await this.dataStore.GetResourceAsync <IAccount>("/accounts/foobarAccount");

            account2.Email.ShouldBe("*****@*****.**");

            // Only one GET; second is intercepted by the cache (but the updated data is returned!) #magic
            await this.dataStore.RequestExecutor.Received(1).ExecuteAsync(
                Arg.Is <IHttpRequest>(x => x.Method == HttpMethod.Get),
                Arg.Any <CancellationToken>());
        }
예제 #6
0
        public DefaultIdSiteUrlBuilder(IInternalDataStore internalDataStore, string applicationHref, IIdSiteJtiProvider jtiProvider, IClock clock)
        {
            if (internalDataStore == null)
            {
                throw new ArgumentNullException(nameof(internalDataStore));
            }

            if (string.IsNullOrEmpty(applicationHref))
            {
                throw new ArgumentNullException(nameof(applicationHref));
            }

            if (jtiProvider == null)
            {
                throw new ArgumentNullException(nameof(jtiProvider));
            }

            if (clock == null)
            {
                throw new ArgumentNullException(nameof(clock));
            }

            this.internalDataStore = internalDataStore;
            this.jtiProvider       = jtiProvider;
            this.clock             = clock;
            this.applicationHref   = applicationHref;
            this.ssoEndpoint       = GetBaseUrl(applicationHref) + "/sso";
        }
        public async Task Does_not_cache_email_verification_tokens()
        {
            var cacheProvider   = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            var emailVerificationTokenResponse = @"
{
    ""href"": ""https://api.stormpath.com/v1/accounts/foobarAccount""
}
";

            // POST returns email verification token response
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), emailVerificationTokenResponse, "application/json", transportError: false) as IHttpResponse));

            var href = $"/accounts/emailVerificationTokens/fooToken";

            await(this.dataStore as IInternalAsyncDataStore).CreateAsync <IResource, IEmailVerificationToken>(href, null, CancellationToken.None);
            await(this.dataStore as IInternalAsyncDataStore).CreateAsync <IResource, IEmailVerificationToken>(href, null, CancellationToken.None);

            // Not cached
            await this.dataStore.RequestExecutor.Received(2).ExecuteAsync(
                Arg.Any <IHttpRequest>(),
                Arg.Any <CancellationToken>());
        }
        public async Task Deleting_custom_data_with_proxy_updates_cache()
        {
            var cacheProvider = Caches.NewInMemoryCacheProvider().Build();

            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            // GET returns expanded request
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.AccountWithExpandedCustomData, "application/json", transportError: false) as IHttpResponse));

            // Save is not an expanded request
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(201, "Created", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false) as IHttpResponse));

            var account = await this.dataStore.GetResourceAsync <IAccount>("/accounts/foobarAccount?expand=customData");

            account.CustomData.Remove("isAdmin");
            await account.SaveAsync();

            var customData = await account.GetCustomDataAsync();

            customData["isAdmin"].ShouldBe(null);

            await this.dataStore.RequestExecutor.Received(1).ExecuteAsync(
                Arg.Is <IHttpRequest>(x => x.Method == HttpMethod.Get),
                Arg.Any <CancellationToken>());
        }
        public async Task Does_not_cache_login_attempts()
        {
            var cacheProvider   = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            var authResponse = @"
{
  ""account"": {
    ""href"" : ""https://api.stormpath.com/v1/accounts/5BedLIvyfLjdKKEEXAMPLE""
  }
}";

            // POST returns auth response
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), authResponse, "application/json", transportError: false) as IHttpResponse));

            var request       = new UsernamePasswordRequest("foo", "bar", null, null) as IAuthenticationRequest;
            var authenticator = new BasicAuthenticator(this.dataStore);

            var result1 = await authenticator.AuthenticateAsync("/loginAttempts", request, null, CancellationToken.None);

            var result2 = await authenticator.AuthenticateAsync("/loginAttempts", request, null, CancellationToken.None);

            // Not cached
            await this.dataStore.RequestExecutor.Received(2).ExecuteAsync(
                Arg.Any <IHttpRequest>(),
                Arg.Any <CancellationToken>());
        }
예제 #10
0
 public CollectionResourceExecutor(string collectionHref, IInternalDataStore dataStore, Expression expression)
 {
     this.collectionHref = collectionHref;
     this.asyncDataStore = dataStore as IInternalAsyncDataStore;
     this.syncDataStore  = dataStore as IInternalSyncDataStore;
     this.expression     = expression;
 }
예제 #11
0
        public void Updating_custom_data_with_proxy_updates_cache()
        {
            var cacheProvider   = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            // GET returns expanded request
            requestExecutor
            .Execute(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get))
            .Returns(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.AccountWithExpandedCustomData, "application/json", transportError: false));

            // Save is not an expanded request
            requestExecutor
            .Execute(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post))
            .Returns(new DefaultHttpResponse(201, "Created", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false));

            var account = this.dataStore.GetResource <IAccount>("/accounts/foobarAccount?expand=customData");

            account.CustomData.Put("isAdmin", true);
            account.CustomData.Put("writeAccess", "yes");
            account.Save();

            var customData = account.GetCustomData();

            customData["isAdmin"].ShouldBe(true);
            customData["writeAccess"].ShouldBe("yes");

            this.dataStore.RequestExecutor.Received(1).Execute(
                Arg.Is <IHttpRequest>(x => x.Method == HttpMethod.Get));
        }
예제 #12
0
        public ResourceData(IInternalDataStore dataStore)
        {
            this.internalDataStore      = dataStore;
            this.internalDataStoreAsync = dataStore as IInternalAsyncDataStore;
            this.internalDataStoreSync  = dataStore as IInternalSyncDataStore;

            this.Update();
        }
        public ResourceData(IInternalDataStore dataStore)
        {
            this.internalDataStore = dataStore;
            this.internalDataStoreAsync = dataStore as IInternalAsyncDataStore;
            this.internalDataStoreSync = dataStore as IInternalSyncDataStore;

            this.Update();
        }
        private static IAccount CreateAccountWith(IInternalDataStore dataStore, string givenName, string surname, string email, string password, object customData)
        {
            var account = dataStore.Instantiate<IAccount>();
            account.SetGivenName(givenName);
            account.SetSurname(surname);
            account.SetEmail(email);
            account.SetPassword(password);
            account.CustomData.Put(customData);

            return account;
        }
        public IAuthenticationResult Authenticate(IInternalDataStore dataStore, IApplication application, IAuthenticationRequest request, IRetrievalOptions<IAuthenticationResult> options)
        {
            Validate(dataStore, application, request);

            if (request is UsernamePasswordRequest)
            {
                return new BasicAuthenticator(dataStore).Authenticate(application.Href, request, options);
            }

            throw new InvalidOperationException($"The AuthenticationRequest {request.GetType().Name} is not supported by this implementation.");
        }
        public IAuthenticationResult Authenticate(IInternalDataStore dataStore, IApplication application, IAuthenticationRequest request, IRetrievalOptions <IAuthenticationResult> options)
        {
            Validate(dataStore, application, request);

            if (request is UsernamePasswordRequest)
            {
                return(new BasicAuthenticator(dataStore).Authenticate(application.Href, request, options));
            }

            throw new InvalidOperationException($"The AuthenticationRequest {request.GetType().Name} is not supported by this implementation.");
        }
        public BasicAuthenticator(IInternalDataStore dataStore)
        {
            this.dataStore = dataStore;
            this.dataStoreAsync = dataStore as IInternalAsyncDataStore;
            this.dataStoreSync = dataStore as IInternalSyncDataStore;

            if (this.dataStore == null ||
                this.dataStoreSync == null)
            {
                throw new ArgumentNullException("Internal data store could not be initialized.");
            }
        }
예제 #18
0
        public BasicAuthenticator(IInternalDataStore dataStore)
        {
            this.dataStore      = dataStore;
            this.dataStoreAsync = dataStore as IInternalAsyncDataStore;
            this.dataStoreSync  = dataStore as IInternalSyncDataStore;

            if (this.dataStore == null ||
                this.dataStoreSync == null)
            {
                throw new ArgumentNullException("Internal data store could not be initialized.");
            }
        }
예제 #19
0
        private static IAccount CreateAccountWith(IInternalDataStore dataStore, string givenName, string surname, string email, string password, object customData)
        {
            var account = dataStore.Instantiate <IAccount>();

            account.SetGivenName(givenName);
            account.SetSurname(surname);
            account.SetEmail(email);
            account.SetPassword(password);
            account.CustomData.Put(customData);

            return(account);
        }
        void INotifiable.OnUpdate(Map properties, IInternalDataStore dataStore)
        {
            var newProperties = new Dictionary<string, object>(2);

            bool hasProperties = !properties.IsNullOrEmpty();
            if (hasProperties)
            {
                newProperties.Add(IsNewAccountPropertyName, properties[IsNewAccountPropertyName]);
                properties.Remove(IsNewAccountPropertyName);

                var account = dataStore.InstantiateWithData<IAccount>(properties);
                newProperties.Add(AccountPropertyName, account);

                this.GetResourceData()?.Update(newProperties);
            }
        }
        private static void Validate(IInternalDataStore dataStore, IApplication application, IAuthenticationRequest request)
        {
            if (dataStore == null)
            {
                throw new ArgumentNullException(nameof(dataStore));
            }

            if (application == null)
            {
                throw new ArgumentNullException(nameof(application));
            }

            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
        }
        void INotifiable.OnUpdate(Map properties, IInternalDataStore dataStore)
        {
            var newProperties = new Dictionary <string, object>(2);

            bool hasProperties = !properties.IsNullOrEmpty();

            if (hasProperties)
            {
                newProperties.Add(IsNewAccountPropertyName, properties[IsNewAccountPropertyName]);
                properties.Remove(IsNewAccountPropertyName);

                var account = dataStore.InstantiateWithData <IAccount>(properties);
                newProperties.Add(AccountPropertyName, account);

                this.GetResourceData()?.Update(newProperties);
            }
        }
        private static void Validate(IInternalDataStore dataStore, IApplication application, IAuthenticationRequest request)
        {
            if (dataStore == null)
            {
                throw new ArgumentNullException(nameof(dataStore));
            }

            if (application == null)
            {
                throw new ArgumentNullException(nameof(application));
            }

            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }
        }
        public DefaultIdSiteSyncCallbackHandler(IInternalDataStore internalDataStore, IHttpRequest httpRequest)
        {
            if (internalDataStore == null)
            {
                throw new ArgumentNullException(nameof(internalDataStore));
            }

            if (httpRequest == null)
            {
                throw new ArgumentNullException(nameof(httpRequest));
            }

            this.internalDataStore = internalDataStore;
            this.jwtResponse       = HandlerShared.GetJwtResponse(httpRequest);

            this.nonceStore     = new DefaultNonceStore(internalDataStore.CacheResolver);
            this.syncNonceStore = this.nonceStore as ISynchronousNonceStore;
        }
        public DefaultIdSiteSyncCallbackHandler(IInternalDataStore internalDataStore, IHttpRequest httpRequest)
        {
            if (internalDataStore == null)
            {
                throw new ArgumentNullException(nameof(internalDataStore));
            }

            if (httpRequest == null)
            {
                throw new ArgumentNullException(nameof(httpRequest));
            }

            this.internalDataStore = internalDataStore;
            this.jwtResponse = HandlerShared.GetJwtResponse(httpRequest);

            this.nonceStore = new DefaultNonceStore(internalDataStore.CacheResolver);
            this.syncNonceStore = this.nonceStore as ISynchronousNonceStore;
        }
        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 async Task Email_verification_result_removes_associated_account_from_cache()
        {
            var cacheProvider   = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For <IRequestExecutor>();

            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            var emailVerificationTokenResponse = @"
{
    ""href"": ""https://api.stormpath.com/v1/accounts/foobarAccount""
}
";

            // POST returns email verification token response
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any <CancellationToken>())
            .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), emailVerificationTokenResponse, "application/json", transportError: false) as IHttpResponse));

            // GET returns account as unverified first,
            // then second GET returns account as verified
            requestExecutor
            .ExecuteAsync(Arg.Is <IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any <CancellationToken>())
            .Returns(
                Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.Account.Replace(@"""status"": ""ENABLED""", @"""status"": ""UNVERIFIED"""), "application/json", transportError: false) as IHttpResponse),
                Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false) as IHttpResponse));

            var account = await this.dataStore.GetResourceAsync <IAccount>("/accounts/foobarAccount");

            account.Status.ShouldBe(AccountStatus.Unverified);

            var href          = $"/accounts/emailVerificationTokens/fooToken";
            var tokenResponse = await(this.dataStore as IInternalAsyncDataStore).CreateAsync <IResource, IEmailVerificationToken>(href, null, CancellationToken.None);

            await this.dataStore.GetResourceAsync <IAccount>(tokenResponse.Href);

            account.Status.ShouldBe(AccountStatus.Enabled);

            // Second GET should *not* hit cache
            await this.dataStore.RequestExecutor.Received(2).ExecuteAsync(
                Arg.Is <IHttpRequest>(x => x.Method == HttpMethod.Get),
                Arg.Any <CancellationToken>());
        }
        internal static IAccountResult CreateAccountResult(IJwtClaims claims, IInternalDataStore dataStore)
        {
            var state = claims.GetClaim(IdSiteClaims.State);

            bool isNewAccount = (bool)claims.GetClaim(IdSiteClaims.IsNewSubject);
            var  resultStatus = GetResultStatus(claims);

            var properties = new Dictionary <string, object>()
            {
                [DefaultAccountResult.NewAccountPropertyName] = isNewAccount,
                [DefaultAccountResult.StatePropertyName]      = state,
                [DefaultAccountResult.StatusPropertyName]     = resultStatus,
            };

            var accountHref = GetAccountHref(claims);

            if (!string.IsNullOrEmpty(accountHref))
            {
                properties[DefaultAccountResult.AccountPropertyName] = new LinkProperty(accountHref);
            }

            return(dataStore.InstantiateWithData <IAccountResult>(properties));
        }
예제 #29
0
 public DefaultGoogleCreateProviderRequestBuilder(IInternalDataStore dataStore)
     : base(dataStore)
 {
 }
예제 #30
0
 public DefaultGoogleAccountRequestBuilder(IInternalDataStore dataStore)
     : base(dataStore)
 {
 }
예제 #31
0
 public DefaultFacebookAccountRequestBuilder(IInternalDataStore dataStore)
     : base(dataStore)
 {
 }
        public void Updating_custom_data_with_proxy_updates_cache()
        {
            var cacheProvider = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For<IRequestExecutor>();
            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            // GET returns expanded request
            requestExecutor
                .Execute(Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Get))
                .Returns(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.AccountWithExpandedCustomData, "application/json", transportError: false));

            // Save is not an expanded request
            requestExecutor
                .Execute(Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Post))
                .Returns(new DefaultHttpResponse(201, "Created", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false));

            var account = this.dataStore.GetResource<IAccount>("/accounts/foobarAccount?expand=customData");

            account.CustomData.Put("isAdmin", true);
            account.CustomData.Put("writeAccess", "yes");
            account.Save();

            var customData = account.GetCustomData();
            customData["isAdmin"].ShouldBe(true);
            customData["writeAccess"].ShouldBe("yes");

            this.dataStore.RequestExecutor.Received(1).Execute(
                Arg.Is<IHttpRequest>(x => x.Method == HttpMethod.Get));
        }
 public DefaultCustomDataProxy(IInternalDataStore dataStore, string parentHref)
 {
     this.proxy = dataStore.InstantiateWithHref<ICustomData>(GenerateProxyId(parentHref)) as DefaultCustomData;
     this.deleteAll = false;
 }
 public DefaultRefreshGrantAuthenticator(IApplication application, IInternalDataStore internalDataStore)
     : base(application, internalDataStore)
 {
 }
예제 #35
0
 public AbstractProviderAccountRequestBuilder(IInternalDataStore dataStore)
 {
     this.dataStore = dataStore;
 }
 public Entity_identity_map_tests()
 {
     this.dataStore = TestDataStore.Create(new StubRequestExecutor(FakeJson.Account).Object);
 }
예제 #37
0
        public void Handle_response(string id_, string jwtResponse, string expectedStatus, bool isNewAccount, string expectedState)
        {
            IAccountResult accountResultFromListener = null;

            var listener = new InlineIdSiteSyncResultListener(
                onAuthenticated: result =>
            {
                if (expectedStatus == IdSiteResultStatus.Authenticated)
                {
                    accountResultFromListener = result;
                }
                else
                {
                    throw new InvalidOperationException("This method should not have been executed");
                }
            },
                onLogout: result =>
            {
                if (expectedStatus == IdSiteResultStatus.Logout)
                {
                    accountResultFromListener = result;
                }
                else
                {
                    throw new InvalidOperationException("This method should not have been executed");
                }
            },
                onRegistered: result =>
            {
                if (expectedStatus == IdSiteResultStatus.Registered)
                {
                    accountResultFromListener = result;
                }
                else
                {
                    throw new InvalidOperationException("This method should not have been executed");
                }
            });

            var testApiKey          = ClientApiKeys.Builder().SetId("2EV70AHRTYF0JOA7OEFO3SM29").SetSecret("goPUHQMkS4dlKwl5wtbNd91I+UrRehCsEDJrIrMruK8").Build();
            var fakeRequestExecutor = Substitute.For <IRequestExecutor>();

            fakeRequestExecutor.ApiKey.Returns(testApiKey);

            this.dataStore = TestDataStore.Create(fakeRequestExecutor, Caches.NewInMemoryCacheProvider().Build());

            var request = new DefaultHttpRequest(HttpMethod.Get, new CanonicalUri($"https://foo.bar?{IdSiteClaims.JwtResponse}={jwtResponse}"));

            IIdSiteSyncCallbackHandler callbackHandler = new DefaultIdSiteSyncCallbackHandler(this.dataStore, request);

            callbackHandler.SetResultListener(listener);

            var accountResult = callbackHandler.GetAccountResult();

            // Validate result
            (accountResult as DefaultAccountResult).Account.Href.ShouldBe("https://api.stormpath.com/v1/accounts/7Ora8KfVDEIQP38KzrYdAs");
            (accountResultFromListener as DefaultAccountResult).Account.Href.ShouldBe("https://api.stormpath.com/v1/accounts/7Ora8KfVDEIQP38KzrYdAs");

            accountResult.IsNewAccount.ShouldBe(isNewAccount);
            accountResultFromListener.IsNewAccount.ShouldBe(isNewAccount);

            accountResult.State.ShouldBe(expectedState);
            accountResultFromListener.State.ShouldBe(expectedState);

            var expectedResultStatus = IdSiteResultStatus.Parse(expectedStatus);

            accountResult.Status.ShouldBe(expectedResultStatus);
            accountResultFromListener.Status.ShouldBe(expectedResultStatus);
        }
        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 async Task Updating_resource_updates_cache()
        {
            var cacheProvider = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For<IRequestExecutor>();
            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            // GET returns original
            requestExecutor
                .ExecuteAsync(Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any<CancellationToken>())
                .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false) as IHttpResponse));

            // Save returns update data
            requestExecutor
                .ExecuteAsync(Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any<CancellationToken>())
                .Returns(Task.FromResult(new DefaultHttpResponse(201, "Created", new HttpHeaders(), FakeJson.Account.Replace("*****@*****.**", "*****@*****.**"), "application/json", transportError: false) as IHttpResponse));

            var account1 = await this.dataStore.GetResourceAsync<IAccount>("/accounts/foobarAccount");
            account1.Email.ShouldBe("*****@*****.**");

            account1.SetEmail("*****@*****.**");
            await account1.SaveAsync();
            account1.Email.ShouldBe("*****@*****.**");

            var account2 = await this.dataStore.GetResourceAsync<IAccount>("/accounts/foobarAccount");
            account2.Email.ShouldBe("*****@*****.**");

            // Only one GET; second is intercepted by the cache (but the updated data is returned!) #magic
            await this.dataStore.RequestExecutor.Received(1).ExecuteAsync(
                Arg.Is<IHttpRequest>(x => x.Method == HttpMethod.Get),
                Arg.Any<CancellationToken>());
        }
예제 #40
0
 public AbstractGrantAuthenticator(IApplication application, IInternalDataStore internalDataStore)
 {
     this.application       = application;
     this.internalDataStore = internalDataStore;
 }
 public ProviderAccountResolver(IInternalDataStore dataStore)
 {
     this.dataStoreAsync = dataStore as IInternalAsyncDataStore;
     this.dataStoreSync = dataStore as IInternalSyncDataStore;
 }
예제 #42
0
 public DefaultLinkedInCreateProviderRequestBuilder(IInternalDataStore dataStore)
     : base(dataStore)
 {
 }
 public DefaultCustomData_tests()
 {
     this.dataStore = TestDataStore.Create();
 }
예제 #44
0
 public DefaultLinkedInAccountRequestBuilder(IInternalDataStore dataStore)
     : base(dataStore)
 {
 }
        internal static IAccountResult CreateAccountResult(IJwtClaims claims, IInternalDataStore dataStore)
        {
            var state = claims.GetClaim(IdSiteClaims.State);

            bool isNewAccount = (bool)claims.GetClaim(IdSiteClaims.IsNewSubject);
            var resultStatus = GetResultStatus(claims);

            var properties = new Dictionary<string, object>()
            {
                [DefaultAccountResult.NewAccountPropertyName] = isNewAccount,
                [DefaultAccountResult.StatePropertyName] = state,
                [DefaultAccountResult.StatusPropertyName] = resultStatus,
            };

            var accountHref = GetAccountHref(claims);
            if (!string.IsNullOrEmpty(accountHref))
            {
                properties[DefaultAccountResult.AccountPropertyName] = new LinkProperty(accountHref);
            }

            return dataStore.InstantiateWithData<IAccountResult>(properties);
        }
        public void Handle_response(string id_, string jwtResponse, string expectedStatus, bool isNewAccount, string expectedState)
        {
            IAccountResult accountResultFromListener = null;

            var listener = new InlineIdSiteSyncResultListener(
                onAuthenticated: result =>
                {
                    if (expectedStatus == IdSiteResultStatus.Authenticated)
                    {
                        accountResultFromListener = result;
                    }
                    else
                    {
                        throw new InvalidOperationException("This method should not have been executed");
                    }
                },
                onLogout: result =>
                {
                    if (expectedStatus == IdSiteResultStatus.Logout)
                    {
                        accountResultFromListener = result;
                    }
                    else
                    {
                        throw new InvalidOperationException("This method should not have been executed");
                    }
                },
                onRegistered: result =>
                {
                    if (expectedStatus == IdSiteResultStatus.Registered)
                    {
                        accountResultFromListener = result;
                    }
                    else
                    {
                        throw new InvalidOperationException("This method should not have been executed");
                    }
                });

            var testApiKey = ClientApiKeys.Builder().SetId("2EV70AHRTYF0JOA7OEFO3SM29").SetSecret("goPUHQMkS4dlKwl5wtbNd91I+UrRehCsEDJrIrMruK8").Build();
            var fakeRequestExecutor = Substitute.For<IRequestExecutor>();
            fakeRequestExecutor.ApiKey.Returns(testApiKey);

            this.dataStore = TestDataStore.Create(fakeRequestExecutor, Caches.NewInMemoryCacheProvider().Build());

            var request = new DefaultHttpRequest(HttpMethod.Get, new CanonicalUri($"https://foo.bar?{IdSiteClaims.JwtResponse}={jwtResponse}"));

            IIdSiteSyncCallbackHandler callbackHandler = new DefaultIdSiteSyncCallbackHandler(this.dataStore, request);
            callbackHandler.SetResultListener(listener);

            var accountResult = callbackHandler.GetAccountResult();

            // Validate result
            (accountResult as DefaultAccountResult).Account.Href.ShouldBe("https://api.stormpath.com/v1/accounts/7Ora8KfVDEIQP38KzrYdAs");
            (accountResultFromListener as DefaultAccountResult).Account.Href.ShouldBe("https://api.stormpath.com/v1/accounts/7Ora8KfVDEIQP38KzrYdAs");

            accountResult.IsNewAccount.ShouldBe(isNewAccount);
            accountResultFromListener.IsNewAccount.ShouldBe(isNewAccount);

            accountResult.State.ShouldBe(expectedState);
            accountResultFromListener.State.ShouldBe(expectedState);

            var expectedResultStatus = IdSiteResultStatus.Parse(expectedStatus);
            accountResult.Status.ShouldBe(expectedResultStatus);
            accountResultFromListener.Status.ShouldBe(expectedResultStatus);
        }
        private void BuildDataStore(string resourceResponse, ICacheProvider cacheProviderUnderTest)
        {
            var fakeRequestExecutor = new StubRequestExecutor(resourceResponse);

            this.dataStore = TestDataStore.Create(fakeRequestExecutor.Object, cacheProviderUnderTest);
        }
        public async Task Does_not_cache_login_attempts()
        {
            var cacheProvider = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For<IRequestExecutor>();
            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            var authResponse = @"
{
  ""account"": {
    ""href"" : ""https://api.stormpath.com/v1/accounts/5BedLIvyfLjdKKEEXAMPLE""
  }
}";

            // POST returns auth response
            requestExecutor
                .ExecuteAsync(Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any<CancellationToken>())
                .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), authResponse, "application/json", transportError: false) as IHttpResponse));

            var request = new UsernamePasswordRequest("foo", "bar", null, null) as IAuthenticationRequest;
            var authenticator = new BasicAuthenticator(this.dataStore);

            var result1 = await authenticator.AuthenticateAsync("/loginAttempts", request, null, CancellationToken.None);
            var result2 = await authenticator.AuthenticateAsync("/loginAttempts", request, null, CancellationToken.None);

            // Not cached
            await this.dataStore.RequestExecutor.Received(2).ExecuteAsync(
                Arg.Any<IHttpRequest>(),
                Arg.Any<CancellationToken>());
        }
 private static async Task GeneratedArgumentsWere(IInternalDataStore dataStore, string expectedQueryString)
 {
     await dataStore.RequestExecutor.Received(1).ExecuteAsync(
         Arg.Is<IHttpRequest>(x => x.CanonicalUri.QueryString.ToString() == expectedQueryString),
         Arg.Any<CancellationToken>());
 }
        public async Task Deleting_custom_data_with_proxy_updates_cache()
        {
            var cacheProvider = Caches.NewInMemoryCacheProvider().Build();

            var requestExecutor = Substitute.For<IRequestExecutor>();
            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            // GET returns expanded request
            requestExecutor
                .ExecuteAsync(Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any<CancellationToken>())
                .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.AccountWithExpandedCustomData, "application/json", transportError: false) as IHttpResponse));

            // Save is not an expanded request
            requestExecutor
                .ExecuteAsync(Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any<CancellationToken>())
                .Returns(Task.FromResult(new DefaultHttpResponse(201, "Created", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false) as IHttpResponse));

            var account = await this.dataStore.GetResourceAsync<IAccount>("/accounts/foobarAccount?expand=customData");
            account.CustomData.Remove("isAdmin");
            await account.SaveAsync();

            var customData = await account.GetCustomDataAsync();
            customData["isAdmin"].ShouldBe(null);

            await this.dataStore.RequestExecutor.Received(1).ExecuteAsync(
                Arg.Is<IHttpRequest>(x => x.Method == HttpMethod.Get),
                Arg.Any<CancellationToken>());
        }
 public DefaultProviderFactory(IInternalDataStore dataStore)
 {
     this.dataStore = dataStore;
 }
        private void BuildDataStore(string resourceResponse, ICacheProvider cacheProviderUnderTest)
        {
            var fakeRequestExecutor = new StubRequestExecutor(resourceResponse);

            this.dataStore = TestDataStore.Create(fakeRequestExecutor.Object, cacheProviderUnderTest);
        }
        public async Task Email_verification_result_removes_associated_account_from_cache()
        {
            var cacheProvider = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For<IRequestExecutor>();
            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            var emailVerificationTokenResponse = @"
{
    ""href"": ""https://api.stormpath.com/v1/accounts/foobarAccount""
}
";

            // POST returns email verification token response
            requestExecutor
                .ExecuteAsync(Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any<CancellationToken>())
                .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), emailVerificationTokenResponse, "application/json", transportError: false) as IHttpResponse));

            // GET returns account as unverified first,
            // then second GET returns account as verified
            requestExecutor
                .ExecuteAsync(Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any<CancellationToken>())
                .Returns(
                    Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.Account.Replace(@"""status"": ""ENABLED""", @"""status"": ""UNVERIFIED"""), "application/json", transportError: false) as IHttpResponse),
                    Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), FakeJson.Account, "application/json", transportError: false) as IHttpResponse));

            var account = await this.dataStore.GetResourceAsync<IAccount>("/accounts/foobarAccount");
            account.Status.ShouldBe(AccountStatus.Unverified);

            var href = $"/accounts/emailVerificationTokens/fooToken";
            var tokenResponse = await (this.dataStore as IInternalAsyncDataStore).CreateAsync<IResource, IEmailVerificationToken>(href, null, CancellationToken.None);
            await this.dataStore.GetResourceAsync<IAccount>(tokenResponse.Href);

            account.Status.ShouldBe(AccountStatus.Enabled);

            // Second GET should *not* hit cache
            await this.dataStore.RequestExecutor.Received(2).ExecuteAsync(
                Arg.Is<IHttpRequest>(x => x.Method == HttpMethod.Get),
                Arg.Any<CancellationToken>());
        }
 public DefaultGithubRequestFactory(IInternalDataStore dataStore)
 {
     this.dataStore = dataStore;
 }
        public async Task Does_not_cache_email_verification_tokens()
        {
            var cacheProvider = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For<IRequestExecutor>();
            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            var emailVerificationTokenResponse = @"
{
    ""href"": ""https://api.stormpath.com/v1/accounts/foobarAccount""
}
";

            // POST returns email verification token response
            requestExecutor
                .ExecuteAsync(Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any<CancellationToken>())
                .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), emailVerificationTokenResponse, "application/json", transportError: false) as IHttpResponse));

            var href = $"/accounts/emailVerificationTokens/fooToken";
            await (this.dataStore as IInternalAsyncDataStore).CreateAsync<IResource, IEmailVerificationToken>(href, null, CancellationToken.None);
            await (this.dataStore as IInternalAsyncDataStore).CreateAsync<IResource, IEmailVerificationToken>(href, null, CancellationToken.None);

            // Not cached
            await this.dataStore.RequestExecutor.Received(2).ExecuteAsync(
                Arg.Any<IHttpRequest>(),
                Arg.Any<CancellationToken>());
        }
 internal EmailVerificationRequestBuilder(IInternalDataStore dataStore)
 {
     this.InternalDataStore = dataStore;
 }
        public async Task Does_not_cache_password_reset_tokens()
        {
            var cacheProvider = Caches.NewInMemoryCacheProvider().Build();
            var requestExecutor = Substitute.For<IRequestExecutor>();
            this.dataStore = TestDataStore.Create(requestExecutor, cacheProvider);

            var passwordResetTokenResponse = @"
{
    ""href"": ""https://api.stormpath.com/v1/applications/foo/passwordResetTokens/bar"",
    ""email"": ""*****@*****.**"",
    ""account"": {
        ""href"": ""https://api.stormpath.com/v1/accounts/cJoiwcorTTmkDDBsf02bAb""
    }
}
";

            // POST returns token response
            requestExecutor
                .ExecuteAsync(Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Post), Arg.Any<CancellationToken>())
                .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), passwordResetTokenResponse, "application/json", transportError: false) as IHttpResponse));

            // GET also returns token response
            requestExecutor
                .ExecuteAsync(Arg.Is<IHttpRequest>(req => req.Method == HttpMethod.Get), Arg.Any<CancellationToken>())
                .Returns(Task.FromResult(new DefaultHttpResponse(200, "OK", new HttpHeaders(), passwordResetTokenResponse, "application/json", transportError: false) as IHttpResponse));

            await this.dataStore.GetResourceAsync<IPasswordResetToken>("https://api.stormpath.com/v1/applications/foo/passwordResetTokens/bar");
            await this.dataStore.GetResourceAsync<IPasswordResetToken>("https://api.stormpath.com/v1/applications/foo/passwordResetTokens/bar");

            // Not cached
            await this.dataStore.RequestExecutor.Received(2).ExecuteAsync(
                Arg.Any<IHttpRequest>(),
                Arg.Any<CancellationToken>());
        }