org.mitre.uma.service.impl.UmaDataServiceExtension_1_3.java Source code

Java tutorial

Introduction

Here is the source code for org.mitre.uma.service.impl.UmaDataServiceExtension_1_3.java

Source

/*******************************************************************************
 * Copyright 2018 The MIT Internet Trust Consortium
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/

package org.mitre.uma.service.impl;

import static org.mitre.util.JsonUtils.readSet;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.oauth2.repository.OAuth2TokenRepository;
import org.mitre.openid.connect.ClientDetailsEntityJsonProcessor;
import org.mitre.openid.connect.service.MITREidDataService;
import org.mitre.openid.connect.service.MITREidDataServiceExtension;
import org.mitre.openid.connect.service.MITREidDataServiceMaps;
import org.mitre.openid.connect.service.impl.MITREidDataServiceSupport;
import org.mitre.uma.model.Claim;
import org.mitre.uma.model.Permission;
import org.mitre.uma.model.PermissionTicket;
import org.mitre.uma.model.Policy;
import org.mitre.uma.model.ResourceSet;
import org.mitre.uma.model.SavedRegisteredClient;
import org.mitre.uma.repository.PermissionRepository;
import org.mitre.uma.repository.ResourceSetRepository;
import org.mitre.uma.service.SavedRegisteredClientService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

/**
 * @author jricher
 *
 */
@Service("umaDataExtension_1_3")
public class UmaDataServiceExtension_1_3 extends MITREidDataServiceSupport implements MITREidDataServiceExtension {

    private static final String THIS_VERSION = MITREidDataService.MITREID_CONNECT_1_3;

    private static final String REGISTERED_CLIENT = "registeredClient";
    private static final String URI = "uri";
    private static final String NAME = "name";
    private static final String TYPE = "type";
    private static final String VALUE = "value";
    private static final String CLIENT_ID = "clientId";
    private static final String EXPIRATION = "expiration";
    private static final String ID = "id";
    private static final String ICON_URI = "iconUri";
    private static final String OWNER = "owner";
    private static final String POLICIES = "policies";
    private static final String SCOPES = "scopes";
    private static final String CLAIMS_REQUIRED = "claimsRequired";
    private static final String ISSUER = "issuer";
    private static final String CLAIM_TOKEN_FORMAT = "claimTokenFormat";
    private static final String CLAIM_TYPE = "claimType";
    private static final String FRIENDLY_NAME = "friendlyName";
    private static final String PERMISSIONS = "permissions";
    private static final String RESOURCE_SET = "resourceSet";
    private static final String PERMISSION_TICKETS = "permissionTickets";
    private static final String PERMISSION = "permission";
    private static final String TICKET = "ticket";
    private static final String CLAIMS_SUPPLIED = "claimsSupplied";
    private static final String SAVED_REGISTERED_CLIENTS = "savedRegisteredClients";
    private static final String RESOURCE_SETS = "resourceSets";
    private static final String TOKEN_PERMISSIONS = "tokenPermissions";
    private static final String TOKEN_ID = "tokenId";

    private static final Logger logger = LoggerFactory.getLogger(UmaDataServiceExtension_1_3.class);

    @Autowired
    private SavedRegisteredClientService registeredClientService;
    @Autowired
    private ResourceSetRepository resourceSetRepository;
    @Autowired
    private PermissionRepository permissionRepository;
    @Autowired
    private OAuth2TokenRepository tokenRepository;

    private Map<Long, Set<Long>> tokenToPermissionRefs = new HashMap<>();

    /* (non-Javadoc)
     * @see org.mitre.openid.connect.service.MITREidDataServiceExtension#supportsVersion(java.lang.String)
     */
    @Override
    public boolean supportsVersion(String version) {
        return THIS_VERSION.equals(version);

    }

