Search in sources :

Example 1 with ApiTokenRealm

use of com.bakdata.conquery.models.auth.apitoken.ApiTokenRealm in project conquery by bakdata.

the class ApiTokenRealmFactory method createRealm.

@Override
public ConqueryAuthenticationRealm createRealm(ManagerNode managerNode) {
    final TokenStorage tokenStorage = new TokenStorage(storeDir, apiTokenStoreConfig, managerNode.getValidator(), Jackson.BINARY_MAPPER.copy());
    managerNode.getEnvironment().lifecycle().manage(tokenStorage);
    final ApiTokenRealm apiTokenRealm = new ApiTokenRealm(managerNode.getStorage(), tokenStorage);
    managerNode.getAuthController().getAuthenticationFilter().registerTokenExtractor(new ApiTokenExtractor());
    JerseyEnvironment environment = managerNode.getEnvironment().jersey();
    environment.register(new AbstractBinder() {

        @Override
        protected void configure() {
            bind(apiTokenRealm).to(ApiTokenRealm.class);
        }
    });
    environment.register(ApiTokenResource.class);
    return apiTokenRealm;
}
Also used : JerseyEnvironment(io.dropwizard.jersey.setup.JerseyEnvironment) AbstractBinder(org.glassfish.hk2.utilities.binding.AbstractBinder) ApiTokenRealm(com.bakdata.conquery.models.auth.apitoken.ApiTokenRealm) TokenStorage(com.bakdata.conquery.models.auth.apitoken.TokenStorage)

Example 2 with ApiTokenRealm

use of com.bakdata.conquery.models.auth.apitoken.ApiTokenRealm in project conquery by bakdata.

the class ApiTokenRealmTest method execute.

