Skip to content

Commit

Permalink
Merge pull request #6 from chornthorn/refactor/khode-2fa-provider
Browse files Browse the repository at this point in the history
refactor: rename provider to khode-2fa and remove duplicate endpoint
  • Loading branch information
chornthorn authored Nov 16, 2024
2 parents 3624c93 + 4ed3d22 commit 961247e
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 89 deletions.
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
37 changes: 9 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -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:**
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
{
Expand All @@ -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:
Expand All @@ -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
{
Expand All @@ -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:
Expand All @@ -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
{
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.khodecamp</groupId>
<artifactId>khode-two-factor-auth</artifactId>
<version>1.3.0</version>
<version>1.4.0</version>
<packaging>jar</packaging>

<dependencies>
Expand Down
11 changes: 0 additions & 11 deletions src/main/java/com/khodecamp/KhodeResourceProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
51 changes: 3 additions & 48 deletions src/main/java/com/khodecamp/KhodeResourceService.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
Expand Down Expand Up @@ -303,51 +303,6 @@ public Response verifyAndEnableTotp(final String userid, Map<String, String> 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<String, String> data) {
Response validation = validateUserId(userId);
if (validation != null) return validation;
Expand Down

0 comments on commit 961247e

Please sign in to comment.