    /* (non-Javadoc)
     * @see org.mitre.openid.connect.service.MITREidDataServiceExtension#exportExtensionData(com.google.gson.stream.JsonWriter)
     */
    @Override
    public void exportExtensionData(JsonWriter writer) throws IOException {
        writer.name(SAVED_REGISTERED_CLIENTS);
        writer.beginArray();
        writeSavedRegisteredClients(writer);
        writer.endArray();

        writer.name(RESOURCE_SETS);
        writer.beginArray();
        writeResourceSets(writer);
        writer.endArray();

        writer.name(PERMISSION_TICKETS);
        writer.beginArray();
        writePermissionTickets(writer);
        writer.endArray();

        writer.name(TOKEN_PERMISSIONS);
        writer.beginArray();
        writeTokenPermissions(writer);
        writer.endArray();
    }

    /**
     * @param writer
     * @throws IOException
     */
    private void writeTokenPermissions(JsonWriter writer) throws IOException {
        for (OAuth2AccessTokenEntity token : tokenRepository.getAllAccessTokens()) {
            if (!token.getPermissions().isEmpty()) { // skip tokens that don't have the permissions structure attached
                writer.beginObject();
                writer.name(TOKEN_ID).value(token.getId());
                writer.name(PERMISSIONS);
                writer.beginArray();
                for (Permission p : token.getPermissions()) {
                    writer.beginObject();
                    writer.name(RESOURCE_SET).value(p.getResourceSet().getId());
                    writer.name(SCOPES);
                    writer.beginArray();
                    for (String s : p.getScopes()) {
                        writer.value(s);
                    }
                    writer.endArray();
                    writer.endObject();
                }
                writer.endArray();

                writer.endObject();
            }
        }
    }

    /**
     * @param writer
     * @throws IOException
     */
    private void writePermissionTickets(JsonWriter writer) throws IOException {
        for (PermissionTicket ticket : permissionRepository.getAll()) {
            writer.beginObject();

            writer.name(CLAIMS_SUPPLIED);
            writer.beginArray();
            for (Claim claim : ticket.getClaimsSupplied()) {
                writer.beginObject();

                writer.name(ISSUER);
                writer.beginArray();
                for (String issuer : claim.getIssuer()) {
                    writer.value(issuer);
                }
                writer.endArray();
                writer.name(CLAIM_TOKEN_FORMAT);
                writer.beginArray();
                for (String format : claim.getClaimTokenFormat()) {
                    writer.value(format);
                }
                writer.endArray();
                writer.name(CLAIM_TYPE).value(claim.getClaimType());
                writer.name(FRIENDLY_NAME).value(claim.getFriendlyName());
                writer.name(NAME).value(claim.getName());
                writer.name(VALUE).value(claim.getValue().toString());
                writer.endObject();
            }
            writer.endArray();

            writer.name(EXPIRATION).value(toUTCString(ticket.getExpiration()));

            writer.name(PERMISSION);
            writer.beginObject();
            Permission p = ticket.getPermission();
            writer.name(RESOURCE_SET).value(p.getResourceSet().getId());
            writer.name(SCOPES);
            writer.beginArray();
            for (String s : p.getScopes()) {
                writer.value(s);
            }
            writer.endArray();
            writer.endObject();

            writer.name(TICKET).value(ticket.getTicket());

            writer.endObject();
        }

    }

