예제 #1
0
        private async Task <bool> ExecutePasswordFlow(IOwinEnvironment context, IClient client, string username, string password, CancellationToken cancellationToken)
        {
            var preLoginContext = new PreLoginContext(context)
            {
                Login = username
            };
            await _handlers.PreLoginHandler(preLoginContext, cancellationToken);

            var passwordGrantRequestBuilder = OauthRequests.NewPasswordGrantRequest()
                                              .SetLogin(preLoginContext.Login)
                                              .SetPassword(password);

            if (preLoginContext.AccountStore != null)
            {
                passwordGrantRequestBuilder.SetAccountStore(preLoginContext.AccountStore);
            }

            var passwordGrantRequest = passwordGrantRequestBuilder.Build();

            var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken);

            var tokenResult = await application.NewPasswordGrantAuthenticator()
                              .AuthenticateAsync(passwordGrantRequest, cancellationToken);

            var accessToken = await tokenResult.GetAccessTokenAsync(cancellationToken);

            var account = await accessToken.GetAccountAsync(cancellationToken);

            var postLoginContext = new PostLoginContext(context, account);
            await _handlers.PostLoginHandler(postLoginContext, cancellationToken);

            var sanitizer = new GrantResultResponseSanitizer();

            return(await JsonResponse.Ok(context, sanitizer.SanitizeResponseWithRefreshToken(tokenResult)).ConfigureAwait(false));
        }
예제 #2
0
        protected override Task <bool> GetJsonAsync(IOwinEnvironment context, IClient client, CancellationToken cancellationToken)
        {
            var viewModelBuilder = new LoginViewModelBuilder(_configuration.Web.Login, _configuration.Providers);
            var loginViewModel   = viewModelBuilder.Build();

            return(JsonResponse.Ok(context, loginViewModel));
        }
예제 #3
0
        protected override Task <bool> GetJsonAsync(IOwinEnvironment context, IClient client, CancellationToken cancellationToken)
        {
            var viewModelBuilder  = new RegisterViewModelBuilder(_configuration.Web.Register);
            var registerViewModel = viewModelBuilder.Build();

            return(JsonResponse.Ok(context, registerViewModel));
        }
        protected override async Task <bool> PostJsonAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken)
        {
            var body = await context.Request.GetBodyAsStringAsync(cancellationToken);

            var model    = PostBodyParser.ToModel <RegisterPostModel>(body, bodyContentType, _logger);
            var formData = Serializer.DeserializeDictionary(body);

            var allNonEmptyFieldNames = formData.Where(f => !string.IsNullOrEmpty(f.Value.ToString())).Select(f => f.Key).ToList();

            var providedCustomFields = new Dictionary <string, object>();

            foreach (var item in formData.Where(x => !DefaultFields.Contains(x.Key)))
            {
                providedCustomFields.Add(item.Key, item.Value);
            }

            var customDataObject = formData.Get <IDictionary <string, object> >("customData");

            if (customDataObject != null && customDataObject.Any())
            {
                foreach (var item in customDataObject)
                {
                    providedCustomFields.Add(item.Key, item.Value);
                }
            }

            var jsonErrorHandler = new Func <string, CancellationToken, Task>((message, ct)
                                                                              => Error.Create(context, new BadRequest(message), ct));

            var newAccount = await InstantiateLocalAccount(
                context,
                model,
                allNonEmptyFieldNames,
                providedCustomFields,
                client,
                jsonErrorHandler,
                cancellationToken);

            if (newAccount == null)
            {
                return(true); // Some error occurred and the handler was invoked
            }

            var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken);

            var executor = new RegisterExecutor(client, _configuration, _handlers, _logger);

            var createdAccount = await executor.HandleRegistrationAsync(context, application, newAccount, cancellationToken);

            await executor.HandlePostRegistrationAsync(context, createdAccount, cancellationToken);

            var sanitizer     = new AccountResponseSanitizer();
            var responseModel = new
            {
                account = sanitizer.Sanitize(createdAccount)
            };

            return(await JsonResponse.Ok(context, responseModel));
        }
예제 #5
0
        protected override async Task <bool> PostJsonAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken)
        {
            var executor = new LogoutExecutor(client, _configuration, _handlers, _logger);
            await executor.HandleLogoutAsync(context, cancellationToken);

            await JsonResponse.Ok(context);

            return(true);
        }
