Skip to content

Commit

Permalink
feat: add authentication SG flow tests (#3877)
Browse files Browse the repository at this point in the history
  • Loading branch information
yurem committed Feb 17, 2023
1 parent 0152435 commit d5c3fac
Show file tree
Hide file tree
Showing 10 changed files with 489 additions and 257 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ public class ChallengeGenerator {
@Inject
private Base64Service base64Service;

public String getAttestationChallenge() {
return getChallenge();
}

public String getAssertionChallenge() {
return getChallenge();
}

public String getChallenge() {
byte buffer[] = new byte[32];
new SecureRandom().nextBytes(buffer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public ObjectNode options(JsonNode params) {
optionsResponseNode.put("userVerification", userVerification.name());

// Generate and put challenge
String challenge = challengeGenerator.getChallenge();
String challenge = challengeGenerator.getAssertionChallenge();
optionsResponseNode.put("challenge", challenge);
log.debug("Put challenge {}", challenge);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public ObjectNode options(JsonNode params) {
log.debug("Put authenticatorSelection {}", authenticatorSelectionNode);

// Generate and put challenge
String challenge = challengeGenerator.getChallenge();
String challenge = challengeGenerator.getAttestationChallenge();
optionsResponseNode.put("challenge", challenge);
log.debug("Put challenge {}", challenge);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

package io.jans.fido2.service.persist;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
Expand All @@ -23,13 +22,9 @@
import io.jans.fido2.service.ChallengeGenerator;
import io.jans.fido2.service.shared.UserService;
import io.jans.orm.PersistenceEntryManager;
import io.jans.orm.model.BatchOperation;
import io.jans.orm.model.ProcessBatchOperation;
import io.jans.orm.model.SearchScope;
import io.jans.orm.model.base.SimpleBranch;
import io.jans.orm.model.fido2.Fido2AuthenticationData;
import io.jans.orm.model.fido2.Fido2AuthenticationEntry;
import io.jans.orm.model.fido2.Fido2AuthenticationStatus;
import io.jans.orm.search.filter.Filter;
import io.jans.util.StringHelper;
import jakarta.enterprise.context.ApplicationScoped;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ public class RegistrationPersistenceService extends io.jans.as.common.service.co
@Inject
private UserService userService;

// public void setUserService(UserService userService) {
// this.userService = userService;
// }

@Inject
private PersistenceEntryManager persistenceEntryManager;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,28 +87,7 @@ public class AssertionSuperGluuController {
* "keyHandle":"YJvWD9n40eIurInJvPKUoxpKzrleUMWgu9w3v_NUBu7BiGAclgkH_Zg88_T5y6Rh78imTxTh0djWFYG4jxOixw","version":"U2F_V2"}]}
*/
public JsonNode startAuthentication(String userName, String keyHandle, String appId, String sessionId) {
boolean oneStep = StringHelper.isEmpty(userName);

boolean valid = userSessionIdService.isValidSessionId(sessionId, userName);
if (!valid) {
throw new Fido2RuntimeException(String.format("session_id '%s' is invalid", sessionId));
}

if (StringHelper.isEmpty(userName) && StringHelper.isEmpty(keyHandle)) {
throw new Fido2RuntimeException("The request should contains either username or keyhandle");
}

ObjectNode params = dataMapperService.createObjectNode();
// Add all required parameters from request to allow process U2F request
params.put(CommonVerifiers.SUPER_GLUU_REQUEST, true);
params.put(CommonVerifiers.SUPER_GLUU_APP_ID, appId);
params.put(CommonVerifiers.SUPER_GLUU_KEY_HANDLE, keyHandle);
params.put(CommonVerifiers.SUPER_GLUU_MODE, oneStep ? SuperGluuMode.ONE_STEP.getMode() : SuperGluuMode.TWO_STEP.getMode());

params.put("username", userName);
params.put("session_id", sessionId);

log.debug("Prepared U2F_V2 assertions options request: {}", params.toString());
ObjectNode params = buildFido2AssertionStartResponse(userName, keyHandle, appId, sessionId);

ObjectNode result = assertionService.options(params);

Expand All @@ -135,6 +114,33 @@ public JsonNode startAuthentication(String userName, String keyHandle, String ap
return superGluuResult;
}

public ObjectNode buildFido2AssertionStartResponse(String userName, String keyHandle, String appId,
String sessionId) {
boolean oneStep = StringHelper.isEmpty(userName);

boolean valid = userSessionIdService.isValidSessionId(sessionId, userName);
if (!valid) {
throw new Fido2RuntimeException(String.format("session_id '%s' is invalid", sessionId));
}

if (StringHelper.isEmpty(userName) && StringHelper.isEmpty(keyHandle)) {
throw new Fido2RuntimeException("The request should contains either username or keyhandle");
}

ObjectNode params = dataMapperService.createObjectNode();
// Add all required parameters from request to allow process U2F request
params.put(CommonVerifiers.SUPER_GLUU_REQUEST, true);
params.put(CommonVerifiers.SUPER_GLUU_APP_ID, appId);
params.put(CommonVerifiers.SUPER_GLUU_KEY_HANDLE, keyHandle);
params.put(CommonVerifiers.SUPER_GLUU_MODE, oneStep ? SuperGluuMode.ONE_STEP.getMode() : SuperGluuMode.TWO_STEP.getMode());

params.put("username", userName);
params.put("session_id", sessionId);

log.debug("Prepared U2F_V2 assertions options request: {}", params.toString());
return params;
}

/* Example for one_step:
* - request:
* username: null
Expand All @@ -159,14 +165,20 @@ public JsonNode startAuthentication(String userName, String keyHandle, String ap
*
*/
public JsonNode finishAuthentication(String userName, String authenticateResponseString) {
AuthenticateResponse authenticateResponse;
try {
authenticateResponse = dataMapperService.readValue(authenticateResponseString, AuthenticateResponse.class);
} catch (IOException ex) {
throw new Fido2RpRuntimeException("Failed to parse options assertion request", ex);
}
AuthenticateResponse authenticateResponse = parseAuthenticateResponse(authenticateResponseString);

if (!ArrayUtils.contains(RawAuthenticationService.SUPPORTED_AUTHENTICATE_TYPES, authenticateResponse.getClientData().getTyp())) {
ObjectNode params = buildFido2AuthenticationVerifyResponse(userName, authenticateResponseString, authenticateResponse);

ObjectNode result = assertionService.verify(params);

result.put("status", "success");
result.put("challenge", authenticateResponse.getClientData().getChallenge());

return result;
}

public ObjectNode buildFido2AuthenticationVerifyResponse(String userName, String authenticateResponseString, AuthenticateResponse authenticateResponse) {
if (!ArrayUtils.contains(RawAuthenticationService.SUPPORTED_AUTHENTICATE_TYPES, authenticateResponse.getClientData().getTyp())) {
throw new Fido2RuntimeException("Invalid options attestation request type");
}

Expand Down Expand Up @@ -216,14 +228,18 @@ public JsonNode finishAuthentication(String userName, String authenticateRespons
}

log.debug("Prepared U2F_V2 assertion verify request: {}", params.toString());
return params;
}

ObjectNode result = assertionService.verify(params);

result.put("status", "success");
result.put("challenge", authenticateResponse.getClientData().getChallenge());

return result;
}
public AuthenticateResponse parseAuthenticateResponse(String authenticateResponseString) {
AuthenticateResponse authenticateResponse;
try {
authenticateResponse = dataMapperService.readValue(authenticateResponseString, AuthenticateResponse.class);
} catch (IOException ex) {
throw new Fido2RpRuntimeException("Failed to parse options assertion request", ex);
}
return authenticateResponse;
}

private byte[] generateAuthData(ClientData clientData, RawAuthenticateResponse rawAuthenticateResponse) throws IOException {
byte[] rpIdHash = digestService.hashSha256(clientData.getOrigin());
Expand Down

This file was deleted.

Loading

0 comments on commit d5c3fac

Please sign in to comment.