    /**
     * @param writer
     * @throws IOException
     */
    private void writeResourceSets(JsonWriter writer) throws IOException {
        for (ResourceSet rs : resourceSetRepository.getAll()) {
            writer.beginObject();
            writer.name(ID).value(rs.getId());
            writer.name(CLIENT_ID).value(rs.getClientId());
            writer.name(ICON_URI).value(rs.getIconUri());
            writer.name(NAME).value(rs.getName());
            writer.name(TYPE).value(rs.getType());
            writer.name(URI).value(rs.getUri());
            writer.name(OWNER).value(rs.getOwner());
            writer.name(POLICIES);
            writer.beginArray();
            for (Policy policy : rs.getPolicies()) {
                writer.beginObject();
                writer.name(NAME).value(policy.getName());
                writer.name(SCOPES);
                writer.beginArray();
                for (String scope : policy.getScopes()) {
                    writer.value(scope);
                }
                writer.endArray();
                writer.name(CLAIMS_REQUIRED);
                writer.beginArray();
                for (Claim claim : policy.getClaimsRequired()) {
                    writer.beginObject();

                    writer.name(ISSUER);
                    writer.beginArray();
                    for (String issuer : claim.getIssuer()) {
                        writer.value(issuer);
                    }
                    writer.endArray();
                    writer.name(CLAIM_TOKEN_FORMAT);
                    writer.beginArray();
                    for (String format : claim.getClaimTokenFormat()) {
                        writer.value(format);
                    }
                    writer.endArray();
                    writer.name(CLAIM_TYPE).value(claim.getClaimType());
                    writer.name(FRIENDLY_NAME).value(claim.getFriendlyName());
                    writer.name(NAME).value(claim.getName());
                    writer.name(VALUE).value(claim.getValue().toString());
                    writer.endObject();
                }
                writer.endArray();
                writer.endObject();
            }
            writer.endArray();
            writer.name(SCOPES);
            writer.beginArray();
            for (String scope : rs.getScopes()) {
                writer.value(scope);
            }
            writer.endArray();
            writer.endObject();
            logger.debug("Finished writing resource set {}", rs.getId());
        }

    }

    /**
     * @param writer
     */
    private void writeSavedRegisteredClients(JsonWriter writer) throws IOException {
        for (SavedRegisteredClient src : registeredClientService.getAll()) {
            writer.beginObject();
            writer.name(ISSUER).value(src.getIssuer());
            writer.name(REGISTERED_CLIENT).value(src.getRegisteredClient().getSource().toString());
            writer.endObject();
            logger.debug("Wrote saved registered client {}", src.getId());
        }
        logger.info("Done writing saved registered clients");
    }

    /* (non-Javadoc)
     * @see org.mitre.openid.connect.service.MITREidDataServiceExtension#importExtensionData(com.google.gson.stream.JsonReader)
     */
    @Override
    public boolean importExtensionData(String name, JsonReader reader) throws IOException {
        if (name.equals(SAVED_REGISTERED_CLIENTS)) {
            readSavedRegisteredClients(reader);
            return true;
        } else if (name.equals(RESOURCE_SETS)) {
            readResourceSets(reader);
            return true;
        } else if (name.equals(PERMISSION_TICKETS)) {
            readPermissionTickets(reader);
            return true;
        } else if (name.equals(TOKEN_PERMISSIONS)) {
            readTokenPermissions(reader);
            return true;
        } else {
            return false;
        }
    }

    /**
     * @param reader
     */
    private void readTokenPermissions(JsonReader reader) throws IOException {
        reader.beginArray();
        while (reader.hasNext()) {
            reader.beginObject();
            Long tokenId = null;
            Set<Long> permissions = new HashSet<>();
            while (reader.hasNext()) {
                switch (reader.peek()) {
                case END_OBJECT:
                    continue;
                case NAME:
                    String name = reader.nextName();
                    if (name.equals(TOKEN_ID)) {
                        tokenId = reader.nextLong();
                    } else if (name.equals(PERMISSIONS)) {
                        reader.beginArray();
                        while (reader.hasNext()) {
                            Permission p = new Permission();
                            Long rsid = null;
                            Set<String> scope = new HashSet<>();
                            reader.beginObject();
                            while (reader.hasNext()) {
                                switch (reader.peek()) {
                                case END_OBJECT:
                                    continue;
                                case NAME:
                                    String pname = reader.nextName();
                                    if (reader.peek() == JsonToken.NULL) {
                                        reader.skipValue();
                                    } else if (pname.equals(RESOURCE_SET)) {
                                        rsid = reader.nextLong();
                                    } else if (pname.equals(SCOPES)) {
                                        scope = readSet(reader);
                                    } else {
                                        logger.debug("Found unexpected entry");
                                        reader.skipValue();
                                    }
                                    break;
                                default:
                                    logger.debug("Found unexpected entry");
                                    reader.skipValue();
                                    continue;
                                }
                            }
                            reader.endObject();
                            p.setScopes(scope);
                            Permission saved = permissionRepository.saveRawPermission(p);
                            permissionToResourceRefs.put(saved.getId(), rsid);
                            permissions.add(saved.getId());
                        }
                        reader.endArray();
                    }
                    break;
                default:
                    logger.debug("Found unexpected entry");
                    reader.skipValue();
                    continue;
                }
            }
            reader.endObject();
            tokenToPermissionRefs.put(tokenId, permissions);
        }
        reader.endArray();

    }

