From 62522fe5aaa2971835c76e8e9b0d4280fee1db32 Mon Sep 17 00:00:00 2001 From: Arnab Dutta <32794267+duttarnab@users.noreply.github.com> Date: Mon, 30 May 2022 11:34:28 +0530 Subject: [PATCH] feat: endpoint to get details of connected FIDO devices registered to users #1465 (#1466) * feat: need endpoint to get details of connected FIDO devices registered to users #1465 * feat: need endpoint to get details of connected FIDO devices registered to users #1465 --- .../io/jans/configapi/util/ApiConstants.java | 1 + .../docs/jans-config-api-swagger.yaml | 105 +++++++++++++++++ .../plugins/admin-ui-plugin/pom.xml | 2 +- jans-config-api/plugins/fido2-plugin/pom.xml | 5 + .../src/main/assembly/assembly.xml | 11 ++ .../plugin/fido2/rest/ApiApplication.java | 1 + .../fido2/rest/Fido2RegistrationResource.java | 38 +++++++ .../service/Fido2RegistrationService.java | 106 ++++++++++++++++++ .../plugin/fido2/util/Constants.java | 4 +- 9 files changed, 271 insertions(+), 2 deletions(-) create mode 100644 jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/rest/Fido2RegistrationResource.java create mode 100644 jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/service/Fido2RegistrationService.java diff --git a/jans-config-api/common/src/main/java/io/jans/configapi/util/ApiConstants.java b/jans-config-api/common/src/main/java/io/jans/configapi/util/ApiConstants.java index 3b3e4dc4f9a..c0561e45b36 100644 --- a/jans-config-api/common/src/main/java/io/jans/configapi/util/ApiConstants.java +++ b/jans-config-api/common/src/main/java/io/jans/configapi/util/ApiConstants.java @@ -73,6 +73,7 @@ private ApiConstants() {} public static final String USER = "/user"; public static final String ORG = "/org"; public static final String SERVER_STAT = "/server-stat"; + public static final String USERNAME_PATH = "{username}"; public static final String LIMIT = "limit"; public static final String START_INDEX = "startIndex"; diff --git a/jans-config-api/docs/jans-config-api-swagger.yaml b/jans-config-api/docs/jans-config-api-swagger.yaml index 4c454384deb..d5e3c0b2f7d 100644 --- a/jans-config-api/docs/jans-config-api-swagger.yaml +++ b/jans-config-api/docs/jans-config-api-swagger.yaml @@ -162,6 +162,30 @@ paths: security: - oauth2: [https://jans.io/oauth/config/fido2.write] parameters: [] + /jans-config-api/fido2/registration/entries/{username}: + get: + summary: Get details of connected FIDO2 devices registered to user. + description: Get details of connected FIDO2 devices registered to user. + operationId: get-registration-entries-fido2 + tags: + - Fido2 - Configuration + responses: + '200': + description: OK + content: + application/json: + schema: + title: FIDO2 registered devices + description: List of all FIDO2 registered devices. + type: array + items: + $ref: '#/components/schemas/Fido2RegistrationEntry' + '401': + $ref: '#/components/responses/Unauthorized' + '500': + $ref: '#/components/responses/InternalServerError' + security: + - oauth2: [ https://jans.io/oauth/config/fido2.readonly ] /jans-config-api/api/v1/attributes: get: summary: Gets a list of Gluu attributes. @@ -5752,6 +5776,87 @@ components: description: Fido2Configuration. $ref: '#/components/schemas/Fido2Configuration' + Fido2RegistrationEntry: + type: object + description: Fido2 registration entry + properties: + publicKeyId: + description: Public key id + type: string + displayName: + description: Dislay name + type: string + counter: + description: counter + type: integer + deviceNotificationConf: + description: Device notification configuration + type: string + challangeHash: + description: Challange hash + type: string + registrationData: + description: Fido2 registration data. + $ref: '#/components/schemas/Fido2RegistrationData' + registrationStatus: + description: registration status + type: string + enum: + - pending + - registered + - compromised + + Fido2RegistrationData: + type: object + description: Fido2 registration data. + properties: + username: + description: Username + type: string + domain: + description: Domain + type: string + userId: + description: user id + type: string + challenge: + description: challenge + type: string + attenstationRequest: + description: Attenstation request + type: string + attenstationResponse: + description: Attenstation response + type: string + uncompressedECPoint: + description: uncompressed EC point + type: string + publicKeyId: + description: public key id + type: string + type: + description: type + type: string + counter: + description: counter + type: integer + attestationType: + description: attestation type + type: string + signatureAlgorithm: + description: signature algorithm + type: integer + applicationId: + description: application id + type: string + status: + description: status + type: string + enum: + - pending + - registered + - compromised + Fido2Configuration: type: object description: Fido2 configuration properties. diff --git a/jans-config-api/plugins/admin-ui-plugin/pom.xml b/jans-config-api/plugins/admin-ui-plugin/pom.xml index 664846ef554..50875c66a94 100644 --- a/jans-config-api/plugins/admin-ui-plugin/pom.xml +++ b/jans-config-api/plugins/admin-ui-plugin/pom.xml @@ -21,7 +21,7 @@ io.jans - jans-config-api-server + jans-config-api-shared compile diff --git a/jans-config-api/plugins/fido2-plugin/pom.xml b/jans-config-api/plugins/fido2-plugin/pom.xml index f93382b377f..7390bbd721a 100644 --- a/jans-config-api/plugins/fido2-plugin/pom.xml +++ b/jans-config-api/plugins/fido2-plugin/pom.xml @@ -22,6 +22,11 @@ jans-config-api-shared ${jans.version} + + io.jans + jans-fido2-model + ${jans.version} + io.jans jans-config-api-server diff --git a/jans-config-api/plugins/fido2-plugin/src/main/assembly/assembly.xml b/jans-config-api/plugins/fido2-plugin/src/main/assembly/assembly.xml index 4a93c3a8515..986c9836a7f 100644 --- a/jans-config-api/plugins/fido2-plugin/src/main/assembly/assembly.xml +++ b/jans-config-api/plugins/fido2-plugin/src/main/assembly/assembly.xml @@ -7,6 +7,17 @@ jar false + + + true + / + false + + io.jans:jans-fido2-model + + runtime + + ${project.build.directory}/classes diff --git a/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/rest/ApiApplication.java b/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/rest/ApiApplication.java index cc868cbfe10..e1588c80b6c 100644 --- a/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/rest/ApiApplication.java +++ b/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/rest/ApiApplication.java @@ -13,6 +13,7 @@ public Set> getClasses() { HashSet> classes = new HashSet<>(); classes.add(Fido2ConfigResource.class); + classes.add(Fido2RegistrationResource.class); return classes; } diff --git a/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/rest/Fido2RegistrationResource.java b/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/rest/Fido2RegistrationResource.java new file mode 100644 index 00000000000..c41936eda43 --- /dev/null +++ b/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/rest/Fido2RegistrationResource.java @@ -0,0 +1,38 @@ +package io.jans.configapi.plugin.fido2.rest; + +import io.jans.configapi.core.rest.BaseResource; +import io.jans.configapi.core.rest.ProtectedApi; +import io.jans.configapi.plugin.fido2.service.Fido2RegistrationService; +import io.jans.configapi.plugin.fido2.util.Constants; +import io.jans.configapi.util.ApiAccessConstants; +import io.jans.configapi.util.ApiConstants; +import io.jans.fido2.model.entry.Fido2RegistrationEntry; +import jakarta.inject.Inject; +import jakarta.validation.constraints.NotNull; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.slf4j.Logger; + +import java.util.List; + +@Path(Constants.REGISTRATION) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +public class Fido2RegistrationResource extends BaseResource { + + @Inject + Logger logger; + + @Inject + Fido2RegistrationService fido2RegistrationService; + + @GET + @Path(Constants.ENTRIES + ApiConstants.USERNAME_PATH) + @ProtectedApi(scopes = {ApiAccessConstants.FIDO2_CONFIG_READ_ACCESS}) + public Response findAllRegisteredByUsername(@PathParam("username") @NotNull String username) { + logger.debug("FIDO2 registration entries by username."); + List entries = fido2RegistrationService.findAllRegisteredByUsername(username); + return Response.ok(entries).build(); + } +} diff --git a/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/service/Fido2RegistrationService.java b/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/service/Fido2RegistrationService.java new file mode 100644 index 00000000000..44b89fa2b4c --- /dev/null +++ b/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/service/Fido2RegistrationService.java @@ -0,0 +1,106 @@ +/* + * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. + * + * Copyright (c) 2020, Janssen Project + */ + +package io.jans.configapi.plugin.fido2.service; + +import io.jans.as.common.service.common.UserService; +import io.jans.as.model.config.StaticConfiguration; +import io.jans.fido2.model.entry.Fido2RegistrationEntry; +import io.jans.fido2.model.entry.Fido2RegistrationStatus; +import io.jans.orm.PersistenceEntryManager; +import io.jans.orm.model.base.SimpleBranch; +import io.jans.orm.search.filter.Filter; +import io.jans.util.StringHelper; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import org.slf4j.Logger; + +import java.util.Collections; +import java.util.List; + +/** + * @author Yuriy Movchan + * @version May 08, 2020 + */ +@ApplicationScoped +public class Fido2RegistrationService { + + @Inject + private Logger log; + + @Inject + private StaticConfiguration staticConfiguration; + + @Inject + private UserService userService; + + @Inject + private PersistenceEntryManager persistenceEntryManager; + + public List findAllByUsername(String username) { + String userInum = userService.getUserInum(username); + if (userInum == null) { + return Collections.emptyList(); + } + + String baseDn = getBaseDnForFido2RegistrationEntries(userInum); + if (persistenceEntryManager.hasBranchesSupport(baseDn)) { + if (!containsBranch(baseDn)) { + return Collections.emptyList(); + } + } + + Filter userFilter = Filter.createEqualityFilter("personInum", userInum); + + List fido2RegistrationnEntries = persistenceEntryManager.findEntries(baseDn, Fido2RegistrationEntry.class, userFilter); + + return fido2RegistrationnEntries; + } + + public List findAllRegisteredByUsername(String username) { + String userInum = userService.getUserInum(username); + if (userInum == null) { + return Collections.emptyList(); + } + + String baseDn = getBaseDnForFido2RegistrationEntries(userInum); + if (persistenceEntryManager.hasBranchesSupport(baseDn)) { + if (!containsBranch(baseDn)) { + return Collections.emptyList(); + } + } + + Filter userInumFilter = Filter.createEqualityFilter("personInum", userInum); + Filter registeredFilter = Filter.createEqualityFilter("jansStatus", Fido2RegistrationStatus.registered.getValue()); + Filter filter = Filter.createANDFilter(userInumFilter, registeredFilter); + + List fido2RegistrationnEntries = persistenceEntryManager.findEntries(baseDn, Fido2RegistrationEntry.class, filter); + + return fido2RegistrationnEntries; + } + + public String getBaseDnForFido2RegistrationEntries(String userInum) { + final String userBaseDn = getDnForUser(userInum); // "ou=fido2_register,inum=1234,ou=people,o=jans" + if (StringHelper.isEmpty(userInum)) { + return userBaseDn; + } + + return String.format("ou=fido2_register,%s", userBaseDn); + } + + public String getDnForUser(String userInum) { + String peopleDn = staticConfiguration.getBaseDn().getPeople(); + if (StringHelper.isEmpty(userInum)) { + return peopleDn; + } + + return String.format("inum=%s,%s", userInum, peopleDn); + } + + public boolean containsBranch(final String baseDn) { + return persistenceEntryManager.contains(baseDn, SimpleBranch.class); + } +} diff --git a/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/util/Constants.java b/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/util/Constants.java index a55d0418ec3..453657c14da 100644 --- a/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/util/Constants.java +++ b/jans-config-api/plugins/fido2-plugin/src/main/java/io/jans/configapi/plugin/fido2/util/Constants.java @@ -10,5 +10,7 @@ public class Constants { private Constants() {} - public static final String CONFIG = "/config"; + public static final String CONFIG = "/config"; + public static final String REGISTRATION = "/registration"; + public static final String ENTRIES = "/entries"; } \ No newline at end of file