I’ve been working on a website project adapted for security, and I now use my XSIID blinking implant to unlock a website I built in place (and in addition) to a passcode and other tokens. I wanted to share the code I use here, so other people can see how to build a basic security firewall with an implant.
I’m mostly using JavaScript, reading and writing randomly generated data to the tag, and then posting the data written and read for confirmation with the server. If the data is valid, I am able to log in. And it’s as easy as holding my phone to my hand. I also have a few NFC rings I use for this, as well as regular credit card sized NTAGs (NTAG216).
I also use Python as a backend with Django. This template extends a base template with BootStrap and JQuery, and takes a single optional URL parameter, “generate”, used to tell the software to write to the tag even when a read is invalid. This is in order to train the tags, and also because very rarely a tag can be corrupted when there is a successful write but the server is cut off from caching the new data written to it.
The software identifies the tag by its ID (MAC address) and writes bytes to the tag.
{% extends 'base.html' %}
{% block content %}
<legend>NFC Verification</legend>
<p>Place the NFC device near the back of the phone. <a href="{% url 'security:mrz' %}" title="Use MRZ instead">Use MRZ instead</a></p>
<form action="{{ request.path }}{% if request.GET.generate %}?generate=t{% endif %}" id="nfc-form" method="POST" class="hide">
{{ form }}
</form>
<p class="text-center" style="font-size: 40px"><i class="bi bi-reception-4"></i></p>
<p id="errors">Tap the screen to enable NFC.</p>
{% endblock %}
{% block javascript %}
var form = document.getElementById('nfc-form');
function readTag() {
var successfulWrite = false;
var successfulRead = false;
if ("NDEFReader" in window) {
const ndef = new NDEFReader();
document.getElementById('errors').innerHtml = 'Initialized.';
try {
ndef.scan().then(() => {
document.getElementById('errors').innerHTML = 'Scanning.';
ndef.onreading = (event) => {
if(successfulWrite) { return; }
if(successfulRead) { return; }
document.getElementById('errors').innerHTML= 'Read tag.';
const decoder = new TextDecoder();
for (const record of event.message.records) {
document.getElementById('errors').innerHTML= 'Record detected.';
document.getElementById('id_nfc_data_read').value = decoder.decode(record.data);
document.getElementById('id_nfc_id').value = event.serialNumber;
successfulRead = true;
}
ndef.write("{{ nfc_data }}").then(function() {
successfulWrite = true;
document.getElementById('errors').innerHTML= 'Data written, confirming.';
document.getElementById('id_nfc_data_written').value = "{{ nfc_data }}";
var formData = new FormData(form);
$.ajax({
url: '{{ request.path }}{% if request.GET.generate %}?generate=t{% endif %}',
data: formData,
method: 'POST',
timeout: 60 * 1000,
cache: false,
contentType: false,
processData: false,
error: function(xhr, textStatus, errorThrown) {
successfulRead = false;
successfulWrite = false;
document.getElementById('errors').innerHTML = errorThrown.message;
},
success: function(response) {
if(response == 'y') {
document.getElementById('errors').innerHTML= 'Redirecting.';
window.navigator.vibrate({{ default_vibration }});
window.location.href = '{% if request.GET.next %}{{ request.GET.next }}{% else %}/go/{% endif %}';
} else {
successfulRead = false;
successfulWrite = false;
document.getElementById('errors').innerHTML = 'Invalid tag.';
}
}
});
});
};
});
} catch(error) {
document.getElementById('errors').innerHTML= error.message;
}
}
}
var reading = false;
function initialize() {
if(!reading) {
window.navigator.vibrate({{ default_vibration }});
reading = true;
readTag();
}
}
document.body.addEventListener('click', function(event) {
initialize();
});
document.body.addEventListener('touchmove', function(event) {
initialize();
});
{% if not request.GET.generate %}
setInterval(function() {
$.ajax({
url: "{% url 'security:modal' %}",
method: 'POST',
success: function(data){
if(data == 'y') {
window.location.href = '{% if request.GET.next %}{{ request.GET.next }}{% else %}/go/{% endif %}';
}
}
});
}, 15 * 1000);
{% endif %}
{% endblock %}
This also requires a view which returns a HTTP response in case the user is already authenticated (so the passthrough happens on multiple pages at the same time when the user has already scanned a tag).
The Python is fairly simple too, with a basic model storing text:
class NFCScan(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name='nfc_scans')
timestamp = models.DateTimeField(default=timezone.now)
session_key = models.CharField(max_length=100, default='', blank=True, null=True)
nfc_id = models.TextField(blank=True, default='')
nfc_data_read = models.TextField(blank=True, default='')
nfc_data_written = models.TextField(blank=True, default='')
nfc_id = models.TextField(blank=True, default='')
nfc_name = models.TextField(blank=True, default='')
valid = models.BooleanField(default=True)
And a view to scan the tag:
@login_required
def scan_nfc(request):
if request.method == 'POST':
form = NFCScanForm(request.POST)
if form.is_valid():
allowed = NFCScan.objects.filter(user=request.user).count() == 0 or (NFCScan.objects.filter(user=request.user, nfc_id=form.cleaned_data.get('nfc_id', None), valid=True, nfc_data_written=form.cleaned_data.get('nfc_data_read', None)).count() == 1) or (request.GET.get('generate', False) and face_mrz_or_nfc_verified(request))
if not allowed: return HttpResponse('n')
form.instance.user = request.user
form.instance.session_key = request.session.session_key
form.instance.nfc_data_written = form.cleaned_data.get('nfc_data_written', None)
scan = form.save()
return HttpResponse('y')
return render(request, 'security/nfc.html', {
'title': 'Scan NFC',
'form': NFCScanForm(),
'nfc_data': get_random_string(length=settings.VERIFICATION_NFC_LENGTH),
'session_key': request.session.session_key
})
This code is also sensitive to the session key, so I use the following test to then require an NFC scan for pages that I want to secure with the tag (for example a private blog).
def nfc_verified(request):
user = request.user
return user.is_authenticated and ((user.nfc_scans.filter(valid=True, session_key=request.session.session_key).last() and user.nfc_scans.filter(valid=True, session_key=request.session.session_key).last().timestamp > timezone.now() - datetime.timedelta(minutes=settings.NFC_SCAN_REQUIRED_MINUTES)) or user.user_sessions.filter(bypass=True, session_key=request.session.session_key, timestamp__gte=timezone.now() - datetime.timedelta(minutes=settings.LOGIN_VALID_MINUTES)).first())
Here’s the full code on GitHub:
This works pretty well. I have some barcode labels printed on some of my larger tags as a fallback too, in case a tag fails I can scan the barcode and parse the text on it as an additional option to verify my identity. Maybe there’s another sort of biohacking idea here? Tattoos of barcodes could be used in a similar way to log in to a site (like a QR or PDF code), though I’m not sure about fading. More reliably, I’ve been able to use the Kabsch-Umeyama algorithm to verify my identity by taking a picture of the constellations (albino speckled dark colored skin) on arms and hands.
I hope this information is useful to some of you, I’m not sure anyone has posted much about using these tags for authentication here but I expect it has real potential as a market for the tags. NFC authentication is super reliable and useful, at least in my use case, because I always have it on me and it’s compatible with any smartphone. I look forward to what the world of biohacking brings, I’m going to continue with my implant experiments with a magnet implant and potentially others. I used to have a tritium implant, but I had it removed because I did a sloppy job on the surgery and it was causing some discomfort. This implant has been really comfortable though, it’s useful and practical for my application. If you want to read more about my projects, check out my Amazon Author profile where I’m working on a few series about full stack solutions I build for all sorts of cool stuff including security, AI, ML, blogging, media, facial recognition, embedded devices, responsive websites, and more. Thanks for reading!