    private Map<Long, Long> permissionToResourceRefs = new HashMap<>();

    /**
     * @param reader
     */
    private void readPermissionTickets(JsonReader reader) throws IOException {
        JsonParser parser = new JsonParser();
        reader.beginArray();
        while (reader.hasNext()) {
            PermissionTicket ticket = new PermissionTicket();
            reader.beginObject();
            while (reader.hasNext()) {
                switch (reader.peek()) {
                case END_OBJECT:
                    continue;
                case NAME:
                    String name = reader.nextName();
                    if (reader.peek() == JsonToken.NULL) {
                        reader.skipValue();
                    } else if (name.equals(CLAIMS_SUPPLIED)) {
                        Set<Claim> claimsSupplied = new HashSet<>();
                        reader.beginArray();
                        while (reader.hasNext()) {
                            Claim c = new Claim();
                            reader.beginObject();
                            while (reader.hasNext()) {
                                switch (reader.peek()) {
                                case END_OBJECT:
                                    continue;
                                case NAME:
                                    String cname = reader.nextName();
                                    if (reader.peek() == JsonToken.NULL) {
                                        reader.skipValue();
                                    } else if (cname.equals(ISSUER)) {
                                        c.setIssuer(readSet(reader));
                                    } else if (cname.equals(CLAIM_TOKEN_FORMAT)) {
                                        c.setClaimTokenFormat(readSet(reader));
                                    } else if (cname.equals(CLAIM_TYPE)) {
                                        c.setClaimType(reader.nextString());
                                    } else if (cname.equals(FRIENDLY_NAME)) {
                                        c.setFriendlyName(reader.nextString());
                                    } else if (cname.equals(NAME)) {
                                        c.setName(reader.nextString());
                                    } else if (cname.equals(VALUE)) {
                                        JsonElement e = parser.parse(reader.nextString());
                                        c.setValue(e);
                                    } else {
                                        logger.debug("Found unexpected entry");
                                        reader.skipValue();
                                    }
                                    break;
                                default:
                                    logger.debug("Found unexpected entry");
                                    reader.skipValue();
                                    continue;
                                }
                            }
                            reader.endObject();
                            claimsSupplied.add(c);
                        }
                        reader.endArray();
                        ticket.setClaimsSupplied(claimsSupplied);
                    } else if (name.equals(EXPIRATION)) {
                        ticket.setExpiration(utcToDate(reader.nextString()));
                    } else if (name.equals(PERMISSION)) {
                        Permission p = new Permission();
                        Long rsid = null;
                        reader.beginObject();
                        while (reader.hasNext()) {
                            switch (reader.peek()) {
                            case END_OBJECT:
                                continue;
                            case NAME:
                                String pname = reader.nextName();
                                if (reader.peek() == JsonToken.NULL) {
                                    reader.skipValue();
                                } else if (pname.equals(RESOURCE_SET)) {
                                    rsid = reader.nextLong();
                                } else if (pname.equals(SCOPES)) {
                                    p.setScopes(readSet(reader));
                                } else {
                                    logger.debug("Found unexpected entry");
                                    reader.skipValue();
                                }
                                break;
                            default:
                                logger.debug("Found unexpected entry");
                                reader.skipValue();
                                continue;
                            }
                        }
                        reader.endObject();
                        Permission saved = permissionRepository.saveRawPermission(p);
                        permissionToResourceRefs.put(saved.getId(), rsid);
                        ticket.setPermission(saved);
                    } else if (name.equals(TICKET)) {
                        ticket.setTicket(reader.nextString());
                    } else {
                        logger.debug("Found unexpected entry");
                        reader.skipValue();
                    }
                    break;
                default:
                    logger.debug("Found unexpected entry");
                    reader.skipValue();
                    continue;
                }
            }
            reader.endObject();
            permissionRepository.save(ticket);
        }
        reader.endArray();
    }

