I am trying to work through the MVC client quickstart but running into an "object reference not set ..." error at the line - "#foreach (var prop in (await Context.AuthenticateAsync()).Properties.Items)" from inside my Index.cshtml that I modified following the quickstart doc. Below is the complete Index.cshtml. Could somebody tell me what I am doing wrong here?
#using Microsoft.AspNetCore.Authentication
<h2>Claims</h2>
<dl>
#foreach (var claim in User.Claims)
{
<dt>#claim.Type</dt>
<dd>#claim.Value</dd>
}
</dl>
<h2>Properties</h2>
<dl>
#foreach (var prop in (await Context.AuthenticateAsync()).Properties.Items)
{
<dt>#prop.Key</dt>
<dd>#prop.Value</dd>
}
</dl>
You are missing .RequireAuthorization(); on this part of code:
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute()
.RequireAuthorization();
});
The RequireAuthorization method disables anonymous access for the entire application.
Here I have a working example to follow: https://github.com/nahidf/IdentityServer4-adventures/tree/master/src/MvcClient
Related
I'm using CakePHP 3.8 to create a CMS for a website. I need a simple WYSIWYG editor with image upload. I'd previously used CKEditor, but was having problems getting the image upload working, so thought I'd try TinyMCE instead.
So, I downloaded TinyMCE 5 (with all standard plugins), linked it in in the head section of my page, and created a form with a TinyMCE textarea like this:
<fieldset>
<legend>New Page</legend>
<?php
echo $this->Flash->render();
echo $this->Form->create($newpage);
echo $this->Form->control('title');
echo $this->Form->control('content',
array('label' => 'Page Content',
'type' => 'textarea',
'id' => 'editor_area'));
echo $this->Form->button('Save');
echo $this->Form->end();
?>
</fieldset>
<script>
tinymce.init({
selector:'#editor_area',
height: 500,
menubar: false,
images_upload_url: '<?php echo IMG_UPLOAD_URL ?>',
toolbar: [
'undo redo | cut copy paste | styleselect | bold italic underline removeformat | alignleft aligncenter alignright | charmap | bullist numlist | link image'
],
plugins: ['advlist lists link autolink image charmap imagetools code']
});
</script>
This works fine, text area appears with the editor etc. The upload url in images_upload_url points to the following UploadsController.php (I've left out the details for brevity; can add them in if needed):
<?php
namespace App\Controller\Admin;
use App\Controller\AppController;
class UploadsController extends AppController
{
public function uploadImage() {
$result = array();
$result['success'] = 'success';
// Process file upload
return $this->response->withType('application/json')
->withStringBody(json_encode($result));
}
}
When I upload an image, I get the following error in the console:
Failed to load resource: the server responded with a status of 403 (Forbidden)
The output from CakePHP shows the error:
Error: CSRF token mismatch.
The debugger shows that the POST includes the following:
Cookie: CAKEPHP=dvsktjv7vp8la5nv7dv19634d1; csrfToken=53e5718e13a1e963d51f9c93c48471a478b35c02b565d6f0699cd2a335775c2b17986cfc2cc587ff7343a6573e3eb2e498a9cb962397599c023417d1dfa9506c; ckCsrfToken=7l2PEC0g06819qQcLwdX5ul7E7jNRa3r61jENt2x
I'm not sure where to go from here.
(Or if there's a more straightforward way to include a free/inexpensive WYSIWYG editor with a decent image/file uploader, I'm open to suggestions! It's a website for a school, so budget is very small and can't be a monthly cost.)
The cookie data is only one part of the CSRF protection mechanism, the client needs to send the CSRF token in either the request data or the X-CSRF-Token header too.
I'm not overly familiar with TinyMCE image uploads, but looking at the docs, you'll probably need a custom upload handler, where you can add additional data, the CSRF token that is.
Taking the example from the TinyMCE docs, the handler could look something like this, where the CSRF token is appended to the form data:
images_upload_handler: function (blobInfo, success, failure) {
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.withCredentials = false;
xhr.open('POST', <?= json_encode(IMG_UPLOAD_URL) ?>);
xhr.onload = function() {
var json;
if (xhr.status != 200) {
failure('HTTP Error: ' + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != 'string') {
failure('Invalid JSON: ' + xhr.responseText);
return;
}
success(json.location);
};
formData = new FormData();
formData.append('file', blobInfo.blob(), blobInfo.filename());
// append CSRF token in the form data
formData.append('_csrfToken', <?= json_encode($this->request->getParam('_csrfToken')) ?>);
xhr.send(formData);
}
Also according to the docs the response JSON must contain a property named location that contains the web path to the uploaded file, that might be in the code that you've left out, mentioning it just in case.
See also
TinyMCE Docs > Introduction & getting started > Uploading images and files
TinyMCE Docs > Configuration reference > Image & file upload options > images_upload_handler
Cookbook > Security > Cross Site Request Forgery (CSRF) Middleware
I've created a .NET Core Web API that uses SPA with React. I want to preload some data into the application.
My startup.cs file looks like this:
app.UseSpa(spa => {
spa.Options.SourcePath = "ClientApp";
spa.UseSpaPrerendering(options => {
options.BootModulePath = $"main.chunk.js";
options.SupplyData = (context, data) => {
data["siteConfiguration"] = "{my custom object}";
};
});
if (env.IsDevelopment()) {
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
I'm getting an error about the BootModulePath is not being found.
Couldn't find any information about this property used with React or how to pre-render data into React SPA with .NET Core.
Is there an example on how to accomplish this?
Thanks
I'm using a bit of a different approach to accomplish this. I am using spa services in .net core https://learn.microsoft.com/en-us/aspnet/core/client-side/spa-services?view=aspnetcore-2.2#server-prerendering to do my pre rendering. I am also using razor pages to generate the html page (with just a single div for react to mount to). All I need to do is add a tag on my root div in my Index.cshtml page that looks something like this:
<div id="react-app" asp-prerender-module="ClientApp/dist/main-server">Loading...</div>
The entry point for my main-server bundle looks like:
export default createServerRenderer(params => {
//do stuff here
return new Promise<RenderResult>((resolve, reject) => {
params.domainTasks.then(() => {
resolve({
html: /* html string rendered by your app */,
globals: {
cachedVar1: data1,
cachedVar2: data2
}
});
}, reject); // Also propagate any errors back into the host application
});
});
This lets me pre-load data that was created by node during the pre-rendering by putting them in global variables in JavaScript.
If you want to pre-load data that comes from the .net core server and not from node, then what you can do is to pass that data as part of your model to the view.
public async Task<IActionResult> Index()
{
//get data here
return View(preloadedData);
}
Then in the Index.cshtml page, you can add something like this:
<script>
var PRELOADED_CACHE = #Html.Raw(Json.Serialize(#Model));
</script>
This will put a global variable called PRELOADED_CACHE which you can access from your application in the browser (but won't be available during pre-rendering).
I know this isn't precisely what you are looking for, but hopefully this at least gives you some helpful ideas.
<form
action="some url"
method="POST"
target="_blank"
>
{_.map(somedata, (value, key: string) => (
<input name={key} key={key} type="hidden" value={value}/>
))}
</form>
I am working with a page which submits a form on click of some button, this posts some data and opens a page in a new tab. This works perfectly fine in chrome mobile android but does not work(the new url opens in the new tab but shows no data posted by the form) when i create a PWA shortcut using Add to Home Screen feature and submit the form from inside of it. Also the new tab opens inside PWA only instead of mobile android chrome.
I apologise that this relates to Jquery (it uses core JS at its heart) but I believe this is something similar to solve the form posting issue. It uses the JS FormData object which allows for files as well.
function formPost(form){
var formData = new FormData();
$(form).find('input,select,textarea').each(function(){
if ($(this).attr('type') == 'file'){
use = $(this).get(0).files[0];
} else {
use = $(this).val();
}
formData.append($(this).attr('name'),use);
})
var request = new XMLHttpRequest();
request.open('POST',$(form).attr('action'));
request.send(formData);
}
Its worth saying that for browsers this requires at least IE10 but I think at end of 2019 we shouldn't be worrying about that !! https://caniuse.com/#search=formdata (PWAs operate in "modern browsers").
I'm using meteor ui twitter accounts. What I'm attempting to do is basically delete all the users from the Meteor collection when the button clear is clicked on. This is my code:
HTML File:
<div ng-controller="TweetsCtrl">
<meteor-include src="loginButtons"></meteor-include>
<ul>
<br>
<div ng-repeat="t in twitterAccs">
<img src = "{{t.services.twitter.profile_image_url_https}}">
<br>
<i>#{{t.services.twitter.screenName}}</i>
<br>
<br>
</div>
<button ng-click="clearUsers()">Clear</button>
</ul>
JS File:
if (Meteor.isClient) {
angular.module('twitter-example',['angular-meteor']);
angular.module('twitter-example').controller('TweetsCtrl',['$scope','$meteor',function($scope,$meteor) {
$scope.twitterAccs = $meteor.collection(Meteor.users);
$scope.clearUsers = function () {
$scope.twitterAccs = $meteor.collection(Meteor.users.remove({}) );
console.log("hello");
}
}]);
}
I assume this is only for development purposes right? It would suck to allow a visitor to your site to delete all your users. The fact you have a nice button set up for it has me worried it's a feature!
The easiest way to do it is hook up a Meteor.method like
if (Meteor.isServer) {
Meteor.methods({
clearUsers: function() {
Meteor.users.remove({});
}
});
}
Then do a Meteor.call('clearUsers') where your console.log("hello") is. You can also run the call via the browser console, I do this setup sometimes instead of going directly to the db via the terminal.
You could also do it via allow deny rules (see: http://docs.meteor.com/#/full/allow), by default a rule is setup so a user can only edit their own profile object.
Lastly you could include the meteor package insecure (I assume you must have already removed it) which will allow anyone to edit any collections assuming you haven't set up any of the allow, deny rules mentioned above.
I am using CodeIgniter controller functions.
(example)
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Me extends CI_Controller {
public function __construct()
{
parent::__construct();
if (is_logged_in()){if (is_admin()) { redirect('login'); }}
else { redirect('login');}
}
public function change_password()
{
$id=$this->session->userdata['user_data']['id'];
$data = json_decode(file_get_contents("php://input"));
$my_data=array(
'pass'=>$data->pass,
'new_pass'=>$data->new_pass,
);
$result=$this->vanesh_model->change_pass($id,$my_data);
if($result==1)
{
$arr = array('msg' => "Password changed successfuly.", 'error' => '');
$jsn = json_encode($arr);
print_r($jsn);
}
else if($result==2)
{
$arr = array('msg' => "", 'error' => 'Old Password is Invalid');
$jsn = json_encode($arr);
print_r($jsn);
}
else if($result==3)
{
$arr = array('msg' => "", 'error' => 'Sorry, Password change failed');
$jsn = json_encode($arr);
print_r($jsn);
}
}
}
?>
I am afraid of using angular session services, so I want to maintain sessions with only CI. What I am doing in my application is add, update, delete only if he is logged in. And I am using information stored in session. Consider the situation, suppose, I am logged in and doing something, side by side: I destroy the session using browser tools. Now I am continuing with application (doing operations like: change password). I have/had maintained error messages, success messages, its ok. If session OFF, it gives error message. But instead of error messages, I want to redirect to LOGIN page(with page refresh).
Note: For CI Login controller, I didn't used angular js. I have used angularjs only after login.
If by opening new tab I destroy the session, and come back to application's tab: I am able to perform tasks(may be with errors,). If session is OFF I see this in Browser's console: http://localhost/ums/login
This is because of CI constructor(please look over the code).
You should separate angular and CI as much as possible, since both have view-controller it creates a mess. Instead you should have CI in a separate folder, call it api, for example, after that anything you will need from CI should be acessed from angular with ajax calls.
I made a small webapp a while ago and this seemed to be the best way to organize code.
Few updates have been made to angular since then so if there's a better way please let me know
Solved.
Used javascript function. Checking session by http request everytime. If response comes "1". Means redirect to login as:
/* function for checking logged-in and role */
function check_session()
{
$.get("servercontroller/check_session", function(data, status){
if(data=="1") /* error 1 => un-athorized user */
{
window.location.href="/login-page-url";
}
});
}