Categories
discuss

Node Express and csurf – 403 (Forbidden) invalid csrf token

Looked through and tried everything I could find on here, and elsewhere by Googling…and I’m just not able to get past this. I’m using Node, Express, EJS, and attempting to use csurf on a form, that is posted w/ jQuery ajax. No matter how I configure csurf, I get “403 (Forbidden) invalid csrf token”

I’ve tried configuring both globally in app.js and in the controller. Here’s what I tried in app.js:

var express = require('express');
var session  = require('express-session');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var mysql = require('mysql');
var flash = require("connect-flash");
var csrf = require("csurf");

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(logger('dev'));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(session({
    secret: 'somethingsecret',
    resave: true,
    saveUninitialized: true,
    httpOnly: true,
    secure: false
}));
app.use(csrf());
app.use(function (req, res, next) {
    var token = req.csrfToken();
    res.cookie('XSRF-TOKEN', token);
    res.locals.csrfToken = token;
    console.log("csrf token = " + token);
    next();
});
app.use(flash());
app.use(express.static(path.join(__dirname, 'public')));

app.use(function (err, req, res, next) {
    if (err.code !== 'EBADCSRFTOKEN') return next(err);

    // handle CSRF token errors here
    res.status(403);
    res.send('form tampered with');
})

//routing
var routes = require('./routes/index');
var users = require('./routes/users');
var register = require('./routes/register');

app.use('/', routes);
app.use('/users', users);
app.use('/register', register);

…with this controller:

var express = require("express");
var router = express.Router();
var bodyParser = require("body-parser");
var userSvc = require("../service/userservice");

var jsonParser = bodyParser.json();

router.get("/", function(req, res, next) {
    console.log("token = " + token);
    userSvc.getAllPublicRoles(function(data) {
        res.render("register", {
            title: "Register a new account",
            roles: data
        });
    });
});

router.post("/new", jsonParser, function(req, res, next) {
    userSvc.addUser(req.body, function(result) {
        console.log("New user id = " + result.insertId);
        res.send('{"success" : "Updated Successfully", "status" : 200}');
    });
});

…and this view:

form:

<form id="registerForm" class="form-horizontal" method="post">
    <input type="hidden" name="_csrf" value="<%= csrfToken %>" />

ajax call:

        $.ajax({
            url: "/register/new",
            type: "POST",
            dataType: "json",
            data: user
        }).done(function(data) {
            if (data) {
                console.log("Success! = " + data);
            }
        }).fail(function(data) {
            console.log("Something went wrong: " + data.responseText);
        });

Then I just tried just doing everything in the controller, removing all references, calls, etc. from app.js, and using the same form and ajax call as above:

var express = require("express");
var router = express.Router();
var bodyParser = require("body-parser");
var csrf = require("csurf");
var userSvc = require("../service/userservice");

var csrfProtection = csrf();
var jsonParser = bodyParser.json();

router.get("/", csrfProtection, function(req, res, next) {
    var token = req.csrfToken();
    console.log("token = " + token);
    userSvc.getAllPublicRoles(function(data) {
        res.render("register", {
            title: "Register a new account",
            csrfToken: token,
            roles: data
        });
    });
});

router.post("/new", jsonParser, csrfProtection, function(req, res, next) {
    userSvc.addUser(req.body, function(result) {
        console.log("New user id = " + result.insertId);
        res.send('{"success" : "Updated Successfully", "status" : 200}');
    });
});

Not sure where to go from here. I’ve been using node for about two weeks, in my spare time, so pardon my ignorance here.

Answer

If you want to store the token in a cookie instead of the session, let csurf create the cookie for you e.g.

