Hello,
I am trying to implement the following QR code authentication system.
First, I want to show to the user a QR code that contains the link, thus the ActionUrl, to which he must make a POST request. Note that this is a Browser connection flow, so the QR code is shown on the browser.
Authenticate Method Authenticator
@Override
public void authenticate(AuthenticationFlowContext context) {
try {
context.challenge(context.form().createForm("qr-login.ftl"));
} catch (Exception e) {
context.failureChallenge(AuthenticationFlowError.INTERNAL_ERROR,
context.form().setError("Error", e.getMessage())
.createErrorPage(Response.Status.INTERNAL_SERVER_ERROR));
}
}
View
<#import "template.ftl" as layout>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
<style>
.center-container {
display: flex;
justify-content: center;
align-items: center;
}
</style>
<@layout.registrationLayout displayInfo=true; section>
<#if section = "header">
${msg("AuthTitle")}
<#elseif section = "form">
<form id="kc-template-code-login-form" class="${properties.kcFormClass!}" action="${url.loginAction}"
method="post">
<div class="${properties.kcFormGroupClass!}">
<div class="center-container">
<div id="qrcode"></div>
</div>
</div>
</form>
<#elseif section = "info" >
${msg("AuthInstruction")}
</#if>
</@layout.registrationLayout>
<script>
let qrcode = new QRCode("qrcode", "${url.loginAction}");
</script>
When the User will Scan the QR Code with his smartphone, it will send a POST request to the url.loginAction*. This request contains the “username” of the user. Then in the action method, I want to get the “username” parameter of this POST request and log the user that has the given username.
Action Method Authenticator
@Override
public void action(AuthenticationFlowContext context) {
// Get the user.
String enteredName= context.getHttpRequest().getDecodedFormParameters().getFirst("username");
context.clearUser();
try {
UserModel user = KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(), enteredName);
if (user == null) {
throw new ModelDuplicateException("User not found");
}
context.setUser(user);
} catch (ModelDuplicateException e) {
context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS,
context.form()
.setError("UserError", e.getMessage())
.createForm("qr-login.ftl"));
}
context.success();
}
The problem I face is that I don’t know how to trigger the action method by sending this POST request, thus allowing the browser to authenticate the user from the scanning of the QR code. I’m not sure about the fact that I even need to trigger the Action method, so help would be really appreciated.
Do you have any idea or resources on the steps I need to take to implement this “reaction” from the Authenticator when he receives the POST request ?