use of io.gravitee.am.gateway.handler.oauth2.exception.InvalidClientException in project gravitee-access-management by gravitee-io.
the class ClientAssertionServiceImpl method validateSignatureWithPublicKey.
private Maybe<Client> validateSignatureWithPublicKey(JWT jwt) {
try {
String clientId = jwt.getJWTClaimsSet().getSubject();
SignedJWT signedJWT = (SignedJWT) jwt;
return this.clientSyncService.findByClientId(clientId).switchIfEmpty(Maybe.error(new InvalidClientException("Missing or invalid client"))).flatMap(client -> {
if (client.getTokenEndpointAuthMethod() == null || ClientAuthenticationMethod.PRIVATE_KEY_JWT.equalsIgnoreCase(client.getTokenEndpointAuthMethod())) {
return this.getClientJwkSet(client).switchIfEmpty(Maybe.error(new InvalidClientException("No jwk keys available on client"))).flatMap(jwkSet -> jwkService.getKey(jwkSet, signedJWT.getHeader().getKeyID())).switchIfEmpty(Maybe.error(new InvalidClientException("Unable to validate client, no matching key."))).flatMap(jwk -> {
if (jwsService.isValidSignature(signedJWT, jwk)) {
return Maybe.just(client);
}
return Maybe.error(new InvalidClientException("Unable to validate client, assertion signature is not valid."));
});
} else {
return Maybe.error(new InvalidClientException("Invalid client: missing or unsupported authentication method"));
}
});
} catch (ClassCastException | ParseException ex) {
LOGGER.error(ex.getMessage(), ex);
return Maybe.error(NOT_VALID);
} catch (IllegalArgumentException ex) {
return Maybe.error(new InvalidClientException(ex.getMessage()));
}
}
use of io.gravitee.am.gateway.handler.oauth2.exception.InvalidClientException in project gravitee-access-management by gravitee-io.
the class ClientAssertionServiceImpl method validateJWT.
/**
* This method will parse the JWT bearer then ensure that all requested claims are set as required
* <a href="https://tools.ietf.org/html/rfc7523#section-3">here</a>
* @param assertion jwt as string value.
* @return
*/
private Maybe<JWT> validateJWT(String assertion, String basePath) {
try {
JWT jwt = JWTParser.parse(assertion);
String iss = jwt.getJWTClaimsSet().getIssuer();
String sub = jwt.getJWTClaimsSet().getSubject();
List<String> aud = jwt.getJWTClaimsSet().getAudience();
Date exp = jwt.getJWTClaimsSet().getExpirationTime();
if (iss == null || iss.isEmpty() || sub == null || sub.isEmpty() || aud == null || aud.isEmpty() || exp == null) {
return Maybe.error(NOT_VALID);
}
if (exp.before(Date.from(Instant.now()))) {
return Maybe.error(new InvalidClientException("assertion has expired"));
}
// Check audience, here we expect to have absolute token endpoint path.
OpenIDProviderMetadata discovery = openIDDiscoveryService.getConfiguration(basePath);
if (discovery == null || discovery.getTokenEndpoint() == null) {
return Maybe.error(new ServerErrorException("Unable to retrieve discovery token endpoint."));
}
// https://tools.ietf.org/id/draft-lodderstedt-oauth-par-00.html#pushed-authorization-request-endpoint
if (aud.stream().filter(discovery.getTokenEndpoint()::equals).count() == 0 && (discovery.getIssuer() != null && aud.stream().filter(discovery.getIssuer()::equals).count() == 0) && (discovery.getParEndpoint() != null && aud.stream().filter(discovery.getParEndpoint()::equals).count() == 0)) {
return Maybe.error(NOT_VALID);
}
if (this.domain.usePlainFapiProfile() && !isSignAlgCompliantWithFapi(jwt.getHeader().getAlgorithm().getName())) {
return Maybe.error(new InvalidClientException("JWT Assertion must be signed with PS256"));
}
return Maybe.just(jwt);
} catch (ParseException pe) {
return Maybe.error(NOT_VALID);
}
}
use of io.gravitee.am.gateway.handler.oauth2.exception.InvalidClientException in project gravitee-access-management by gravitee-io.
the class RevocationTokenEndpoint method handle.
@Override
public void handle(RoutingContext context) {
// The authorization server first validates the client credentials (in
// case of a confidential client) and then verifies whether the token
// was issued to the client making the revocation request. If this
// validation fails, the request is refused and the client is informed
// of the error by the authorization server as described below.
Client client = context.get(ConstantKeys.CLIENT_CONTEXT_KEY);
if (client == null) {
throw new InvalidClientException();
}
revocationTokenService.revoke(createRequest(context), client).subscribe(() -> context.response().setStatusCode(200).end(), context::fail);
}
use of io.gravitee.am.gateway.handler.oauth2.exception.InvalidClientException in project gravitee-access-management by gravitee-io.
the class TokenEndpoint method handle.
@Override
public void handle(RoutingContext context) {
// Confidential clients or other clients issued client credentials MUST
// authenticate with the authorization server when making requests to the token endpoint.
Client client = context.get(CLIENT_CONTEXT_KEY);
if (client == null) {
throw new InvalidClientException();
}
TokenRequest tokenRequest = tokenRequestFactory.create(context);
// client_id is not required in the token request since the client can be authenticated via a Basic Authentication
if (tokenRequest.getClientId() != null) {
if (!client.getClientId().equals(tokenRequest.getClientId())) {
throw new InvalidClientException();
}
} else {
// set token request client_id with the authenticated client
tokenRequest.setClientId(client.getClientId());
}
// check if client has authorized grant types
if (client.getAuthorizedGrantTypes() == null || client.getAuthorizedGrantTypes().isEmpty()) {
throw new InvalidClientException("Invalid client: client must at least have one grant type configured");
}
if (context.get(ConstantKeys.PEER_CERTIFICATE_THUMBPRINT) != null) {
// preserve certificate thumbprint to add the information into the access token
tokenRequest.setConfirmationMethodX5S256(context.get(ConstantKeys.PEER_CERTIFICATE_THUMBPRINT));
}
tokenGranter.grant(tokenRequest, client).subscribe(accessToken -> context.response().putHeader(HttpHeaders.CACHE_CONTROL, "no-store").putHeader(HttpHeaders.PRAGMA, "no-cache").putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON).end(Json.encodePrettily(accessToken)), context::fail);
}
use of io.gravitee.am.gateway.handler.oauth2.exception.InvalidClientException in project gravitee-access-management by gravitee-io.
the class ClientBasicAuthProviderTest method shouldNotAuthenticateClient_badClientSecret.
@Test
public void shouldNotAuthenticateClient_badClientSecret() throws Exception {
Client client = mock(Client.class);
when(client.getClientId()).thenReturn("my-client-id");
when(client.getClientSecret()).thenReturn("my-client-secret");
HttpServerRequest httpServerRequest = mock(HttpServerRequest.class);
HeadersMultiMap vertxHttpHeaders = new HeadersMultiMap();
vertxHttpHeaders.add(HttpHeaders.AUTHORIZATION, "Basic bXktY2xpZW50LWlkOm15LW90aGVyLWNsaWVudC1zZWNyZXQ=");
when(httpServerRequest.headers()).thenReturn(MultiMap.newInstance(vertxHttpHeaders));
RoutingContext context = mock(RoutingContext.class);
when(context.request()).thenReturn(httpServerRequest);
CountDownLatch latch = new CountDownLatch(1);
authProvider.handle(client, context, userAsyncResult -> {
latch.countDown();
Assert.assertNotNull(userAsyncResult);
Assert.assertTrue(userAsyncResult.failed());
Assert.assertTrue(userAsyncResult.cause() instanceof InvalidClientException);
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
}
Aggregations