예제 #6
0
        private async Task <bool> ExecuteClientCredentialsFlow(IOwinEnvironment context, IClient client, CancellationToken cancellationToken)
        {
            var basicHeaderParser = new BasicAuthenticationParser(context.Request.Headers.GetString("Authorization"), _logger);

            if (!basicHeaderParser.IsValid)
            {
                await Error.Create <OauthInvalidRequest>(context, cancellationToken);

                return(true);
            }

            var preLoginContext = new PreLoginContext(context)
            {
                Login = basicHeaderParser.Username
            };
            await _handlers.PreLoginHandler(preLoginContext, cancellationToken).ConfigureAwait(false);

            var request = new ClientCredentialsGrantRequest
            {
                Id     = basicHeaderParser.Username,
                Secret = basicHeaderParser.Password
            };

            if (preLoginContext.AccountStore != null)
            {
                request.AccountStoreHref = preLoginContext.AccountStore.Href;
            }

            var application = await client
                              .GetApplicationAsync(_configuration.Application.Href, cancellationToken)
                              .ConfigureAwait(false);

            IOauthGrantAuthenticationResult tokenResult;

            try
            {
                tokenResult = await application
                              .ExecuteOauthRequestAsync(request, cancellationToken)
                              .ConfigureAwait(false);
            }
            // Catch error 10019 (API Authentication failed)
            catch (ResourceException rex) when(rex.Code == 10019)
            {
                return(await Error.Create <OauthInvalidClient>(context, cancellationToken).ConfigureAwait(false));
            }

            var accessToken = await tokenResult.GetAccessTokenAsync(cancellationToken).ConfigureAwait(false);

            var account = await accessToken.GetAccountAsync(cancellationToken).ConfigureAwait(false);

            var postLoginContext = new PostLoginContext(context, account);
            await _handlers.PostLoginHandler(postLoginContext, cancellationToken).ConfigureAwait(false);

            var sanitizer = new GrantResultResponseSanitizer();

            return(await JsonResponse.Ok(context, sanitizer.SanitizeResponseWithoutRefreshToken(tokenResult)).ConfigureAwait(false));
        }
예제 #7
0
        protected override async Task <bool> PostJsonAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken)
        {
            var model = await PostBodyParser.ToModel <LoginPostModel>(context, bodyContentType, _logger, cancellationToken);

            if (model.ProviderData != null)
            {
                return(await HandleSocialLogin(context, client, model, cancellationToken));
            }

            var jsonErrorHandler = new Func <string, CancellationToken, Task>((message, ct)
                                                                              => Error.Create(context, new BadRequest(message), ct));

            bool missingLoginOrPassword = string.IsNullOrEmpty(model.Login) || string.IsNullOrEmpty(model.Password);

            if (missingLoginOrPassword)
            {
                await jsonErrorHandler("Missing login or password.", cancellationToken);

                return(true);
            }

            var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken);

            var executor = new LoginExecutor(client, _configuration, _handlers, _logger);

            var grantResult = await executor.PasswordGrantAsync(
                context,
                application,
                jsonErrorHandler,
                model.Login,
                model.Password,
                cancellationToken);

            if (grantResult == null)
            {
                return(true); // The error handler was invoked
            }

            await executor.HandlePostLoginAsync(context, grantResult, cancellationToken);

            var token = await grantResult.GetAccessTokenAsync(cancellationToken);

            var account = await token.GetAccountAsync(cancellationToken);

            var sanitizer     = new AccountResponseSanitizer();
            var responseModel = new
            {
                account = sanitizer.Sanitize(account)
            };

            return(await JsonResponse.Ok(context, responseModel));
        }
예제 #8
0
        private async Task <bool> ExecuteRefreshFlow(IOwinEnvironment context, IClient client, string refreshToken, CancellationToken cancellationToken)
        {
            var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken);

            var refreshGrantRequest = OauthRequests.NewRefreshGrantRequest()
                                      .SetRefreshToken(refreshToken)
                                      .Build();

            var tokenResult = await application.NewRefreshGrantAuthenticator()
                              .AuthenticateAsync(refreshGrantRequest, cancellationToken);

            var sanitizer = new GrantResultResponseSanitizer();

            return(await JsonResponse.Ok(context, sanitizer.SanitizeResponseWithRefreshToken(tokenResult)).ConfigureAwait(false));
        }
