-
Notifications
You must be signed in to change notification settings - Fork 83
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(jans-auth-server): added sample custom script for authz challenge …
- Loading branch information
Showing
1 changed file
with
177 additions
and
0 deletions.
There are no files selected for viewing
177 changes: 177 additions & 0 deletions
177
docs/script-catalog/authorization_challenge/AuthorizationChallenge.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
import io.jans.as.common.model.common.User; | ||
import io.jans.as.common.model.session.DeviceSession; | ||
import io.jans.as.server.authorize.ws.rs.DeviceSessionService; | ||
import io.jans.as.server.service.UserService; | ||
import io.jans.as.server.service.external.context.ExternalScriptContext; | ||
import io.jans.model.SimpleCustomProperty; | ||
import io.jans.model.custom.script.model.CustomScript; | ||
import io.jans.model.custom.script.type.authzchallenge.AuthorizationChallengeType; | ||
import io.jans.orm.PersistenceEntryManager; | ||
import io.jans.service.cdi.util.CdiUtil; | ||
import io.jans.service.custom.script.CustomScriptManager; | ||
import org.apache.commons.lang3.StringUtils; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.util.Map; | ||
import java.util.UUID; | ||
|
||
/** | ||
* @author Yuriy Z | ||
*/ | ||
public class AuthorizationChallenge implements AuthorizationChallengeType { | ||
|
||
public static final String USERNAME_PARAMETER = "username"; | ||
public static final String PASSWORD_PARAMETER = "password"; | ||
|
||
private static final Logger log = LoggerFactory.getLogger(AuthorizationChallenge.class); | ||
private static final Logger scriptLogger = LoggerFactory.getLogger(CustomScriptManager.class); | ||
|
||
/** | ||
* Return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. | ||
* <p> | ||
* Implementation of this method should consist of 3 main parts: | ||
* 1. validate all parameters are present and if not -> set error and return false | ||
* 2. main authorization logic, if ok -> set authorized user into "context.getExecutionContext().setUser(user);" and return true | ||
* 3. if not ok -> set error which explains what is wrong and return false | ||
* | ||
* @param scriptContext ExternalScriptContext, see https://github.com/JanssenProject/jans/blob/main/jans-auth-server/server/src/main/java/io/jans/as/server/service/external/context/ExternalScriptContext.java | ||
* @return true if Authorization Challenge Endpoint should return code successfully or otherwise false if error should be returned. | ||
*/ | ||
@Override | ||
public boolean authorize(Object scriptContext) { | ||
ExternalScriptContext context = (ExternalScriptContext) scriptContext; | ||
|
||
// 1. validate all required parameters are present | ||
final String username = getParameterOrCreateError(context, USERNAME_PARAMETER); | ||
if (StringUtils.isBlank(username)) { | ||
return false; | ||
} | ||
|
||
final String password = getParameterOrCreateError(context, PASSWORD_PARAMETER); | ||
if (StringUtils.isBlank(password)) { | ||
return false; | ||
} | ||
|
||
scriptLogger.trace("All required parameters are present"); | ||
|
||
// 2. main authorization logic, if ok -> set authorized user into "context.getExecutionContext().setUser(user);" and return true | ||
UserService userService = CdiUtil.bean(UserService.class); | ||
PersistenceEntryManager entryManager = CdiUtil.bean(PersistenceEntryManager.class); | ||
|
||
final User user = userService.getUser(username); | ||
if (user == null) { | ||
context.getExecutionContext().setUser(user); | ||
scriptLogger.trace("User is not found by username {}", username); | ||
createError(context, "username_invalid"); | ||
return false; | ||
} | ||
|
||
final boolean ok = entryManager.authenticate(user.getDn(), User.class, password); | ||
if (ok) { | ||
scriptLogger.trace("User {} is authenticated successfully.", username); | ||
return true; | ||
} | ||
|
||
// 3. not ok -> set error which explains what is wrong and return false | ||
scriptLogger.trace("Failed to authenticate user {}. Please check username and password.", username); | ||
createError(context, "username_or_password_invalid"); | ||
return false; | ||
} | ||
|
||
private String getParameterOrCreateError(ExternalScriptContext context, String parameterName) { | ||
String value = context.getHttpRequest().getParameter(parameterName); | ||
|
||
if (StringUtils.isBlank(value)) { | ||
scriptLogger.trace("No '{}' parameter in request", parameterName); | ||
value = getParameterFromDeviceSession(context, parameterName); | ||
} | ||
|
||
if (StringUtils.isBlank(value)) { | ||
scriptLogger.trace("{} is not provided", parameterName); | ||
createError(context, String.format("%s_required", parameterName)); | ||
return null; | ||
} | ||
|
||
return value; | ||
} | ||
|
||
private void createError(ExternalScriptContext context, String errorCode) { | ||
String deviceSessionPart = prepareDeviceSessionSubJson(context); | ||
|
||
final String entity = String.format("{\"error\": \"%s\"%s}", errorCode, deviceSessionPart); | ||
context.createWebApplicationException(401, entity); | ||
} | ||
|
||
private String prepareDeviceSessionSubJson(ExternalScriptContext context) { | ||
DeviceSession deviceSessionObject = context.getAuthzRequest().getDeviceSessionObject(); | ||
if (deviceSessionObject != null) { | ||
prepareDeviceSession(context, deviceSessionObject); | ||
return String.format(",\"device_session\":\"%s\"", deviceSessionObject.getId()); | ||
} else if (context.getAuthzRequest().isUseDeviceSession()) { | ||
deviceSessionObject = prepareDeviceSession(context, null); | ||
return String.format(",\"device_session\":\"%s\"", deviceSessionObject.getId()); | ||
} | ||
return ""; | ||
} | ||
|
||
private DeviceSession prepareDeviceSession(ExternalScriptContext context, DeviceSession deviceSessionObject) { | ||
DeviceSessionService deviceSessionService = CdiUtil.bean(DeviceSessionService.class); | ||
boolean newSave = deviceSessionObject == null; | ||
if (newSave) { | ||
final String id = UUID.randomUUID().toString(); | ||
deviceSessionObject = new DeviceSession(); | ||
deviceSessionObject.setId(id); | ||
deviceSessionObject.setDn(deviceSessionService.buildDn(id)); | ||
} | ||
|
||
String username = context.getHttpRequest().getParameter(USERNAME_PARAMETER); | ||
if (StringUtils.isNotBlank(username)) { | ||
deviceSessionObject.getAttributes().getAttributes().put(USERNAME_PARAMETER, username); | ||
} | ||
|
||
String password = context.getHttpRequest().getParameter(PASSWORD_PARAMETER); | ||
if (StringUtils.isNotBlank(password)) { | ||
deviceSessionObject.getAttributes().getAttributes().put(PASSWORD_PARAMETER, password); | ||
} | ||
|
||
if (newSave) { | ||
deviceSessionService.persist(deviceSessionObject); | ||
} else { | ||
deviceSessionService.merge(deviceSessionObject); | ||
} | ||
|
||
return deviceSessionObject; | ||
} | ||
|
||
private String getParameterFromDeviceSession(ExternalScriptContext context, String parameterName) { | ||
final DeviceSession deviceSessionObject = context.getAuthzRequest().getDeviceSessionObject(); | ||
if (deviceSessionObject != null) { | ||
return deviceSessionObject.getAttributes().getAttributes().get(parameterName); | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public boolean init(Map<String, SimpleCustomProperty> configurationAttributes) { | ||
scriptLogger.info("Initialized Default AuthorizationChallenge Java custom script."); | ||
return true; | ||
} | ||
|
||
@Override | ||
public boolean init(CustomScript customScript, Map<String, SimpleCustomProperty> configurationAttributes) { | ||
scriptLogger.info("Initialized Default AuthorizationChallenge Java custom script."); | ||
return true; | ||
} | ||
|
||
@Override | ||
public boolean destroy(Map<String, SimpleCustomProperty> configurationAttributes) { | ||
scriptLogger.info("Destroyed Default AuthorizationChallenge Java custom script."); | ||
return true; | ||
} | ||
|
||
@Override | ||
public int getApiVersion() { | ||
return 11; | ||
} | ||
} |