// Store the token in a cookie called '_csrf'
app.use(csrf({cookie: true));

// Make the token available to all views
app.use(function (req, res, next){
    res.locals._csrf = req.csrfToken();
    next();
});

Then you need to make sure the token is available when you’re making the call using AJAX either via the POST’ed data, or as a custom request header such as ‘xsrf-token’.

At the minute, you’re providing the token to the form, but not the actual request (sent using AJAX).

For example, you could render the token in the AJAX setup:

$.ajaxSetup({
   headers: {"X-CSRF-Token": "{{csrfToken}}" }
}); 
Categories
discuss

Typescript: How to check tagName in eventTarget?

Why in this case:

var ele = <HTMLDivElement>document.getElementById("toolbar");
    ele.addEventListener("click", function (e) { 
        if (e.target.tagName === "SPAN") { console.log(e.target.tagName) }  }, false);

Visual Studio shows me this error?

Build: Operator ‘===’ cannot be applied to types ‘HTMLElement’ and ‘string’.

Property ‘tagName’ does not exist on type ‘EventTarget’.

When I run a script works fine.

How to write it properly?

Thank you.

Answer

I would adjust that code snippet like this:

var ele = <HTMLDivElement>document.getElementById("toolbar");
    ele.addEventListener("click", (ev: MouseEvent) => {
        var element = ev.target as HTMLElement;     
        if (element.tagName === "SPAN") { 
            console.log(element.tagName) 
        }  
    }, false);

Casting the event property target to HTMLElement will give us all the proper properties of the underlying element.

Check it in the playground

Categories
discuss

Error 12501 authenticating with google sign-in

I’m using google sign-in services to authenticate users that use my app. I got it to work when I just requested email information

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                    .requestEmail().build();

Then, I figured out I also need to request ID token to be able to authenticate with my backend so I did:

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                    .requestIdToken(String.valueOf(R.string.server_client_id))
                    .requestEmail().build();

The problem is that it wouldn’t let me log in after the changes. The status I keep getting each time I try to login is Status{statusCode=unknown status code: 12501, resolution=null}.

I’ve been searching around and I found this post that is pretty much about the same thing. However, I didn’t make any of the mistakes named by the people who answered, the oAuth Client ID in my dev console is for web application: clientIDs And R.string.server_client_id is the first client ID from the picture. the package names are of course correct in all placed otherwise it wouldn’t even work without the token request. 2 people also suggested that the app needs to be signed for this to work, but googles documentation says that debug key should work too, and it doesn’t make sense to make people sign the apps for debugging.

I’ve been trying to figure this out for hours but with no success. What could be the problem? Please feel free to request more information I might have forgotten to put here.

Answer

Well, this is very embarrassing, but I figured it out:

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                    .requestIdToken(AuthenticatedActivity.this.getResources().getString(R.string.server_client_id))
                    .requestEmail().build();

I was sending it the resource ID instead of dereferenced string resource.

Categories
discuss

Can I use a lambda expression to accumulate the sum in the variable?

I have an Item[] items which contains some basic stats about itself.

public float getAttackDamage() {
    float bonus = 0;
    for(int i = 0 ; i < items.length; i++){
        if(items[i] != null){
            bonus += items[i].getAttackDamage();
        }
    }
    return baseAttackDamage + attackDamageScaling * level + bonus;
}

The above code is how I currently loop through my characters items and apply their getAttackDamage() to the return result.

Is there a way I can rewrite this to use a lambda expressions instead? I tried the follow:

public float getAttackDamage() {
    float bonus = 0;
    Arrays.stream(items).forEach(i -> bonus += i.getAttackDamage());
    return baseAttackDamage + attackDamageScaling * level + bonus;
}

But it didn’t work (compiler error). Is this possible?

Answer

Yes, you could have the following:

double bonus = Arrays.stream(items)
                     .filter(Objects::nonNull)
                     .mapToDouble(Item::getAttackDamage)
                     .sum();

You should remember that forEach is probably not the method you want to call. It breaks functional programming (refer to Brian Goetz‘s comment). In this code, a Stream of each of your item is created. The non-null elements are filtered and mapped to a double value corresponding to the attack damage.

Categories
discuss

How to check if all tasks running on ExecutorService are completed

I’v got ConcurrentLinkedDeque which I’m using for synchronic push/pop elements, and I’v got some async tasks which are taking one element from stack and if this element has neighbors It’s pushing it to stack.

Example code:

private ConcurrentLinkedDeque<Item> stack = new ConcurrentLinkedDeque<>();
private ExecutorService exec = Executors.newFixedThreadPool(5);

    while ((item = stack.pollFirst()) != null) {
                if (item == null) {
                } else {
                    Runnable worker = new Solider(this, item);
                    exec.execute(worker);
                }
            }

   class Solider{
         public void run(){
             if(item.hasNeighbors){
                for(Item item:item.neighbors){
                    stack.push(item)
                }
             } 
         }
    }

I would like to have additional statement in while loop which answers the question – “any task in Executor is working?”

Answer

There isn’t a clean way to check if all Runnables are done if you use ExecutorService.execute(Runnable). Unless you build a mechanism to do so in the Runnable itself (which is sloppy in my opinion).

Instead:
Use ExecutorService.submit(Runnable). This method will return a Future<?> which is a handle to the result of a Runnable. Using Futures provides a clean way to check results.

All you have to do is maintain a list of Futures that you submit, and then you can iterate over the whole list of Futures and either:
  A) wait for all the futures to be done in a blocking way or
  B) check if all the futures are done in a non-blocking way.

Here is a code example:

List<Future<?>> futures = new ArrayList<Future<?>>();
ExecutorService exec = Executors.newFixedThreadPool(5);

// Instead of using exec.execute() use exec.submit()
// because it returns a monitorable future
while((item = stack.pollFirst()) != null){
    Runnable worker = new Solider(this, item);
    Future<?> f = exec.submit(worker);
    futures.add(f);
}

// A) Await all runnables to be done (blocking)
for(Future<?> future : futures)
    future.get(); // get will block until the future is done

// B) Check if all runnables are done (non-blocking)
boolean allDone = true;
for(Future<?> future : futures){
    allDone &= future.isDone(); // check if future is done
}
Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..