refactor auth-spi, auth demo, and docs
This commit is contained in:
1 parent
1f13f6372a
commit
6d7be80930
9 files changed
+83
-19
No files matched your search
@@ -14,13 +14,19 @@ Then registering the provider by editing keycloak-server.json and adding the mod
|
||||
],
|
||||
|
||||
|
||||
You then have to copy the secret-question.ftl file to the standalone/configuration/themes/base/login directory.
|
||||
You then have to copy the secret-question.ftl and secret-question-config.ftl files to the standalone/configuration/themes/base/login directory.
|
||||
|
||||
After you do all this, you then have to reboot keycloak. When reboot is complete, you will need to log into
|
||||
the admin console to create a new flow with your new authenticator.
|
||||
|
||||
If you go to the Authentication menu item and go to the Flow tab, you will be able to view the currently
|
||||
defined flows. You cannot modify an built in flows, so, to add the Authenticator you
|
||||
have to copy an existing flow or create your own. I'm hoping the UI is intuitive enough so that you
|
||||
can figure out for yourself how to create a flow and add the Authenticator. We're looking to add a screencast
|
||||
have to copy an existing flow or create your own.
|
||||
|
||||
Next you have to register your required action.
|
||||
Click on the Required Actions tab. Click on the Register button and choose your new Required Action.
|
||||
Your new required action should now be displayed and enabled in the required actions list.
|
||||
|
||||
I'm hoping the UI is intuitive enough so that you
|
||||
can figure out for yourself how to create a flow and add the Authenticator and Required Action. We're looking to add a screencast
|
||||
to show this in action.
|
||||
@@ -0,0 +1,33 @@
|
||||
<#import "template.ftl" as layout>
|
||||
<@layout.registrationLayout; section>
|
||||
<#if section = "title">
|
||||
${msg("loginTitle",realm.name)}
|
||||
<#elseif section = "header">
|
||||
Setup Secret Question
|
||||
<#elseif section = "form">
|
||||
<form id="kc-totp-login-form" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
|
||||
<div class="${properties.kcFormGroupClass!}">
|
||||
<div class="${properties.kcLabelWrapperClass!}">
|
||||
<label for="totp" class="${properties.kcLabelClass!}">What is your mom's first name?</label>
|
||||
</div>
|
||||
|
||||
<div class="${properties.kcInputWrapperClass!}">
|
||||
<input id="totp" name="secret_answer" type="text" class="${properties.kcInputClass!}" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="${properties.kcFormGroupClass!}">
|
||||
<div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
|
||||
<div class="${properties.kcFormOptionsWrapperClass!}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
|
||||
<div class="${properties.kcFormButtonsWrapperClass!}">
|
||||
<input class="${properties.kcButtonClass!} ${properties.kcButtonPrimaryClass!} ${properties.kcButtonLargeClass!}" name="login" id="kc-login" type="submit" value="${msg("doSubmit")}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</#if>
|
||||
</@layout.registrationLayout>
|
||||
+16
-4
@@ -13,6 +13,8 @@ import org.keycloak.services.util.CookieHelper;
|
||||
import javax.ws.rs.core.Cookie;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
@@ -24,7 +26,11 @@ public class SecretQuestionAuthenticator implements Authenticator {
|
||||
|
||||
protected boolean hasCookie(AuthenticationFlowContext context) {
|
||||
Cookie cookie = context.getHttpRequest().getHttpHeaders().getCookies().get("SECRET_QUESTION_ANSWERED");
|
||||
return cookie != null;
|
||||
boolean result = cookie != null;
|
||||
if (result) {
|
||||
System.out.println("Bypassing secret question because cookie as set");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -33,12 +39,17 @@ public class SecretQuestionAuthenticator implements Authenticator {
|
||||
context.success();
|
||||
return;
|
||||
}
|
||||
Response challenge = context.form().createForm("secret_question.ftl");
|
||||
Response challenge = context.form().createForm("secret-question.ftl");
|
||||
context.challenge(challenge);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void action(AuthenticationFlowContext context) {
|
||||
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
|
||||
if (formData.containsKey("cancel")) {
|
||||
context.cancelLogin();
|
||||
return;
|
||||
}
|
||||
boolean validated = validateAnswer(context);
|
||||
if (!validated) {
|
||||
Response challenge = context.form()
|
||||
@@ -58,11 +69,12 @@ public class SecretQuestionAuthenticator implements Authenticator {
|
||||
maxCookieAge = Integer.valueOf(config.getConfig().get("cookie.max.age"));
|
||||
|
||||
}
|
||||
URI uri = context.getUriInfo().getBaseUriBuilder().path("realms").path(context.getRealm().getName()).build();
|
||||
CookieHelper.addCookie("SECRET_QUESTION_ANSWERED", "true",
|
||||
context.getUriInfo().getBaseUri().getPath() + "/realms/" + context.getRealm().getName(),
|
||||
uri.getRawPath(),
|
||||
null, null,
|
||||
maxCookieAge,
|
||||
true, true);
|
||||
false, true);
|
||||
}
|
||||
|
||||
protected boolean validateAnswer(AuthenticationFlowContext context) {
|
||||
|
||||
+2
-2
@@ -20,14 +20,14 @@ public class SecretQuestionRequiredAction implements RequiredActionProvider {
|
||||
|
||||
@Override
|
||||
public void requiredActionChallenge(RequiredActionContext context) {
|
||||
Response challenge = context.form().createForm("secret_question_config.ftl");
|
||||
Response challenge = context.form().createForm("secret-question-config.ftl");
|
||||
context.challenge(challenge);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processAction(RequiredActionContext context) {
|
||||
String answer = (context.getHttpRequest().getDecodedFormParameters().getFirst("answer"));
|
||||
String answer = (context.getHttpRequest().getDecodedFormParameters().getFirst("secret_answer"));
|
||||
UserCredentialValueModel model = new UserCredentialValueModel();
|
||||
model.setValue(answer);
|
||||
model.setType(SecretQuestionAuthenticator.CREDENTIAL_TYPE);
|
||||
|
||||
Reference in new issue
Block a user