예제 #9
0
        protected override async Task <bool> PostJsonAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken)
        {
            var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken);

            try
            {
                var model = await PostBodyParser.ToModel <ForgotPasswordPostModel>(context, bodyContentType, _logger, cancellationToken);

                await application.SendPasswordResetEmailAsync(model.Email, cancellationToken);
            }
            catch (Exception ex)
            {
                _logger.Error(ex, source: "ForgotRoute.PostJson");
            }

            return(await JsonResponse.Ok(context));
        }
예제 #10
0
        protected override async Task <bool> PostAsync(
            IOwinEnvironment context,
            IClient client,
            ContentNegotiationResult acceptContentNegotiationResult,
            CancellationToken cancellationToken)
        {
            var executor = new LogoutExecutor(client, _configuration, _handlers, _logger);
            await executor.HandleLogoutAsync(context, cancellationToken);

            if (acceptContentNegotiationResult.ContentType == ContentType.Html)
            {
                return(await executor.HandleRedirectAsync(context));
            }

            await JsonResponse.Ok(context);

            return(true);
        }
예제 #11
0
        protected override async Task <bool> GetJsonAsync(IOwinEnvironment context, IClient client, CancellationToken cancellationToken)
        {
            var queryString = QueryStringParser.Parse(context.Request.QueryString, _logger);
            var spToken     = queryString.GetString("sptoken");

            if (string.IsNullOrEmpty(spToken))
            {
                return(await Error.Create(context, new BadRequest("sptoken parameter not provided."), cancellationToken));
            }

            var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken);

            await application.VerifyPasswordResetTokenAsync(spToken, cancellationToken);

            // Errors are caught in AbstractRouteMiddleware

            return(await JsonResponse.Ok(context));
        }
예제 #12
0
        protected override async Task <bool> GetJsonAsync(IOwinEnvironment context, IClient client, CancellationToken cancellationToken)
        {
            var queryString = QueryStringParser.Parse(context.Request.QueryString, _logger);
            var spToken     = queryString.GetString("sptoken");

            if (string.IsNullOrEmpty(spToken))
            {
                return(await Error.Create(context, new BadRequest("sptoken parameter not provided."), cancellationToken));
            }

            var account = await client.VerifyAccountEmailAsync(spToken, cancellationToken);

            // Errors are caught in AbstractRouteMiddleware

            var postVerifyEmailContext = new PostVerifyEmailContext(context, account);
            await _handlers.PostVerifyEmailHandler(postVerifyEmailContext, cancellationToken);

            return(await JsonResponse.Ok(context));
        }
        protected override async Task <bool> GetJsonAsync(IOwinEnvironment context, IClient client, CancellationToken cancellationToken)
        {
            Caching.AddDoNotCacheHeaders(context);

            var stormpathAccount = context.Request[OwinKeys.StormpathUser] as IAccount;

            var expansionOptions = _configuration.Web.Me.Expand;

            if (expansionOptions.Any(e => e.Value))
            {
                stormpathAccount = await GetExpandedAccount(stormpathAccount.Href, client, expansionOptions, cancellationToken);
            }

            var responseModel = new
            {
                account = await SanitizeExpandedAccount(stormpathAccount, expansionOptions, cancellationToken)
            };

            return(await JsonResponse.Ok(context, responseModel));
        }
        private async Task <bool> ExecutePasswordFlow(IOwinEnvironment context, IClient client, string username, string password, CancellationToken cancellationToken)
        {
            var executor    = new LoginExecutor(client, _configuration, _handlers, _logger);
            var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken);

            var jsonErrorHandler = new Func <string, CancellationToken, Task>((message, ct)
                                                                              => Error.Create(context, new BadRequest(message), ct));

            var grantResult = await executor.PasswordGrantAsync(
                context,
                application,
                jsonErrorHandler,
                username,
                password,
                cancellationToken);

            await executor.HandlePostLoginAsync(context, grantResult, cancellationToken);

            var sanitizer = new GrantResultResponseSanitizer();

            return(await JsonResponse.Ok(context, sanitizer.SanitizeResponseWithRefreshToken(grantResult)).ConfigureAwait(false));
        }