@Override
public void execute(StandaloneSupport conquery) throws Exception {
    final User testUser = conquery.getTestUser();
    final ApiTokenRealm realm = conquery.getAuthorizationController().getAuthenticationRealms().stream().filter(ApiTokenRealm.class::isInstance).map(ApiTokenRealm.class::cast).collect(MoreCollectors.onlyElement());
    final ConqueryTokenRealm conqueryTokenRealm = conquery.getAuthorizationController().getConqueryTokenRealm();
    final String userToken = conqueryTokenRealm.createTokenForUser(testUser.getId());
    // Request ApiToken
    final ApiTokenDataRepresentation.Request tokenRequest1 = new ApiTokenDataRepresentation.Request();
    tokenRequest1.setName("test-token");
    tokenRequest1.setScopes(EnumSet.of(Scopes.DATASET));
    tokenRequest1.setExpirationDate(LocalDate.now().plus(1, ChronoUnit.DAYS));
    ApiToken apiToken1 = requestApiToken(conquery, userToken, tokenRequest1);
    assertThat(apiToken1.getToken()).isNotBlank();
    // List ApiToken
    List<ApiTokenDataRepresentation.Response> apiTokens = conquery.getClient().target(HierarchyHelper.hierarchicalPath(conquery.defaultApiURIBuilder(), ApiTokenResource.class, "listUserTokens")).request(MediaType.APPLICATION_JSON_TYPE).header("Authorization", "Bearer " + userToken).get(new GenericType<List<ApiTokenDataRepresentation.Response>>() {
    });
    final ApiTokenDataRepresentation.Response expected = new ApiTokenDataRepresentation.Response();
    expected.setLastUsed(null);
    expected.setCreationDate(LocalDate.now());
    expected.setExpirationDate(LocalDate.now().plus(1, ChronoUnit.DAYS));
    expected.setScopes(EnumSet.of(Scopes.DATASET));
    expected.setName("test-token");
    assertThat(apiTokens).hasSize(1);
    assertThat(apiTokens.get(0)).usingRecursiveComparison().ignoringFields("id").isEqualTo(expected);
    // Request ApiToken 2
    final ApiTokenDataRepresentation.Request tokenRequest2 = new ApiTokenDataRepresentation.Request();
    tokenRequest2.setName("test-token");
    tokenRequest2.setScopes(EnumSet.of(Scopes.ADMIN));
    tokenRequest2.setExpirationDate(LocalDate.now().plus(1, ChronoUnit.DAYS));
    ApiToken apiToken2 = requestApiToken(conquery, userToken, tokenRequest2);
    assertThat(apiToken2.getToken()).isNotBlank();
    // List ApiToken 2
    apiTokens = requestTokenList(conquery, userToken);
    assertThat(apiTokens).hasSize(2);
    // Use ApiToken1 to get Datasets
    List<IdLabel<DatasetId>> datasets = requestDatasets(conquery, apiToken1);
    assertThat(datasets).isNotEmpty();
    // Use ApiToken2 to get Datasets
    datasets = requestDatasets(conquery, apiToken2);
    assertThat(datasets).as("The second token has no scope for dataset").isEmpty();
    // Use ApiToken2 to access Admin
    List<DatasetId> adminDatasets = conquery.getClient().target(HierarchyHelper.hierarchicalPath(conquery.defaultAdminURIBuilder(), AdminDatasetsResource.class, "listDatasets")).request(MediaType.APPLICATION_JSON_TYPE).header("Authorization", "Bearer " + apiToken2.getToken()).get(new GenericType<>() {
    });
    assertThat(adminDatasets).as("The second token has scope for admin").isNotEmpty();
    // Try to delete ApiToken2 with ApiToken (should fail)
    final UUID id2 = apiTokens.stream().filter(t -> t.getScopes().contains(Scopes.ADMIN)).map(ApiTokenDataRepresentation.Response::getId).collect(MoreCollectors.onlyElement());
    Response response = conquery.getClient().target(HierarchyHelper.hierarchicalPath(conquery.defaultApiURIBuilder(), ApiTokenResource.class, "deleteToken")).resolveTemplate(ApiTokenResource.TOKEN, id2).request(MediaType.APPLICATION_JSON_TYPE).header("Authorization", "Bearer " + apiToken2.getToken()).delete(Response.class);
    assertThat(response.getStatus()).as("It is forbidden to act on ApiTokens with ApiTokens").isEqualTo(403);
    // Delete ApiToken2 with user token
    response = conquery.getClient().target(HierarchyHelper.hierarchicalPath(conquery.defaultApiURIBuilder(), ApiTokenResource.class, "deleteToken")).resolveTemplate(ApiTokenResource.TOKEN, id2).request(MediaType.APPLICATION_JSON_TYPE).header("Authorization", "Bearer " + userToken).delete(Response.class);
    assertThat(response.getStatus()).as("It is okay to act on ApiTokens with UserTokens").isEqualTo(200);
    assertThat(realm.listUserToken(testUser)).hasSize(1);
    // Try to use the deleted token to access Admin
    response = conquery.getClient().target(HierarchyHelper.hierarchicalPath(conquery.defaultAdminURIBuilder(), AdminDatasetsResource.class, "listDatasets")).request(MediaType.APPLICATION_JSON_TYPE).header("Authorization", "Bearer " + apiToken2.getToken()).get(Response.class);
    assertThat(response.getStatus()).as("Cannot use deleted token").isEqualTo(401);
    // Try to act on tokens from another user
    final MetaStorage metaStorage = conquery.getMetaStorage();
    final User user2 = new User("TestUser2", "TestUser2", metaStorage);
    metaStorage.addUser(user2);
    final String user2Token = conqueryTokenRealm.createTokenForUser(user2.getId());
    // Try to delete ApiToken2 with ApiToken (should fail)
    final UUID id1 = apiTokens.stream().filter(t -> t.getScopes().contains(Scopes.DATASET)).map(ApiTokenDataRepresentation.Response::getId).collect(MoreCollectors.onlyElement());
    response = conquery.getClient().target(HierarchyHelper.hierarchicalPath(conquery.defaultApiURIBuilder(), ApiTokenResource.class, "deleteToken")).resolveTemplate(ApiTokenResource.TOKEN, id1).request(MediaType.APPLICATION_JSON_TYPE).header("Authorization", "Bearer " + user2Token).delete(Response.class);
    assertThat(response.getStatus()).as("It is forbidden to act on someone else ApiTokens").isEqualTo(403);
    // Request ApiToken 3 (expired)
    final ApiTokenDataRepresentation.Request tokenRequest3 = new ApiTokenDataRepresentation.Request();
    tokenRequest3.setName("test-token");
    tokenRequest3.setScopes(EnumSet.of(Scopes.DATASET));
    tokenRequest3.setExpirationDate(LocalDate.now().minus(1, ChronoUnit.DAYS));
    assertThatThrownBy(() -> requestApiToken(conquery, userToken, tokenRequest3)).as("Expiration date is in the past").isExactlyInstanceOf(ClientErrorException.class).hasMessageContaining("HTTP 422");
    // Craft expired token behind validation to simulate the use of an expired token
    ApiToken apiToken3 = realm.createApiToken(user2, tokenRequest3);
    assertThatThrownBy(() -> requestDatasets(conquery, apiToken3)).as("Expired token").isExactlyInstanceOf(NotAuthorizedException.class);
}
Also used : User(com.bakdata.conquery.models.auth.entities.User) ConqueryTokenRealm(com.bakdata.conquery.models.auth.conquerytoken.ConqueryTokenRealm) ApiTokenDataRepresentation(com.bakdata.conquery.apiv1.auth.ApiTokenDataRepresentation) DatasetId(com.bakdata.conquery.models.identifiable.ids.specific.DatasetId) ApiTokenResource(com.bakdata.conquery.resources.api.ApiTokenResource) Response(javax.ws.rs.core.Response) IdLabel(com.bakdata.conquery.apiv1.IdLabel) MetaStorage(com.bakdata.conquery.io.storage.MetaStorage) ApiToken(com.bakdata.conquery.models.auth.apitoken.ApiToken) ClientErrorException(javax.ws.rs.ClientErrorException) ApiTokenRealm(com.bakdata.conquery.models.auth.apitoken.ApiTokenRealm) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) UUID(java.util.UUID) AdminDatasetsResource(com.bakdata.conquery.resources.admin.rest.AdminDatasetsResource)

