use of io.jans.as.model.error.DefaultErrorResponse in project jans by JanssenProject.
the class BackchannelAuthorizeRestWebServiceImpl method requestBackchannelAuthorizationPost.
@Override
public Response requestBackchannelAuthorizationPost(String clientId, String scope, String clientNotificationToken, String acrValues, String loginHintToken, String idTokenHint, String loginHint, String bindingMessage, String userCodeParam, Integer requestedExpiry, String request, String requestUri, HttpServletRequest httpRequest, HttpServletResponse httpResponse, SecurityContext securityContext) {
// it may be encoded
scope = ServerUtil.urlDecode(scope);
OAuth2AuditLog oAuth2AuditLog = new OAuth2AuditLog(ServerUtil.getIpAddress(httpRequest), Action.BACKCHANNEL_AUTHENTICATION);
oAuth2AuditLog.setClientId(clientId);
oAuth2AuditLog.setScope(scope);
// ATTENTION : please do not add more parameter in this debug method because it will not work with Seam 2.2.2.Final,
// there is limit of 10 parameters (hardcoded), see: org.jboss.seam.core.Interpolator#interpolate
log.debug("Attempting to request backchannel authorization: " + "clientId = {}, scope = {}, clientNotificationToken = {}, acrValues = {}, loginHintToken = {}, " + "idTokenHint = {}, loginHint = {}, bindingMessage = {}, userCodeParam = {}, requestedExpiry = {}, " + "request= {}", clientId, scope, clientNotificationToken, acrValues, loginHintToken, idTokenHint, loginHint, bindingMessage, userCodeParam, requestedExpiry, request);
log.debug("Attempting to request backchannel authorization: " + "isSecure = {}", securityContext.isSecure());
errorResponseFactory.validateComponentEnabled(ComponentType.CIBA);
Response.ResponseBuilder builder = Response.ok();
SessionClient sessionClient = identity.getSessionClient();
Client client = null;
if (sessionClient != null) {
client = sessionClient.getClient();
}
if (client == null) {
// 401
builder = Response.status(Response.Status.UNAUTHORIZED.getStatusCode());
builder.entity(errorResponseFactory.getErrorAsJson(INVALID_CLIENT));
return builder.build();
}
if (!cibaRequestService.hasCibaCompatibility(client)) {
// 401
builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
builder.entity(errorResponseFactory.getErrorAsJson(INVALID_REQUEST));
return builder.build();
}
List<String> scopes = new ArrayList<>();
if (StringHelper.isNotEmpty(scope)) {
Set<String> grantedScopes = scopeChecker.checkScopesPolicy(client, scope);
scopes.addAll(grantedScopes);
}
JwtAuthorizationRequest jwtRequest = null;
if (StringUtils.isNotBlank(request) || StringUtils.isNotBlank(requestUri)) {
jwtRequest = JwtAuthorizationRequest.createJwtRequest(request, requestUri, client, null, cryptoProvider, appConfiguration);
if (jwtRequest == null) {
log.error("The JWT couldn't be processed");
// 400
builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
builder.entity(errorResponseFactory.getErrorAsJson(INVALID_REQUEST));
throw new WebApplicationException(builder.build());
}
authorizeRestWebServiceValidator.validateCibaRequestObject(jwtRequest, client.getClientId());
// JWT wins
if (!jwtRequest.getScopes().isEmpty()) {
scopes.addAll(scopeChecker.checkScopesPolicy(client, jwtRequest.getScopes()));
}
if (StringUtils.isNotBlank(jwtRequest.getClientNotificationToken())) {
clientNotificationToken = jwtRequest.getClientNotificationToken();
}
if (StringUtils.isNotBlank(jwtRequest.getAcrValues())) {
acrValues = jwtRequest.getAcrValues();
}
if (StringUtils.isNotBlank(jwtRequest.getLoginHintToken())) {
loginHintToken = jwtRequest.getLoginHintToken();
}
if (StringUtils.isNotBlank(jwtRequest.getIdTokenHint())) {
idTokenHint = jwtRequest.getIdTokenHint();
}
if (StringUtils.isNotBlank(jwtRequest.getLoginHint())) {
loginHint = jwtRequest.getLoginHint();
}
if (StringUtils.isNotBlank(jwtRequest.getBindingMessage())) {
bindingMessage = jwtRequest.getBindingMessage();
}
if (StringUtils.isNotBlank(jwtRequest.getUserCode())) {
userCodeParam = jwtRequest.getUserCode();
}
if (jwtRequest.getRequestedExpiry() != null) {
requestedExpiry = jwtRequest.getRequestedExpiry();
} else if (jwtRequest.getExp() != null) {
requestedExpiry = Math.toIntExact(jwtRequest.getExp() - System.currentTimeMillis() / 1000);
}
}
if (appConfiguration.isFapi() && jwtRequest == null) {
// 400
builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
builder.entity(errorResponseFactory.getErrorAsJson(INVALID_REQUEST));
return builder.build();
}
User user = null;
try {
if (Strings.isNotBlank(loginHint)) {
// login_hint
user = userService.getUniqueUserByAttributes(appConfiguration.getBackchannelLoginHintClaims(), loginHint);
} else if (Strings.isNotBlank(idTokenHint)) {
// id_token_hint
AuthorizationGrant authorizationGrant = authorizationGrantList.getAuthorizationGrantByIdToken(idTokenHint);
if (authorizationGrant == null) {
// 400
builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
builder.entity(errorResponseFactory.getErrorAsJson(UNKNOWN_USER_ID));
return builder.build();
}
user = authorizationGrant.getUser();
}
if (Strings.isNotBlank(loginHintToken)) {
// login_hint_token
Jwt jwt = Jwt.parse(loginHintToken);
SignatureAlgorithm algorithm = jwt.getHeader().getSignatureAlgorithm();
String keyId = jwt.getHeader().getKeyId();
if (algorithm == null || Strings.isBlank(keyId)) {
// 400
builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
builder.entity(errorResponseFactory.getErrorAsJson(UNKNOWN_USER_ID));
return builder.build();
}
boolean validSignature = false;
if (algorithm.getFamily() == AlgorithmFamily.RSA) {
RSAPublicKey publicKey = JwkClient.getRSAPublicKey(client.getJwksUri(), keyId);
RSASigner rsaSigner = new RSASigner(algorithm, publicKey);
validSignature = rsaSigner.validate(jwt);
} else if (algorithm.getFamily() == AlgorithmFamily.EC) {
ECDSAPublicKey publicKey = JwkClient.getECDSAPublicKey(client.getJwksUri(), keyId);
ECDSASigner ecdsaSigner = new ECDSASigner(algorithm, publicKey);
validSignature = ecdsaSigner.validate(jwt);
}
if (!validSignature) {
// 400
builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
builder.entity(errorResponseFactory.getErrorAsJson(UNKNOWN_USER_ID));
return builder.build();
}
JSONObject subject = jwt.getClaims().getClaimAsJSON("subject");
if (subject == null || !subject.has("subject_type") || !subject.has(subject.getString("subject_type"))) {
// 400
builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
builder.entity(errorResponseFactory.getErrorAsJson(UNKNOWN_USER_ID));
return builder.build();
}
String subjectTypeKey = subject.getString("subject_type");
String subjectTypeValue = subject.getString(subjectTypeKey);
user = userService.getUniqueUserByAttributes(appConfiguration.getBackchannelLoginHintClaims(), subjectTypeValue);
}
} catch (InvalidJwtException e) {
log.error(e.getMessage(), e);
} catch (JSONException e) {
log.error(e.getMessage(), e);
}
if (user == null) {
// 400
builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
builder.entity(errorResponseFactory.getErrorAsJson(UNKNOWN_USER_ID));
return builder.build();
}
try {
String userCode = (String) user.getAttribute("jansBackchannelUsrCode", true, false);
DefaultErrorResponse cibaAuthorizeParamsValidation = cibaAuthorizeParamsValidatorService.validateParams(scopes, clientNotificationToken, client.getBackchannelTokenDeliveryMode(), loginHintToken, idTokenHint, loginHint, bindingMessage, client.getBackchannelUserCodeParameter(), userCodeParam, userCode, requestedExpiry);
if (cibaAuthorizeParamsValidation != null) {
builder = Response.status(cibaAuthorizeParamsValidation.getStatus());
builder.entity(errorResponseFactory.errorAsJson(cibaAuthorizeParamsValidation.getType(), cibaAuthorizeParamsValidation.getReason()));
return builder.build();
}
String deviceRegistrationToken = (String) user.getAttribute("jansBackchannelDeviceRegistrationTkn", true, false);
if (deviceRegistrationToken == null) {
// 401
builder = Response.status(Response.Status.UNAUTHORIZED.getStatusCode());
builder.entity(errorResponseFactory.getErrorAsJson(UNAUTHORIZED_END_USER_DEVICE));
return builder.build();
}
int expiresIn = requestedExpiry != null ? requestedExpiry : appConfiguration.getBackchannelAuthenticationResponseExpiresIn();
Integer interval = client.getBackchannelTokenDeliveryMode() == BackchannelTokenDeliveryMode.PUSH ? null : appConfiguration.getBackchannelAuthenticationResponseInterval();
long currentTime = new Date().getTime();
CibaRequestCacheControl cibaRequestCacheControl = new CibaRequestCacheControl(user, client, expiresIn, scopes, clientNotificationToken, bindingMessage, currentTime, acrValues);
cibaRequestService.save(cibaRequestCacheControl, expiresIn);
String authReqId = cibaRequestCacheControl.getAuthReqId();
// Notify End-User to obtain Consent/Authorization
cibaEndUserNotificationService.notifyEndUser(cibaRequestCacheControl.getScopesAsString(), cibaRequestCacheControl.getAcrValues(), authReqId, deviceRegistrationToken);
builder.entity(getJSONObject(authReqId, expiresIn, interval).toString(4).replace("\\/", "/"));
builder.type(MediaType.APPLICATION_JSON_TYPE);
builder.cacheControl(ServerUtil.cacheControl(true, false));
} catch (JSONException e) {
builder = Response.status(400);
builder.entity(errorResponseFactory.getErrorAsJson(INVALID_REQUEST));
log.error(e.getMessage(), e);
} catch (InvalidClaimException e) {
builder = Response.status(400);
builder.entity(errorResponseFactory.getErrorAsJson(INVALID_REQUEST));
log.error(e.getMessage(), e);
}
applicationAuditLogger.sendMessage(oAuth2AuditLog);
return builder.build();
}
use of io.jans.as.model.error.DefaultErrorResponse in project jans by JanssenProject.
the class CIBADeviceRegistrationValidatorService method validateParams.
public DefaultErrorResponse validateParams(String idTokenHint, String deviceRegistrationToken) {
if (Strings.isBlank(deviceRegistrationToken)) {
DefaultErrorResponse errorResponse = new DefaultErrorResponse();
// 400
errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
errorResponse.setType(INVALID_REQUEST);
errorResponse.setReason("The device registration token cannot be blank.");
return errorResponse;
}
if (Strings.isBlank(idTokenHint)) {
DefaultErrorResponse errorResponse = new DefaultErrorResponse();
// 400
errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
errorResponse.setType(UNKNOWN_USER_ID);
errorResponse.setReason("The id token hint cannot be blank.");
return errorResponse;
}
return null;
}
use of io.jans.as.model.error.DefaultErrorResponse in project jans by JanssenProject.
the class BackchannelDeviceRegistrationRestWebServiceImpl method requestBackchannelDeviceRegistrationPost.
@Override
public Response requestBackchannelDeviceRegistrationPost(String idTokenHint, String deviceRegistrationToken, HttpServletRequest httpRequest, HttpServletResponse httpResponse, SecurityContext securityContext) {
OAuth2AuditLog oAuth2AuditLog = new OAuth2AuditLog(ServerUtil.getIpAddress(httpRequest), Action.BACKCHANNEL_DEVICE_REGISTRATION);
// ATTENTION : please do not add more parameter in this debug method because it will not work with Seam 2.2.2.Final,
// there is limit of 10 parameters (hardcoded), see: org.jboss.seam.core.Interpolator#interpolate
log.debug("Attempting to request backchannel device registration: " + "idTokenHint = {}, deviceRegistrationToken = {}, isSecure = {}", idTokenHint, deviceRegistrationToken, securityContext.isSecure());
errorResponseFactory.validateComponentEnabled(ComponentType.CIBA);
Response.ResponseBuilder builder = Response.ok();
DefaultErrorResponse cibaDeviceRegistrationValidation = cibaDeviceRegistrationValidatorService.validateParams(idTokenHint, deviceRegistrationToken);
if (cibaDeviceRegistrationValidation != null) {
builder = Response.status(cibaDeviceRegistrationValidation.getStatus());
builder.entity(errorResponseFactory.errorAsJson(cibaDeviceRegistrationValidation.getType(), cibaDeviceRegistrationValidation.getReason()));
return builder.build();
}
User user = null;
AuthorizationGrant authorizationGrant = authorizationGrantList.getAuthorizationGrantByIdToken(idTokenHint);
if (authorizationGrant == null) {
// 400
builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
builder.entity(errorResponseFactory.getErrorAsJson(BackchannelAuthenticationErrorResponseType.UNKNOWN_USER_ID));
return builder.build();
}
user = authorizationGrant.getUser();
if (user == null) {
// 400
builder = Response.status(Response.Status.BAD_REQUEST.getStatusCode());
builder.entity(errorResponseFactory.getErrorAsJson(UNKNOWN_USER_ID));
return builder.build();
}
userService.setCustomAttribute(user, "jansBackchannelDeviceRegistrationTkn", deviceRegistrationToken);
userService.updateUser(user);
applicationAuditLogger.sendMessage(oAuth2AuditLog);
return builder.build();
}
use of io.jans.as.model.error.DefaultErrorResponse in project jans by JanssenProject.
the class CIBAAuthorizeParamsValidatorService method validateParams.
public DefaultErrorResponse validateParams(List<String> scopeList, String clientNotificationToken, BackchannelTokenDeliveryMode tokenDeliveryMode, String loginHintToken, String idTokenHint, String loginHint, String bindingMessage, Boolean backchannelUserCodeParameter, String userCodeParam, String userCode, Integer requestedExpirity) {
if (tokenDeliveryMode == null) {
DefaultErrorResponse errorResponse = new DefaultErrorResponse();
errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
errorResponse.setType(UNAUTHORIZED_CLIENT);
errorResponse.setReason("Clients registering to use CIBA must indicate a token delivery mode.");
return errorResponse;
}
if (scopeList == null || !scopeList.contains("openid")) {
DefaultErrorResponse errorResponse = new DefaultErrorResponse();
errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
errorResponse.setType(INVALID_SCOPE);
errorResponse.setReason("CIBA authentication requests must contain the openid scope value.");
return errorResponse;
}
if (!validateOneParamNotBlank(loginHintToken, idTokenHint, loginHint)) {
DefaultErrorResponse errorResponse = new DefaultErrorResponse();
errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
errorResponse.setType(INVALID_REQUEST);
errorResponse.setReason("It is required that the Client provides one (and only one) of the hints in the authentication " + "request, that is login_hint_token, id_token_hint or login_hint.");
return errorResponse;
}
if (tokenDeliveryMode == BackchannelTokenDeliveryMode.PING || tokenDeliveryMode == BackchannelTokenDeliveryMode.PUSH) {
if (Strings.isBlank(clientNotificationToken)) {
DefaultErrorResponse errorResponse = new DefaultErrorResponse();
errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
errorResponse.setType(INVALID_REQUEST);
errorResponse.setReason("The client notification token is required if the Client is registered to use Ping or Push modes.");
return errorResponse;
}
}
if (Strings.isNotBlank(bindingMessage)) {
final Pattern pattern = Pattern.compile(appConfiguration.getBackchannelBindingMessagePattern());
if (!pattern.matcher(bindingMessage).matches()) {
DefaultErrorResponse errorResponse = new DefaultErrorResponse();
errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
errorResponse.setType(INVALID_BINDING_MESSAGE);
errorResponse.setReason("The provided binding message is unacceptable. It must match the pattern: " + pattern.pattern());
return errorResponse;
}
}
if (BooleanUtils.isTrue(backchannelUserCodeParameter)) {
if (Strings.isBlank(userCodeParam)) {
DefaultErrorResponse errorResponse = new DefaultErrorResponse();
errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
errorResponse.setType(INVALID_USER_CODE);
errorResponse.setReason("The user code is required.");
return errorResponse;
} else if (Strings.isBlank(userCode)) {
DefaultErrorResponse errorResponse = new DefaultErrorResponse();
errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
errorResponse.setType(INVALID_USER_CODE);
errorResponse.setReason("The user code is not set.");
return errorResponse;
} else if (!userCode.equals(userCodeParam)) {
DefaultErrorResponse errorResponse = new DefaultErrorResponse();
errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
errorResponse.setType(INVALID_USER_CODE);
errorResponse.setReason("The user code is not valid.");
return errorResponse;
}
}
if (requestedExpirity != null && (requestedExpirity < 1 || requestedExpirity > appConfiguration.getCibaMaxExpirationTimeAllowedSec())) {
DefaultErrorResponse errorResponse = new DefaultErrorResponse();
errorResponse.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
errorResponse.setType(INVALID_REQUEST);
errorResponse.setReason("Requested expirity is not allowed.");
return errorResponse;
}
return null;
}
use of io.jans.as.model.error.DefaultErrorResponse in project jans by JanssenProject.
the class UmaWebException method createErrorUri.
public static URI createErrorUri(String redirectUri, ErrorResponseFactory factory, UmaErrorResponseType errorType, String state) {
try {
DefaultErrorResponse error = factory.getErrorResponse(errorType);
if (redirectUri.contains("?")) {
redirectUri += "&";
} else {
redirectUri += "?";
}
redirectUri += "error=" + error.getErrorCode();
redirectUri += "&error_description=" + URLEncoder.encode(error.getErrorDescription(), "UTF-8");
if (StringUtils.isNotBlank(error.getErrorUri())) {
redirectUri += "&error_uri=" + URLEncoder.encode(error.getErrorUri(), "UTF-8");
}
if (StringUtils.isNotBlank(state)) {
redirectUri += "&state=" + state;
}
return new URI(redirectUri);
} catch (Exception e) {
LOGGER.error("Failed to construct uri: " + redirectUri, e);
throw factory.createWebApplicationException(INTERNAL_SERVER_ERROR, UmaErrorResponseType.SERVER_ERROR, "Failed to construct uri");
}
}
Aggregations