예제 #15
0
        protected override async Task <bool> PostJsonAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken)
        {
            var model = await PostBodyParser.ToModel <ChangePasswordPostModel>(context, bodyContentType, _logger, cancellationToken);

            var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken);

            var account = await application.VerifyPasswordResetTokenAsync(model.SpToken, cancellationToken);

            // Errors are caught in AbstractRouteMiddleware

            var preChangePasswordContext = new PreChangePasswordContext(context, account);
            await _handlers.PreChangePasswordHandler(preChangePasswordContext, cancellationToken);

            await application.ResetPasswordAsync(model.SpToken, model.Password, cancellationToken);

            var postChangePasswordContext = new PostChangePasswordContext(context, account);
            await _handlers.PostChangePasswordHandler(postChangePasswordContext, cancellationToken);

            // TODO autologin

            return(await JsonResponse.Ok(context));
        }
        private async Task <bool> ExecuteClientCredentialsFlow(IOwinEnvironment context, IClient client, CancellationToken cancellationToken)
        {
            var jsonErrorHandler = new Func <AbstractError, CancellationToken, Task>((err, ct)
                                                                                     => Error.Create(context, err, ct));

            var basicHeaderParser = new BasicAuthenticationParser(context.Request.Headers.GetString("Authorization"), _logger);

            if (!basicHeaderParser.IsValid)
            {
                await jsonErrorHandler(new OauthInvalidRequest(), cancellationToken);

                return(true);
            }

            var executor    = new LoginExecutor(client, _configuration, _handlers, _logger);
            var application = await client
                              .GetApplicationAsync(_configuration.Application.Href, cancellationToken)
                              .ConfigureAwait(false);

            var tokenResult = await executor.ClientCredentialsGrantAsync(
                context,
                application,
                jsonErrorHandler,
                basicHeaderParser.Username,
                basicHeaderParser.Password,
                cancellationToken);

            if (tokenResult == null)
            {
                return(true); // Some error occurred and the handler was invoked
            }

            await executor.HandlePostLoginAsync(context, tokenResult, cancellationToken);

            var sanitizer = new GrantResultResponseSanitizer();

            return(await JsonResponse.Ok(context, sanitizer.SanitizeResponseWithoutRefreshToken(tokenResult)).ConfigureAwait(false));
        }
예제 #17
0
        protected JsonResult JsonSuccess(object data)
        {
            var result = JsonResponse.Ok(data);

            return(Json(result));
        }
예제 #18
0
        protected override async Task <bool> PostJsonAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken)
        {
            var model = await PostBodyParser.ToModel <VerifyEmailPostModel>(context, bodyContentType, _logger, cancellationToken);

            var jsonSuccessHandler = new Func <CancellationToken, Task <bool> >(ct => JsonResponse.Ok(context));

            return(await ResendVerification(
                       email : model.Email,
                       client : client,
                       environment : context,
                       errorHandler : null, // Errors are caught in AbstractRouteMiddleware
                       successHandler : jsonSuccessHandler,
                       cancellationToken : cancellationToken));
        }
