use of io.jans.as.model.crypto.signature.SignatureAlgorithm in project jans by JanssenProject.
the class AuthCryptoProvider method getSignatureAlgorithm.
public SignatureAlgorithm getSignatureAlgorithm(String alias) throws KeyStoreException {
Certificate[] chain = keyStore.getCertificateChain(alias);
if ((chain == null) || chain.length == 0) {
return null;
}
X509Certificate cert = (X509Certificate) chain[0];
String sighAlgName = cert.getSigAlgName();
for (SignatureAlgorithm sa : SignatureAlgorithm.values()) {
if (sighAlgName.equalsIgnoreCase(sa.getAlgorithm())) {
return sa;
}
}
return null;
}
use of io.jans.as.model.crypto.signature.SignatureAlgorithm in project jans by JanssenProject.
the class AuthCryptoProvider method getJson.
private JSONObject getJson(final Algorithm algorithm, final KeyPairGenerator keyGen, final String signatureAlgorithmStr, final Long expirationTime) throws NoSuchAlgorithmException, OperatorCreationException, CertificateException, KeyStoreException, IOException {
// Generate the key
KeyPair keyPair = keyGen.generateKeyPair();
PrivateKey pk = keyPair.getPrivate();
// Java API requires a certificate chain
X509Certificate cert = generateV3Certificate(keyPair, dnName, signatureAlgorithmStr, expirationTime);
X509Certificate[] chain = new X509Certificate[1];
chain[0] = cert;
String alias = UUID.randomUUID().toString() + getKidSuffix(algorithm.getUse(), algorithm);
keyStore.setKeyEntry(alias, pk, keyStoreSecret.toCharArray(), chain);
final String oldAliasByAlgorithm = getAliasByAlgorithmForDeletion(algorithm, alias);
if (StringUtils.isNotBlank(oldAliasByAlgorithm)) {
keyStore.deleteEntry(oldAliasByAlgorithm);
LOG.trace("New key: " + alias + ", deleted key: " + oldAliasByAlgorithm);
}
try (FileOutputStream stream = new FileOutputStream(keyStoreFile)) {
keyStore.store(stream, keyStoreSecret.toCharArray());
}
final PublicKey publicKey = keyPair.getPublic();
Use use = algorithm.getUse();
JSONObject jsonObject = new JSONObject();
jsonObject.put(JWKParameter.KEY_TYPE, algorithm.getFamily());
jsonObject.put(JWKParameter.KEY_ID, alias);
jsonObject.put(JWKParameter.KEY_USE, algorithm.getUse().getParamName());
jsonObject.put(JWKParameter.ALGORITHM, algorithm.getParamName());
jsonObject.put(JWKParameter.EXPIRATION_TIME, expirationTime);
if (publicKey instanceof RSAPublicKey) {
RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey;
jsonObject.put(JWKParameter.MODULUS, Base64Util.base64urlencodeUnsignedBigInt(rsaPublicKey.getModulus()));
jsonObject.put(JWKParameter.EXPONENT, Base64Util.base64urlencodeUnsignedBigInt(rsaPublicKey.getPublicExponent()));
} else if (publicKey instanceof ECPublicKey) {
ECPublicKey ecPublicKey = (ECPublicKey) publicKey;
if (use == Use.SIGNATURE) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.fromString(algorithm.getParamName());
jsonObject.put(JWKParameter.CURVE, signatureAlgorithm.getCurve().getName());
} else if (use == Use.ENCRYPTION) {
KeyEncryptionAlgorithm keyEncryptionAlgorithm = KeyEncryptionAlgorithm.fromName(algorithm.getParamName());
jsonObject.put(JWKParameter.CURVE, keyEncryptionAlgorithm.getCurve().getName());
}
jsonObject.put(JWKParameter.X, Base64Util.base64urlencodeUnsignedBigInt(ecPublicKey.getW().getAffineX()));
jsonObject.put(JWKParameter.Y, Base64Util.base64urlencodeUnsignedBigInt(ecPublicKey.getW().getAffineY()));
} else if (use == Use.SIGNATURE && publicKey instanceof EdDSAPublicKey) {
EdDSAPublicKey edDSAPublicKey = (EdDSAPublicKey) publicKey;
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.fromString(algorithm.getParamName());
jsonObject.put(JWKParameter.CURVE, signatureAlgorithm.getCurve().getName());
jsonObject.put(JWKParameter.X, Base64Util.base64urlencode(edDSAPublicKey.getEncoded()));
// EdDSA keys (EdDSAPublicKey, EDDSAPrivateKey) don't use BigInteger, but only byte[],
// so Base64Util.base64urlencode, but not Base64Util.base64urlencodeUnsignedBigInt is used.
}
JSONArray x5c = new JSONArray();
x5c.put(Base64.encodeBase64String(cert.getEncoded()));
jsonObject.put(JWKParameter.CERTIFICATE_CHAIN, x5c);
return jsonObject;
}
use of io.jans.as.model.crypto.signature.SignatureAlgorithm 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.crypto.signature.SignatureAlgorithm in project jans by JanssenProject.
the class AuthorizeRestWebServiceValidator method validateRequestObject.
public void validateRequestObject(JwtAuthorizationRequest jwtRequest, RedirectUriResponse redirectUriResponse) {
if (!jwtRequest.getAud().isEmpty() && !jwtRequest.getAud().contains(appConfiguration.getIssuer())) {
log.error("Failed to match aud to AS, aud: {}", jwtRequest.getAud());
throw redirectUriResponse.createWebException(AuthorizeErrorResponseType.INVALID_REQUEST_OBJECT);
}
if (!appConfiguration.isFapi()) {
return;
}
// FAPI related validation
if (jwtRequest.getNestedJwt() != null) {
SignatureAlgorithm nestedJwtSigAlg = jwtRequest.getNestedJwt().getHeader().getSignatureAlgorithm();
if (appConfiguration.isFapi() && (nestedJwtSigAlg == RS256 || nestedJwtSigAlg == NONE)) {
log.error("The Nested JWT signature algorithm is not valid.");
throw redirectUriResponse.createWebException(AuthorizeErrorResponseType.INVALID_REQUEST_OBJECT);
}
}
String redirectUri = jwtRequest.getRedirectUri();
Client client = clientService.getClient(jwtRequest.getClientId());
if (redirectUri != null && redirectionUriService.validateRedirectionUri(client, redirectUri) == null) {
log.error(" unregistered redirect uri");
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).entity(errorResponseFactory.getErrorAsJson(AuthorizeErrorResponseType.INVALID_REQUEST_OBJECT, jwtRequest.getState(), "The request has unregistered request_uri")).type(MediaType.APPLICATION_JSON_TYPE).build());
}
if (jwtRequest.getExp() == null) {
log.error("The exp claim is not set");
throw redirectUriResponse.createWebException(AuthorizeErrorResponseType.INVALID_REQUEST_OBJECT);
}
final long expInMillis = jwtRequest.getExp() * 1000L;
final long now = new Date().getTime();
if (expInMillis < now) {
log.error("Request object expired. Exp: {}, now: {}", expInMillis, now);
throw redirectUriResponse.createWebException(AuthorizeErrorResponseType.INVALID_REQUEST_OBJECT);
}
if (jwtRequest.getScopes() == null || jwtRequest.getScopes().isEmpty()) {
log.error("Request object does not have scope claim.");
throw redirectUriResponse.createWebException(AuthorizeErrorResponseType.INVALID_REQUEST_OBJECT);
}
if (StringUtils.isBlank(jwtRequest.getNonce())) {
log.error("Request object does not have nonce claim.");
throw redirectUriResponse.createWebException(AuthorizeErrorResponseType.INVALID_REQUEST_OBJECT);
}
if (StringUtils.isBlank(jwtRequest.getRedirectUri())) {
log.error("Request object does not have redirect_uri claim.");
if (redirectUriResponse.getRedirectUri().getBaseRedirectUri() != null) {
throw redirectUriResponse.createWebException(AuthorizeErrorResponseType.INVALID_REQUEST_OBJECT);
} else {
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).entity(errorResponseFactory.getErrorAsJson(AuthorizeErrorResponseType.INVALID_REQUEST_OBJECT, jwtRequest.getState(), "Request object does not have redirect_uri claim.")).type(MediaType.APPLICATION_JSON_TYPE).build());
}
}
}
use of io.jans.as.model.crypto.signature.SignatureAlgorithm in project jans by JanssenProject.
the class BaseOAuthProtectionService method processAuthorization.
@Override
public Response processAuthorization(HttpHeaders headers, ResourceInfo resourceInfo) {
try {
String token = headers.getHeaderString(HttpHeaders.AUTHORIZATION);
boolean authFound = StringUtils.isNotEmpty(token);
log.info("Authorization header {} found", authFound ? "" : "not");
if (!authFound) {
log.info("Request is missing authorization header");
// see section 3.12 RFC 7644
return IProtectionService.simpleResponse(UNAUTHORIZED, "No authorization header found");
}
token = token.replaceFirst("Bearer\\s+", "");
log.debug("Validating token {}", token);
List<String> scopes = getRequestedScopes(resourceInfo);
log.info("Call requires scopes: {}", scopes);
Jwt jwt = tokenAsJwt(token);
if (jwt == null) {
// Do standard token validation
IntrospectionResponse iresp = null;
try {
iresp = introspectionService.introspectToken("Bearer " + token, token);
} catch (Exception e) {
log.error(e.getMessage());
}
return processIntrospectionResponse(iresp, scopes);
}
// Process the JWT: validate isuer, expiration and signature
JwtClaims claims = jwt.getClaims();
if (!oidcConfig.getIssuer().equals(claims.getClaimAsString(JwtClaimName.ISSUER)))
return IProtectionService.simpleResponse(FORBIDDEN, "Invalid token issuer");
int exp = Optional.ofNullable(claims.getClaimAsInteger(JwtClaimName.EXPIRATION_TIME)).orElse(0);
if (1000L * exp < System.currentTimeMillis())
return IProtectionService.simpleResponse(FORBIDDEN, "Expired token");
Map jwks = mapper.readValue(new URL(oidcConfig.getJwksUri()), Map.class);
// tokenScopes is never null
List<String> tokenScopes = claims.getClaimAsStringList("scope");
AuthCryptoProvider cryptoProvider = new AuthCryptoProvider(null, null, null, true);
SignatureAlgorithm signatureAlg = jwt.getHeader().getSignatureAlgorithm();
if (AlgorithmFamily.HMAC.equals(signatureAlg.getFamily())) {
// It is "expensive" to get the associated client secret
return IProtectionService.simpleResponse(INTERNAL_SERVER_ERROR, "HMAC algorithm not allowed for token signature. Please use an algorithm in the EC, ED, or RSA family for signing");
}
boolean valid = cryptoProvider.verifySignature(jwt.getSigningInput(), jwt.getEncodedSignature(), jwt.getHeader().getKeyId(), new JSONObject(jwks), null, signatureAlg);
if (valid && tokenScopes.containsAll(scopes))
return null;
String msg = "Invalid token signature or insufficient scopes";
log.error("{}. Token scopes: {}", msg, tokenScopes);
// see section 3.12 RFC 7644
return IProtectionService.simpleResponse(FORBIDDEN, msg);
} catch (Exception e) {
log.error(e.getMessage(), e);
return IProtectionService.simpleResponse(INTERNAL_SERVER_ERROR, e.getMessage());
}
}
Aggregations