From ffed84194e405af2f3f07f3b684e0c039d53e9b0 Mon Sep 17 00:00:00 2001 From: olympus5 Date: Sat, 25 Oct 2025 10:42:09 +0200 Subject: [PATCH] Realign source code examples in auth-spi doc closes #43757 Signed-off-by: olympus5 --- .../server_development/topics/auth-spi.adoc | 58 ++++++++----------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/docs/documentation/server_development/topics/auth-spi.adoc b/docs/documentation/server_development/topics/auth-spi.adoc index b8e5dd242aa..522e86c958c 100644 --- a/docs/documentation/server_development/topics/auth-spi.adoc +++ b/docs/documentation/server_development/topics/auth-spi.adoc @@ -453,7 +453,7 @@ public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) if (challengeResponse == null) { return false; } - CredentialModel credentialModel = getCredentialStore().getStoredCredentialById(realm, user, input.getCredentialId()); + CredentialModel credentialModel = user.credentialManager().getStoredCredentialById(input.getCredentialId()); SecretQuestionCredentialModel sqcm = getCredentialFromModel(credentialModel); return sqcm.getSecretQuestionSecretData().getAnswer().equals(challengeResponse); } @@ -473,7 +473,7 @@ public boolean supportsCredentialType(String credentialType) { @Override public boolean isConfiguredFor(RealmModel realm, UserModel user, String credentialType) { if (!supportsCredentialType(credentialType)) return false; - return !getCredentialStore().getStoredCredentialsByType(realm, user, credentialType).isEmpty(); + return user.credentialManager().getStoredCredentialsByTypeStream(credentialType).findAny().isPresent(); } ---- @@ -519,7 +519,7 @@ Here is the implementation of the setRequiredActions() method. ---- @Override public void setRequiredActions(KeycloakSession session, RealmModel realm, UserModel user) { - user.addRequiredAction("SECRET_QUESTION_CONFIG"); + user.addRequiredAction(SecretQuestionRequiredAction.PROVIDER_ID); } ---- @@ -631,11 +631,13 @@ protected void setCookie(AuthenticationFlowContext context) { } URI uri = context.getUriInfo().getBaseUriBuilder().path("realms").path(context.getRealm().getName()).build(); - addCookie(context, "SECRET_QUESTION_ANSWERED", "true", - uri.getRawPath(), - null, null, - maxCookieAge, - false, true); + + NewCookie newCookie = new NewCookie.Builder("SECRET_QUESTION_ANSWERED").value("true") + .path(uri.getRawPath()) + .maxAge(maxCookieAge) + .secure(false) + .build(); + context.getSession().getContext().getHttpResponse().setCookieIfAbsent(newCookie); } ---- @@ -647,16 +649,16 @@ The config values can be defined within the Admin Console if you set up config d [source,java] ---- @Override - public CredentialTypeMetadata getCredentialTypeMetadata(CredentialTypeMetadataContext metadataContext) { - return CredentialTypeMetadata.builder() - .type(getType()) - .category(CredentialTypeMetadata.Category.TWO_FACTOR) - .displayName(SecretQuestionCredentialProviderFactory.PROVIDER_ID) - .helpText("secret-question-text") - .createAction(SecretQuestionAuthenticatorFactory.PROVIDER_ID) - .removeable(false) - .build(session); - } +public CredentialTypeMetadata getCredentialTypeMetadata(CredentialTypeMetadataContext metadataContext) { + return CredentialTypeMetadata.builder() + .type(getType()) + .category(CredentialTypeMetadata.Category.TWO_FACTOR) + .displayName(SecretQuestionCredentialProviderFactory.PROVIDER_ID) + .helpText("secret-question-text") + .createAction(SecretQuestionAuthenticatorFactory.PROVIDER_ID) + .removeable(false) + .build(session); +} ---- The last method to implement in the SecretQuestionCredentialProvider class is getCredentialTypeMetadata(CredentialTypeMetadataContext metadataContext), which is an abstract method of the CredentialProvider interface. Each Credential provider has to provide and implement this method. The method returns an instance of CredentialTypeMetadata, @@ -805,16 +807,6 @@ When you call AuthenticationFlowContext.form() this gives you a LoginFormsProvid If you called, `LoginFormsProvider.setAttribute("foo", "bar")`, the value of "foo" would be available for reference in your form as `${foo}`. The value of an attribute can be any Java bean as well. -If you look at the top of the file, you'll see that we are importing a template: - -[source,xml] ----- -<#import "select.ftl" as layout> ----- - -Importing this template, instead of the standard `template.ftl` allows {project_name} to display a dropdown box that allows the user to select -a different credential or execution. - [[_adding_authenticator]] ==== Adding an authenticator to a flow @@ -860,7 +852,7 @@ This method is responsible for rendering the HTML form that will drive the requi @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); } @@ -882,11 +874,9 @@ The action URL of the form will be routed to the RequiredActionProvider.processA @Override public void processAction(RequiredActionContext context) { - String answer = (context.getHttpRequest().getDecodedFormParameters().getFirst("answer")); - UserCredentialValueModel model = new UserCredentialValueModel(); - model.setValue(answer); - model.setType(SecretQuestionAuthenticator.CREDENTIAL_TYPE); - context.getUser().updateCredentialDirectly(model); + String answer = (context.getHttpRequest().getDecodedFormParameters().getFirst("secret_answer")); + SecretQuestionCredentialProvider sqcp = (SecretQuestionCredentialProvider) context.getSession().getProvider(CredentialProvider.class, "secret-question"); + sqcp.createCredential(context.getRealm(), context.getUser(), SecretQuestionCredentialModel.createSecretQuestion("What is your mom's first name?", answer)); context.success(); } ----