2

I now use viewparams to filter the features by using sql views in GeoServer which is connected to our postgis-db. This means the parameter comes from the request url.

I want to use keycloak for authentication. And i wonder if its possible to set the filter by user attribute of keycloak. If it is not working with keycloak, is there some other authentification method for this requirement?

Why? Now the request may filter anything. I want to define the filter for every user. For example: UserA have the right to request buildings where city='Berlin' and UserB have the right to request buildings where city='Paris'. The datasource should be the same and also the layer in GeoServer, because i don't want to have for every city a new layer.

(As Endpoint we use wmts with vector tiles)

2
  • 1
    did you look at the authentication section of the manual?
    – Ian Turton
    Jul 17, 2019 at 13:04
  • @IanTurton, yes but i woudnt find any info about this request.
    – strech
    Jul 24, 2019 at 8:05

1 Answer 1

0

A late answer, but perhaps someone can benefit. You can implement this functionality by making changes to the getAccessLimits limits of the DefaultResourceAccessManager class (or by making your own implementation of the ResourceAccessManager interface). When using KeyCloak authentication, the user-object will contain an IdToken from which you can derive user-properties such as the 'city' of the user. This user property can be included in a CQL-constraint that limits the data access to the requested layer.

The code below illustrates this functionality:

    public DataAccessLimits getAccessLimits(
            Authentication user, LayerInfo layer, List<LayerGroupInfo> context) {
        final boolean directAccess = context == null || context.isEmpty();
        boolean read = canAccess(user, layer, AccessMode.READ, directAccess);
        boolean write = canAccess(user, layer, AccessMode.WRITE, directAccess);
        Filter readFilter = read ? Filter.INCLUDE : Filter.EXCLUDE;
        Filter writeFilter = write ? Filter.INCLUDE : Filter.EXCLUDE;

        String layerName = layer.getName();
        if (layerName.equals("yourLayerName")) {
            String userProperty = getUserProperty(user);
                try {
                    readFilter = userProperty != null
                                    ? CQL.toFilter("property = " + userProperty)
                                    : Filter.EXCLUDE;
                }
                catch (CQLException e) {
                    readFilter = Filter.EXCLUDE;
                }
            writeFilter = write ? readFilter : writeFilter;
            }
        return buildLimits(layer.getResource().getClass(), readFilter, writeFilter);
    }


    private String getProperty(Authentication user){
        try {
            SimpleKeycloakAccount account = (SimpleKeycloakAccount) user.getDetails();
            Map<String, Object> otherClaims = account.getKeycloakSecurityContext().getIdToken().getOtherClaims();
            return (String) otherClaims.get("municipality");
        }
        catch (Exception e){
            return null;
        }
    }

See also this older presentation by GeoSolutions on Advanced security with GeoServer. Ideally the GeoServer Geofence module should be extended to include such functionality.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.