Aggregations

ApiTokenRealm (com.bakdata.conquery.models.auth.apitoken.ApiTokenRealm)2 IdLabel (com.bakdata.conquery.apiv1.IdLabel)1 ApiTokenDataRepresentation (com.bakdata.conquery.apiv1.auth.ApiTokenDataRepresentation)1 MetaStorage (com.bakdata.conquery.io.storage.MetaStorage)1 ApiToken (com.bakdata.conquery.models.auth.apitoken.ApiToken)1 TokenStorage (com.bakdata.conquery.models.auth.apitoken.TokenStorage)1 ConqueryTokenRealm (com.bakdata.conquery.models.auth.conquerytoken.ConqueryTokenRealm)1 User (com.bakdata.conquery.models.auth.entities.User)1 DatasetId (com.bakdata.conquery.models.identifiable.ids.specific.DatasetId)1 AdminDatasetsResource (com.bakdata.conquery.resources.admin.rest.AdminDatasetsResource)1 ApiTokenResource (com.bakdata.conquery.resources.api.ApiTokenResource)1 ImmutableList (com.google.common.collect.ImmutableList)1 JerseyEnvironment (io.dropwizard.jersey.setup.JerseyEnvironment)1 List (java.util.List)1 UUID (java.util.UUID)1 ClientErrorException (javax.ws.rs.ClientErrorException)1 Response (javax.ws.rs.core.Response)1 AbstractBinder (org.glassfish.hk2.utilities.binding.AbstractBinder)1