diff --git a/CHANGELOG.md b/CHANGELOG.md index f366b91..47fcbf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## [1.4.0] - 2024-11-16 + +### Breaking Changes +- Renamed project from `khode-two-factor-auth` to `khode-2fa` +- Removed duplicate endpoint `isTotpConfigured` (use `getTotpStatus` instead) +- Changed all API endpoint paths to use new provider ID + +### Changed +- Updated all API endpoint paths to use `khode-2fa` identifier +- Updated all documentation to reflect new provider ID +- Streamlined API by consolidating status check functionality into single endpoint + +### Migration +- Update all API paths from `/khode-two-factor-auth/` to `/khode-2fa/` +- Replace `isTotpConfigured` endpoint calls with `getTotpStatus` + +### Technical +- Changed PROVIDER_ID constant in KhodeResourceProviderFactory.java +- Removed redundant endpoint code from KhodeResourceService +- Updated API path references in documentation + + ## [1.3.0] - 2024-11-15 ### Added diff --git a/README.md b/README.md index 3de1877..d05b972 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# khode-two-factor-auth +# Keycloak 2FA Rest API Extension -khode-two-factor-auth is a Keycloak extension that provides a REST API for managing Time-based One-Time Password (TOTP) +khode-2fa is a Keycloak extension that provides a REST API for managing Time-based One-Time Password (TOTP) authentication. This extension allows you to set up, verify, enable, disable, and validate TOTP for users in a Keycloak realm. @@ -63,7 +63,7 @@ After installing using either method, restart Keycloak to load the new extension This extension provides the following REST endpoints for managing TOTP authentication. **Note:** Requirement for before using it: - - Simple URL: `http://keycloak-server:[port]/realms/{realm}/khode-two-factor-auth/` + - Simple URL: `http://keycloak-server:[port]/realms/{realm}/khode-2fa` - Replace `{realm}` and `{user_id}` with the appropriate values. **Authentication Requirements:** @@ -101,29 +101,10 @@ TOKEN=$(curl -X POST \ | jq -r '.access_token') ``` -### Check if TOTP is Configured - -```http -GET /realms/{realm}/khode-two-factor-auth/totp/is-configured/{user_id} -``` - -Returns: - -```json -{ - "configured": true, - "message": "TOTP is configured for this user", - "userId": "user-123", - "code": 0 -} -``` - -Checks if TOTP is already configured for the user. - ### Setup TOTP ```http -POST /realms/{realm}/khode-two-factor-auth/totp/setup/{user_id} +POST /realms/{realm}/khode-2fa/totp/setup/{user_id} ``` Returns: @@ -152,7 +133,7 @@ Generates a TOTP secret for the user and returns the secret and QR code. ### Verify and Enable TOTP ```http -POST /realms/{realm}/khode-two-factor-auth/totp/verify/{user_id} +POST /realms/{realm}/khode-2fa/totp/verify/{user_id} Content-Type: application/json { @@ -175,7 +156,7 @@ Verifies the TOTP code and enables TOTP for the user. ### Get TOTP Status ```http -GET /realms/{realm}/khode-two-factor-auth/totp/status/{user_id} +GET /realms/{realm}/khode-2fa/totp/status/{user_id} ``` Returns: @@ -200,7 +181,7 @@ Returns the TOTP status and credentials for the user. ### Validate TOTP Code ```http -POST /realms/{realm}/khode-two-factor-auth/totp/validate/{user_id} +POST /realms/{realm}/khode-2fa/totp/validate/{user_id} Content-Type: application/json { @@ -224,7 +205,7 @@ Validates the TOTP code for an existing TOTP setup. ### Disable TOTP ```http -DELETE /realms/{realm}/khode-two-factor-auth/totp/{user_id} +DELETE /realms/{realm}/khode-2fa/totp/{user_id} ``` Returns: @@ -243,7 +224,7 @@ Disables TOTP for the user. ### Disable TOTP with Validation (Disable with single endpoint request) ```http -POST /realms/{realm}/khode-two-factor-auth/totp/disable-with-validation/{user_id} +POST /realms/{realm}/khode-2fa/totp/disable-with-validation/{user_id} Content-Type: application/json { diff --git a/pom.xml b/pom.xml index 41ce407..c015ca7 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.khodecamp khode-two-factor-auth - 1.3.0 + 1.4.0 jar diff --git a/src/main/java/com/khodecamp/KhodeResourceProvider.java b/src/main/java/com/khodecamp/KhodeResourceProvider.java index 69c76b4..f0869f1 100644 --- a/src/main/java/com/khodecamp/KhodeResourceProvider.java +++ b/src/main/java/com/khodecamp/KhodeResourceProvider.java @@ -37,17 +37,6 @@ public void close() { } - @GET - @Path("totp/is-configured/{user_id}") - @Produces(MediaType.APPLICATION_JSON) - @Operation(summary = "Check if TOTP is configured for user") - @APIResponse(responseCode = "200", description = "TOTP status retrieved successfully") - @APIResponse(responseCode = "400", description = "Invalid user ID") - @APIResponse(responseCode = "500", description = "Internal server error") - public Response isTotpConfigured(@PathParam("user_id") final String userid) { - return khodeResourceService.isTotpConfigured(userid); - } - @POST @Path("totp/setup/{user_id}") @Produces(MediaType.APPLICATION_JSON) diff --git a/src/main/java/com/khodecamp/KhodeResourceProviderFactory.java b/src/main/java/com/khodecamp/KhodeResourceProviderFactory.java index e66d67d..20bb5cd 100644 --- a/src/main/java/com/khodecamp/KhodeResourceProviderFactory.java +++ b/src/main/java/com/khodecamp/KhodeResourceProviderFactory.java @@ -10,7 +10,7 @@ @AutoService(RealmResourceProviderFactory.class) public class KhodeResourceProviderFactory implements RealmResourceProviderFactory { - public static final String PROVIDER_ID = "khode-two-factor-auth"; + public static final String PROVIDER_ID = "khode-2fa"; @Override public RealmResourceProvider create(KeycloakSession keycloakSession) { diff --git a/src/main/java/com/khodecamp/KhodeResourceService.java b/src/main/java/com/khodecamp/KhodeResourceService.java index 272016b..dbe791b 100644 --- a/src/main/java/com/khodecamp/KhodeResourceService.java +++ b/src/main/java/com/khodecamp/KhodeResourceService.java @@ -130,7 +130,7 @@ private Response handleServerError(String operation, String userid, Exception e) .build(); } - public Response isTotpConfigured(final String userid) { + public Response getTotpStatus(final String userid) { try { Response validation = validateUserId(userid); if (validation != null) return validation; @@ -145,8 +145,8 @@ public Response isTotpConfigured(final String userid) { .isPresent(); return Response.ok(Map.of( - "configured", hasTotp, - "message", hasTotp ? "TOTP is configured for this user" : "TOTP is not configured for this user", + "enabled", hasTotp, + "message", hasTotp ? "TOTP is enabled" : "TOTP is not enabled", "userId", userid, "code", CODE_SUCCESS )).build(); @@ -303,51 +303,6 @@ public Response verifyAndEnableTotp(final String userid, Map dat } } - public Response getTotpStatus(final String userid) { - try { - Response validation = validateUserId(userid); - if (validation != null) return validation; - - // Check if the request is authenticated - checkAuth(userid); - - final UserModel user = getUserContext(userid); - final RealmModel realm = session.getContext().getRealm(); - TotpBean totpBean = new TotpBean(session, realm, user, null); - - var credentials = totpBean.getOtpCredentials().stream() - .map(credential -> Map.of( - "id", credential.getId(), - "type", credential.getType(), - "createdDate", credential.getCreatedDate() - )) - .toList(); - - return Response.ok(Map.of( - "enabled", totpBean.isEnabled(), - "credentials", credentials, - "userId", userid, - "code", CODE_SUCCESS - )).build(); - } catch (NotAuthorizedException e) { - return Response.status(Response.Status.UNAUTHORIZED) - .entity(Map.of( - "error", "Unauthorized", - "code", CODE_UNAUTHORIZED - )) - .build(); - } catch (ForbiddenException e) { - return Response.status(Response.Status.BAD_REQUEST) - .entity(Map.of( - "error", "Forbidden", - "code", CODE_FORBIDDEN - )) - .build(); - } catch (Exception e) { - return handleServerError("getting TOTP status", userid, e); - } - } - public Response validateTotp(final String userId, Map data) { Response validation = validateUserId(userId); if (validation != null) return validation;