How is the hash target set and verified by all nodes? As in the title - I understand that nodes look at the last two weeks of calculated hashes and adjust the difficulty to bring the average time to 10 minutes. But how exactly is this done? 

In particular, all the nodes would have to agree on the same target, else a newly mined block would be valid for some nodes and not others. This seems like a problem of consensus (in the traditional sense, not the Bitcoin way) which is very difficult, isn't it?
The difficulty adjustment algorithm is as follows (from the source code):

unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params&amp; params)
{
    if (params.fPowNoRetargeting)
        return pindexLast-&gt;nBits;

    // Limit adjustment step
    int64_t nActualTimespan = pindexLast-&gt;GetBlockTime() - nFirstBlockTime;
    if (nActualTimespan &lt; params.nPowTargetTimespan/4)
        nActualTimespan = params.nPowTargetTimespan/4;
    if (nActualTimespan &gt; params.nPowTargetTimespan*4)
        nActualTimespan = params.nPowTargetTimespan*4;

    // Retarget
    const arith_uint256 bnPowLimit = UintToArith256(params.powLimit);
    arith_uint256 bnNew;
    bnNew.SetCompact(pindexLast-&gt;nBits);
    bnNew *= nActualTimespan;
    bnNew /= params.nPowTargetTimespan;

    if (bnNew &gt; bnPowLimit)
        bnNew = bnPowLimit;

    return bnNew.GetCompact();
}


The adjustment is only run every 2016 block. What it does is it takes the timestamp of the block at the beginning of the last period (2016 blocks prior) and the timestamp of the block that came before the one with the adjusted difficulty. Those timestamps are then used to calculate the amount of time that passed between the first block in the interval and the last block in the interval. Then that timespan is clamped to be at least 1 quarter of the target timespan and at most 4 times the target timespan. To calculate the new difficulty for this interval, that target is multiplied by the actual amount of time that passed, and divided by the targeted amount of time.

Since all nodes are calculating the target at the same block and with the same previous data, the target calculation is deterministic and everyone will land on the same target.