예제 #19
0
        protected override async Task <bool> PostJsonAsync(IOwinEnvironment context, IClient client, ContentType bodyContentType, CancellationToken cancellationToken)
        {
            var body = await context.Request.GetBodyAsStringAsync(cancellationToken);

            var model    = PostBodyParser.ToModel <RegisterPostModel>(body, bodyContentType, _logger);
            var formData = Serializer.DeserializeDictionary(body);

            var sanitizedFormData = new Dictionary <string, string>();
            var customFields      = new Dictionary <string, string>();

            // Look for a root object called "customData"
            var customDataObject = formData.Get <IDictionary <string, object> >("customData");

            if (customDataObject != null && customDataObject.Any())
            {
                foreach (var field in customDataObject)
                {
                    TryAdd(formData, field.Key, field.Value);
                }
            }

            foreach (var field in formData)
            {
                // The key "customData" is a special case, see above
                if (field.Key.Equals("customData", StringComparison.Ordinal))
                {
                    continue;
                }

                if (!DefaultFields.Contains(field.Key))
                {
                    TryAdd(customFields, field.Key, field.Value?.ToString());
                }

                TryAdd(sanitizedFormData, field.Key, field.Value?.ToString());
            }

            var allNonEmptyFieldNames = sanitizedFormData
                                        .Where(f => !string.IsNullOrEmpty(f.Value.ToString()))
                                        .Select(f => f.Key)
                                        .Distinct()
                                        .ToArray();

            var jsonErrorHandler = new Func <string, CancellationToken, Task>((message, ct)
                                                                              => Error.Create(context, new BadRequest(message), ct));

            var newAccount = await InstantiateLocalAccount(
                context,
                model,
                allNonEmptyFieldNames,
                customFields,
                client,
                jsonErrorHandler,
                cancellationToken);

            if (newAccount == null)
            {
                return(true); // Some error occurred and the handler was invoked
            }

            var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken);

            var executor = new RegisterExecutor(client, _configuration, _handlers, _logger);

            var formDataForHandler = sanitizedFormData
                                     .ToDictionary(kv => kv.Key, kv => kv.Value?.ToString());

            var createdAccount = await executor.HandleRegistrationAsync(
                context,
                application,
                formDataForHandler,
                newAccount,
                jsonErrorHandler,
                cancellationToken);

            if (createdAccount == null)
            {
                return(true); // Some error occurred and the handler was invoked
            }

            await executor.HandlePostRegistrationAsync(context, createdAccount, cancellationToken);

            var sanitizer     = new AccountResponseSanitizer();
            var responseModel = new
            {
                account = sanitizer.Sanitize(createdAccount)
            };

            return(await JsonResponse.Ok(context, responseModel));
        }
예제 #20
0
        private async Task <bool> HandleSocialLogin(IOwinEnvironment context, IClient client, LoginPostModel model,
                                                    CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(model.ProviderData.ProviderId))
            {
                return(await Error.Create(context, new BadRequest("No provider specified"), cancellationToken));
            }

            var application = await client.GetApplicationAsync(_configuration.Application.Href, cancellationToken);

            var socialExecutor = new SocialExecutor(client, _configuration, _handlers, _logger);

            try
            {
                IProviderAccountRequest providerRequest;

                switch (model.ProviderData.ProviderId)
                {
                case "facebook":
                {
                    providerRequest = client.Providers()
                                      .Facebook()
                                      .Account()
                                      .SetAccessToken(model.ProviderData.AccessToken)
                                      .Build();
                    break;
                }

                case "google":
                {
                    providerRequest = client.Providers()
                                      .Google()
                                      .Account()
                                      .SetCode(model.ProviderData.Code)
                                      .Build();
                    break;
                }

                case "github":
                {
                    providerRequest = client.Providers()
                                      .Github()
                                      .Account()
                                      .SetAccessToken(model.ProviderData.AccessToken)
                                      .Build();
                    break;
                }

                case "linkedin":
                {
                    providerRequest = client.Providers()
                                      .LinkedIn()
                                      .Account()
                                      .SetAccessToken(model.ProviderData.AccessToken)
                                      .Build();
                    break;
                }

                default:
                    providerRequest = null;
                    break;
                }

                if (providerRequest == null)
                {
                    return(await Error.Create(context,
                                              new BadRequest($"Unknown provider '{model.ProviderData.ProviderId}'"), cancellationToken));
                }

                var loginResult =
                    await socialExecutor.LoginWithProviderRequestAsync(context, providerRequest, cancellationToken);

                await socialExecutor.HandleLoginResultAsync(
                    context,
                    application,
                    loginResult,
                    cancellationToken);

                var sanitizer     = new AccountResponseSanitizer();
                var responseModel = new
                {
                    account = sanitizer.Sanitize(loginResult.Account)
                };

                return(await JsonResponse.Ok(context, responseModel));
            }
            catch (ResourceException rex)
            {
                // TODO improve error logging (include request id, etc)
                _logger.Error(rex.DeveloperMessage, source: nameof(HandleSocialLogin));
                return(await Error.Create(context, new BadRequest("An error occurred while processing the login"), cancellationToken));
            }
            catch (Exception ex)
            {
                _logger.Error(ex, source: nameof(HandleSocialLogin));
                return(await Error.Create(context, new BadRequest("An error occurred while processing the login"), cancellationToken));
            }
        }