    private Map<Long, Long> resourceSetOldToNewIdMap = new HashMap<>();

    /**
     * @param reader
     */
    private void readResourceSets(JsonReader reader) throws IOException {
        JsonParser parser = new JsonParser();
        reader.beginArray();
        while (reader.hasNext()) {
            Long oldId = null;
            ResourceSet rs = new ResourceSet();
            reader.beginObject();
            while (reader.hasNext()) {
                switch (reader.peek()) {
                case END_OBJECT:
                    continue;
                case NAME:
                    String name = reader.nextName();
                    if (reader.peek() == JsonToken.NULL) {
                        reader.skipValue();
                    } else if (name.equals(ID)) {
                        oldId = reader.nextLong();
                    } else if (name.equals(CLIENT_ID)) {
                        rs.setClientId(reader.nextString());
                    } else if (name.equals(ICON_URI)) {
                        rs.setIconUri(reader.nextString());
                    } else if (name.equals(NAME)) {
                        rs.setName(reader.nextString());
                    } else if (name.equals(TYPE)) {
                        rs.setType(reader.nextString());
                    } else if (name.equals(URI)) {
                        rs.setUri(reader.nextString());
                    } else if (name.equals(OWNER)) {
                        rs.setOwner(reader.nextString());
                    } else if (name.equals(POLICIES)) {
                        Set<Policy> policies = new HashSet<>();
                        reader.beginArray();
                        while (reader.hasNext()) {
                            Policy p = new Policy();
                            reader.beginObject();
                            while (reader.hasNext()) {
                                switch (reader.peek()) {
                                case END_OBJECT:
                                    continue;
                                case NAME:
                                    String pname = reader.nextName();
                                    if (reader.peek() == JsonToken.NULL) {
                                        reader.skipValue();
                                    } else if (pname.equals(NAME)) {
                                        p.setName(reader.nextString());
                                    } else if (pname.equals(SCOPES)) {
                                        p.setScopes(readSet(reader));
                                    } else if (pname.equals(CLAIMS_REQUIRED)) {
                                        Set<Claim> claimsRequired = new HashSet<>();
                                        reader.beginArray();
                                        while (reader.hasNext()) {
                                            Claim c = new Claim();
                                            reader.beginObject();
                                            while (reader.hasNext()) {
                                                switch (reader.peek()) {
                                                case END_OBJECT:
                                                    continue;
                                                case NAME:
                                                    String cname = reader.nextName();
                                                    if (reader.peek() == JsonToken.NULL) {
                                                        reader.skipValue();
                                                    } else if (cname.equals(ISSUER)) {
                                                        c.setIssuer(readSet(reader));
                                                    } else if (cname.equals(CLAIM_TOKEN_FORMAT)) {
                                                        c.setClaimTokenFormat(readSet(reader));
                                                    } else if (cname.equals(CLAIM_TYPE)) {
                                                        c.setClaimType(reader.nextString());
                                                    } else if (cname.equals(FRIENDLY_NAME)) {
                                                        c.setFriendlyName(reader.nextString());
                                                    } else if (cname.equals(NAME)) {
                                                        c.setName(reader.nextString());
                                                    } else if (cname.equals(VALUE)) {
                                                        JsonElement e = parser.parse(reader.nextString());
                                                        c.setValue(e);
                                                    } else {
                                                        logger.debug("Found unexpected entry");
                                                        reader.skipValue();
                                                    }
                                                    break;
                                                default:
                                                    logger.debug("Found unexpected entry");
                                                    reader.skipValue();
                                                    continue;
                                                }
                                            }
                                            reader.endObject();
                                            claimsRequired.add(c);
                                        }
                                        reader.endArray();
                                        p.setClaimsRequired(claimsRequired);
                                    } else {
                                        logger.debug("Found unexpected entry");
                                        reader.skipValue();
                                    }
                                    break;
                                default:
                                    logger.debug("Found unexpected entry");
                                    reader.skipValue();
                                    continue;
                                }
                            }
                            reader.endObject();
                            policies.add(p);
                        }
                        reader.endArray();
                        rs.setPolicies(policies);
                    } else if (name.equals(SCOPES)) {
                        rs.setScopes(readSet(reader));
                    } else {
                        logger.debug("Found unexpected entry");
                        reader.skipValue();
                    }
                    break;
                default:
                    logger.debug("Found unexpected entry");
                    reader.skipValue();
                    continue;
                }
            }
            reader.endObject();
            Long newId = resourceSetRepository.save(rs).getId();
            resourceSetOldToNewIdMap.put(oldId, newId);
        }
        reader.endArray();
        logger.info("Done reading resource sets");
    }

