001/*******************************************************************************
002 * Copyright 2017 The MIT Internet Trust Consortium
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *   http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *******************************************************************************/
016
017package org.mitre.uma.web;
018
019import static org.mitre.oauth2.web.AuthenticationUtilities.ensureOAuthScope;
020import static org.mitre.util.JsonUtils.getAsLong;
021import static org.mitre.util.JsonUtils.getAsStringSet;
022
023import java.util.Set;
024
025import org.mitre.oauth2.model.SystemScope;
026import org.mitre.oauth2.service.SystemScopeService;
027import org.mitre.openid.connect.view.JsonEntityView;
028import org.mitre.openid.connect.view.JsonErrorView;
029import org.mitre.uma.model.PermissionTicket;
030import org.mitre.uma.model.ResourceSet;
031import org.mitre.uma.service.PermissionService;
032import org.mitre.uma.service.ResourceSetService;
033import org.slf4j.Logger;
034import org.slf4j.LoggerFactory;
035import org.springframework.beans.factory.annotation.Autowired;
036import org.springframework.http.HttpStatus;
037import org.springframework.security.access.prepost.PreAuthorize;
038import org.springframework.security.core.Authentication;
039import org.springframework.stereotype.Controller;
040import org.springframework.ui.Model;
041import org.springframework.util.MimeTypeUtils;
042import org.springframework.web.bind.annotation.RequestBody;
043import org.springframework.web.bind.annotation.RequestMapping;
044import org.springframework.web.bind.annotation.RequestMethod;
045
046import com.google.gson.JsonElement;
047import com.google.gson.JsonObject;
048import com.google.gson.JsonParseException;
049import com.google.gson.JsonParser;
050
051/**
052 * @author jricher
053 *
054 */
055@Controller
056@RequestMapping("/" + PermissionRegistrationEndpoint.URL)
057@PreAuthorize("hasRole('ROLE_USER')")
058public class PermissionRegistrationEndpoint {
059        // Logger for this class
060        private static final Logger logger = LoggerFactory.getLogger(PermissionRegistrationEndpoint.class);
061
062        public static final String URL = "permission";
063
064        @Autowired
065        private PermissionService permissionService;
066
067        @Autowired
068        private ResourceSetService resourceSetService;
069
070        @Autowired
071        private SystemScopeService scopeService;
072
073        private JsonParser parser = new JsonParser();
074
075        @RequestMapping(method = RequestMethod.POST, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
076        public String getPermissionTicket(@RequestBody String jsonString, Model m, Authentication auth) {
077
078                ensureOAuthScope(auth, SystemScopeService.UMA_PROTECTION_SCOPE);
079
080                try {
081
082                        // parse the permission request
083
084                        JsonElement el = parser.parse(jsonString);
085                        if (el.isJsonObject()) {
086                                JsonObject o = el.getAsJsonObject();
087
088                                Long rsid = getAsLong(o, "resource_set_id");
089                                Set<String> scopes = getAsStringSet(o, "scopes");
090
091                                if (rsid == null || scopes == null || scopes.isEmpty()){
092                                        // missing information
093                                        m.addAttribute("code", HttpStatus.BAD_REQUEST);
094                                        m.addAttribute("errorMessage", "Missing required component of permission registration request.");
095                                        return JsonErrorView.VIEWNAME;
096                                }
097
098                                // trim any restricted scopes
099                                Set<SystemScope> scopesRequested = scopeService.fromStrings(scopes);
100                                scopesRequested = scopeService.removeRestrictedAndReservedScopes(scopesRequested);
101                                scopes = scopeService.toStrings(scopesRequested);
102
103                                ResourceSet resourceSet = resourceSetService.getById(rsid);
104
105                                // requested resource set doesn't exist
106                                if (resourceSet == null) {
107                                        m.addAttribute("code", HttpStatus.NOT_FOUND);
108                                        m.addAttribute("errorMessage", "Requested resource set not found: " + rsid);
109                                        return JsonErrorView.VIEWNAME;
110                                }
111
112                                // authorized user of the token doesn't match owner of the resource set
113                                if (!resourceSet.getOwner().equals(auth.getName())) {
114                                        m.addAttribute("code", HttpStatus.FORBIDDEN);
115                                        m.addAttribute("errorMessage", "Party requesting permission is not owner of resource set, expected " + resourceSet.getOwner() + " got " + auth.getName());
116                                        return JsonErrorView.VIEWNAME;
117                                }
118
119                                // create the permission
120                                PermissionTicket permission = permissionService.createTicket(resourceSet, scopes);
121
122                                if (permission != null) {
123                                        // we've created the permission, return the ticket
124                                        JsonObject out = new JsonObject();
125                                        out.addProperty("ticket", permission.getTicket());
126                                        m.addAttribute("entity", out);
127
128                                        m.addAttribute("code", HttpStatus.CREATED);
129
130                                        return JsonEntityView.VIEWNAME;
131                                } else {
132                                        // there was a failure creating the permission object
133
134                                        m.addAttribute("code", HttpStatus.INTERNAL_SERVER_ERROR);
135                                        m.addAttribute("errorMessage", "Unable to save permission and generate ticket.");
136
137                                        return JsonErrorView.VIEWNAME;
138                                }
139
140                        } else {
141                                // malformed request
142                                m.addAttribute("code", HttpStatus.BAD_REQUEST);
143                                m.addAttribute("errorMessage", "Malformed JSON request.");
144                                return JsonErrorView.VIEWNAME;
145                        }
146                } catch (JsonParseException e) {
147                        // malformed request
148                        m.addAttribute("code", HttpStatus.BAD_REQUEST);
149                        m.addAttribute("errorMessage", "Malformed JSON request.");
150                        return JsonErrorView.VIEWNAME;
151                }
152
153        }
154
155}