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}