# Añadir Passkeys a mis aplicaciones Django
## Cambios en Dockerfile
En el Dockerfile de creación de la imagen hay que hacer un pequeño cambio para copiar el logo de passkeys con fondo negro al directorio de instalación del módulo de passkeys dentro del contenedor.
Esto es necesario porque el logo que viene por defecto es blanco y si el botón de entrar con passkey es también blanco, pues no se ve.
COPY ./src/config/FIDO_Passkey_mark_A_black.jpg /root/.local/lib/python3.14/site-packages/passkeys/static/passkeys/imgs/
Para ello, en el directorio ```./src/config``` hay que dejar el logo correcto. Lo descargué de la página de la [FIDO Alliance](https://fidoalliance.org/get-the-passkey-icon/).
## Cambios en ```settings.py````
En ```settings.py```` hay que hacer los siguientes cambios:
1. Añadir ```'passkeys',``` a ```INSTALLED_APPS```:
INSTALLED_APPS = [
...
...
'passkeys',
...
...
]
2. Añadir el backend de autenticación:
AUTHENTICATION_BACKENDS = ['passkeys.backend.PasskeyModelBackend']
3. Añadir las siguientes variables:
FIDO_SERVER_ID="finanzas.reymota.es" # Server rp id for FIDO2, it the full domain of your project
FIDO_SERVER_NAME="Finanzas"
KEY_ATTACHMENT = None # Set None to allow all authenticator attachment
> en ```FIDO_SERVER_ID``` hay que poner el nombre del dominio. Este de aquí es un ejemplo.
## Cambios en ```urls.py``` del proyecto.
En el fichero ```urls.py``` del proyecto, hay que añadir una entrada para passkeys.
urlpatterns = [
...
...
path('passkeys/', include('passkeys.urls')),
...
...
]
No olvidar importar ```include```:
from django.urls import path, include
## Cambios en ```reymotausers```
En ```reymotausers``` hay que añadir un nuevo fichero llamado ```auth.py``` con el siguiente contenido:
import json
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.forms import AuthenticationForm
from django.shortcuts import render, redirect
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.serializers import Serializer, CharField
from rest_framework.views import APIView
from passkeys.api.token_backends import get_token_response
def loginView(request):
if request.method == "POST":
passkeys_raw = request.POST.get("passkeys", "")
if passkeys_raw:
user = authenticate(request)
if user:
login(request, user)
return redirect(request.POST.get("next", "") or "principal")
form = AuthenticationForm(request)
form.add_error(None, "Passkey authentication failed. Try again.")
else:
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
return redirect(request.POST.get("next", "") or "principal")
else:
form = AuthenticationForm(request)
return render(request, "registration/login.html", {"form": form})
# def create_session(request,username):
# user=User.objects.get(username=username)
# user.backend='django.contrib.auth.backends.ModelBackend'
# login(request, user)
# return HttpResponseRedirect(reverse('home'))
def logoutView(request):
logout(request) # pragma: no cover
return render(request,"logout.html",{}) # pragma: no cover
class LoginSerializer(Serializer):
username = CharField()
password = CharField()
class LoginAPIView(APIView):
"""
Username + password login API.
Returns the same token format as passkey authentication
(JWT, DRF Token, or session depending on project config).
Use this to get an initial token before registering passkeys.
"""
permission_classes = [AllowAny]
serializer_class = LoginSerializer
def post(self, request):
serializer = LoginSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = authenticate(
request,
username=serializer.validated_data['username'],
password=serializer.validated_data['password'],
)
if user is None:
raise AuthenticationFailed("Invalid username or password")
token_data = get_token_response(user, request)
return Response({
'user_id': user.pk,
'username': user.get_username(),
**token_data,
})
A continuación, hay que modificar ```urls.py``` de ```accounts``` añadiendo
from reymotausers.auth import loginView
y en ```urlpatterns``` cambiar el path de login por:
path('login/', loginView, name='login'),
## Templates para passkeys.
En el directorio ```templates``` hay que añadir una carpeta ```passkeys``` con un fichero ```manage.html``` cuyo contenido es el siguiente:
{% extends "passkeys/base.html" %}
{% load static %}
{% block head %}
{{block.super}}
{% endblock %}
{% block content %}
{{block.super}}