    /**
     * @param reader
     */
    private void readSavedRegisteredClients(JsonReader reader) throws IOException {
        reader.beginArray();
        while (reader.hasNext()) {
            String issuer = null;
            String clientString = null;
            reader.beginObject();
            while (reader.hasNext()) {
                switch (reader.peek()) {
                case END_OBJECT:
                    continue;
                case NAME:
                    String name = reader.nextName();
                    if (reader.peek() == JsonToken.NULL) {
                        reader.skipValue();
                    } else if (name.equals(ISSUER)) {
                        issuer = reader.nextString();
                    } else if (name.equals(REGISTERED_CLIENT)) {
                        clientString = reader.nextString();
                    } else {
                        logger.debug("Found unexpected entry");
                        reader.skipValue();
                    }
                    break;
                default:
                    logger.debug("Found unexpected entry");
                    reader.skipValue();
                    continue;
                }
            }
            reader.endObject();
            RegisteredClient client = ClientDetailsEntityJsonProcessor.parseRegistered(clientString);
            registeredClientService.save(issuer, client);
            logger.debug("Saved registered client");
        }
        reader.endArray();
        logger.info("Done reading saved registered clients");
    }

    /* (non-Javadoc)
     * @see org.mitre.openid.connect.service.MITREidDataServiceExtension#fixExtensionObjectReferences()
     */
    @Override
    public void fixExtensionObjectReferences(MITREidDataServiceMaps maps) {
        for (Long permissionId : permissionToResourceRefs.keySet()) {
            Long oldResourceId = permissionToResourceRefs.get(permissionId);
            Long newResourceId = resourceSetOldToNewIdMap.get(oldResourceId);
            Permission p = permissionRepository.getById(permissionId);
            ResourceSet rs = resourceSetRepository.getById(newResourceId);
            p.setResourceSet(rs);
            permissionRepository.saveRawPermission(p);
            logger.debug(
                    "Mapping rsid " + oldResourceId + " to " + newResourceId + " for permission " + permissionId);
        }
        for (Long tokenId : tokenToPermissionRefs.keySet()) {
            Long newTokenId = maps.getAccessTokenOldToNewIdMap().get(tokenId);
            OAuth2AccessTokenEntity token = tokenRepository.getAccessTokenById(newTokenId);

            Set<Permission> permissions = new HashSet<>();
            for (Long permissionId : tokenToPermissionRefs.get(tokenId)) {
                Permission p = permissionRepository.getById(permissionId);
                permissions.add(p);
            }

            token.setPermissions(permissions);
            tokenRepository.saveAccessToken(token);
        }
        permissionToResourceRefs.clear();
        resourceSetOldToNewIdMap.clear();
        tokenToPermissionRefs.clear();
    }

}