implemented permission registration API
parent
eed8fb0b28
commit
5ff9cd1bbb
|
@ -17,10 +17,19 @@
|
||||||
|
|
||||||
package org.mitre.uma.model;
|
package org.mitre.uma.model;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.CollectionTable;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.ElementCollection;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -39,5 +48,74 @@ public class Permission {
|
||||||
private Set<String> scopes;
|
private Set<String> scopes;
|
||||||
private String ticket;
|
private String ticket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the id
|
||||||
|
*/
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id")
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id the id to set
|
||||||
|
*/
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the resourceSet
|
||||||
|
*/
|
||||||
|
@ManyToOne(fetch = FetchType.EAGER)
|
||||||
|
@JoinColumn(name = "resource_set_id")
|
||||||
|
public ResourceSet getResourceSet() {
|
||||||
|
return resourceSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param resourceSet the resourceSet to set
|
||||||
|
*/
|
||||||
|
public void setResourceSet(ResourceSet resourceSet) {
|
||||||
|
this.resourceSet = resourceSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the scopes
|
||||||
|
*/
|
||||||
|
@ElementCollection(fetch = FetchType.EAGER)
|
||||||
|
@Column(name = "scope")
|
||||||
|
@CollectionTable(
|
||||||
|
name = "permission_scope",
|
||||||
|
joinColumns = @JoinColumn(name = "owner_id")
|
||||||
|
)
|
||||||
|
public Set<String> getScopes() {
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param scopes the scopes to set
|
||||||
|
*/
|
||||||
|
public void setScopes(Set<String> scopes) {
|
||||||
|
this.scopes = scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the ticket
|
||||||
|
*/
|
||||||
|
@Basic
|
||||||
|
@Column(name = "ticket")
|
||||||
|
public String getTicket() {
|
||||||
|
return ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ticket the ticket to set
|
||||||
|
*/
|
||||||
|
public void setTicket(String ticket) {
|
||||||
|
this.ticket = ticket;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,18 @@
|
||||||
|
|
||||||
package org.mitre.uma.repository;
|
package org.mitre.uma.repository;
|
||||||
|
|
||||||
|
import org.mitre.uma.model.Permission;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author jricher
|
* @author jricher
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public interface PermissionRespository {
|
public interface PermissionRepository {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param p
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Permission save(Permission p);
|
||||||
|
|
||||||
}
|
}
|
|
@ -17,6 +17,11 @@
|
||||||
|
|
||||||
package org.mitre.uma.service;
|
package org.mitre.uma.service;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.mitre.uma.model.Permission;
|
||||||
|
import org.mitre.uma.model.ResourceSet;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author jricher
|
* @author jricher
|
||||||
|
@ -24,4 +29,11 @@ package org.mitre.uma.service;
|
||||||
*/
|
*/
|
||||||
public interface PermissionService {
|
public interface PermissionService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param resourceSet the resource set to create the permission on
|
||||||
|
* @param scopes the set of scopes that this permission is for
|
||||||
|
* @return the created (and stored) permission object, with ticket
|
||||||
|
*/
|
||||||
|
public Permission create(ResourceSet resourceSet, Set<String> scopes);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,14 +221,28 @@ CREATE TABLE IF NOT EXISTS pairwise_identifier (
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS resource_set (
|
CREATE TABLE IF NOT EXISTS resource_set (
|
||||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY,
|
id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY,
|
||||||
name VARCHAR(1024),
|
name VARCHAR(1024) NOT NULL,
|
||||||
uri VARCHAR(1024),
|
uri VARCHAR(1024),
|
||||||
icon_uri VARCHAR(1024),
|
icon_uri VARCHAR(1024),
|
||||||
rs_type VARCHAR(256),
|
rs_type VARCHAR(256),
|
||||||
owner VARCHAR(256)
|
owner VARCHAR(256) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS resource_set_scope (
|
CREATE TABLE IF NOT EXISTS resource_set_scope (
|
||||||
owner_id BIGINT,
|
owner_id BIGINT NOT NULL,
|
||||||
scope VARCHAR(256)
|
scope VARCHAR(256) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS permission (
|
||||||
|
id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY,
|
||||||
|
resource_set_id BIGINT NOT NULL,
|
||||||
|
ticket VARCHAR(256) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS permission_scope (
|
||||||
|
owner_id BIGINT NOT NULL,
|
||||||
|
scope VARCHAR(256) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,13 @@
|
||||||
<security:intercept-url pattern="/resource/**" access="permitAll"/>
|
<security:intercept-url pattern="/resource/**" access="permitAll"/>
|
||||||
</security:http>
|
</security:http>
|
||||||
|
|
||||||
<security:http pattern="/#{T(org.mitre.openid.connect.web.ResourceSetRegistrationEndpoint).URL}/**" use-expressions="true" entry-point-ref="oauthAuthenticationEntryPoint" create-session="never">
|
<security:http pattern="/#{T(org.mitre.uma.web.ResourceSetRegistrationEndpoint).URL}/**" use-expressions="true" entry-point-ref="oauthAuthenticationEntryPoint" create-session="never">
|
||||||
|
<security:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
|
||||||
|
<security:custom-filter ref="corsFilter" after="SECURITY_CONTEXT_FILTER" />
|
||||||
|
<security:expression-handler ref="oauthWebExpressionHandler" />
|
||||||
|
</security:http>
|
||||||
|
|
||||||
|
<security:http pattern="/#{T(org.mitre.uma.web.PermissionRegistrationEndpoint).URL}/**" use-expressions="true" entry-point-ref="oauthAuthenticationEntryPoint" create-session="never">
|
||||||
<security:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
|
<security:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
|
||||||
<security:custom-filter ref="corsFilter" after="SECURITY_CONTEXT_FILTER" />
|
<security:custom-filter ref="corsFilter" after="SECURITY_CONTEXT_FILTER" />
|
||||||
<security:expression-handler ref="oauthWebExpressionHandler" />
|
<security:expression-handler ref="oauthWebExpressionHandler" />
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright 2015 The MITRE Corporation
|
||||||
|
* and the MIT Kerberos and 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.repository.impl;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
|
|
||||||
|
import org.mitre.uma.model.Permission;
|
||||||
|
import org.mitre.uma.repository.PermissionRepository;
|
||||||
|
import org.mitre.util.jpa.JpaUtil;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jricher
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public class JpaPermissionRepository implements PermissionRepository {
|
||||||
|
|
||||||
|
@PersistenceContext
|
||||||
|
private EntityManager em;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
|
public Permission save(Permission p) {
|
||||||
|
return JpaUtil.saveOrUpdate(p.getId(), em, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright 2015 The MITRE Corporation
|
||||||
|
* and the MIT Kerberos and 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 java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.mitre.uma.model.Permission;
|
||||||
|
import org.mitre.uma.model.ResourceSet;
|
||||||
|
import org.mitre.uma.repository.PermissionRepository;
|
||||||
|
import org.mitre.uma.service.PermissionService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jricher
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class DefaultPermissionService implements PermissionService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PermissionRepository repository;
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.mitre.uma.service.PermissionService#create(org.mitre.uma.model.ResourceSet, java.util.Set)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Permission create(ResourceSet resourceSet, Set<String> scopes) {
|
||||||
|
Permission p = new Permission();
|
||||||
|
p.setResourceSet(resourceSet);
|
||||||
|
p.setScopes(scopes);
|
||||||
|
p.setTicket(UUID.randomUUID().toString());
|
||||||
|
|
||||||
|
return repository.save(p);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -18,11 +18,20 @@
|
||||||
package org.mitre.uma.web;
|
package org.mitre.uma.web;
|
||||||
|
|
||||||
import static org.mitre.uma.web.OAuthScopeEnforcementUtilities.ensureOAuthScope;
|
import static org.mitre.uma.web.OAuthScopeEnforcementUtilities.ensureOAuthScope;
|
||||||
|
import static org.mitre.util.JsonUtils.getAsLong;
|
||||||
|
import static org.mitre.util.JsonUtils.getAsStringSet;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.mitre.oauth2.service.SystemScopeService;
|
import org.mitre.oauth2.service.SystemScopeService;
|
||||||
import org.mitre.openid.connect.view.JsonEntityView;
|
import org.mitre.openid.connect.view.JsonEntityView;
|
||||||
|
import org.mitre.openid.connect.view.JsonErrorView;
|
||||||
|
import org.mitre.uma.model.Permission;
|
||||||
|
import org.mitre.uma.model.ResourceSet;
|
||||||
import org.mitre.uma.service.PermissionService;
|
import org.mitre.uma.service.PermissionService;
|
||||||
|
import org.mitre.uma.service.ResourceSetService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
@ -32,6 +41,11 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author jricher
|
* @author jricher
|
||||||
*
|
*
|
||||||
|
@ -46,14 +60,83 @@ public class PermissionRegistrationEndpoint {
|
||||||
@Autowired
|
@Autowired
|
||||||
private PermissionService permissionService;
|
private PermissionService permissionService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ResourceSetService resourceSetService;
|
||||||
|
|
||||||
|
private JsonParser parser = new JsonParser();
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.POST, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
|
@RequestMapping(method = RequestMethod.POST, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
|
||||||
public String getPermissionTicket(@RequestBody String jsonString, Model m, Authentication auth) {
|
public String getPermissionTicket(@RequestBody String jsonString, Model m, Authentication auth) {
|
||||||
|
|
||||||
ensureOAuthScope(auth, SystemScopeService.UMA_PROTECTION_SCOPE);
|
ensureOAuthScope(auth, SystemScopeService.UMA_PROTECTION_SCOPE);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// parse the permission request
|
||||||
|
|
||||||
|
JsonElement el = parser.parse(jsonString);
|
||||||
|
if (el.isJsonObject()) {
|
||||||
|
JsonObject o = el.getAsJsonObject();
|
||||||
|
|
||||||
|
Long rsid = getAsLong(o, "resource_set_id");
|
||||||
|
Set<String> scopes = getAsStringSet(o, "scopes");
|
||||||
|
|
||||||
|
if (rsid == null || scopes == null || scopes.isEmpty()){
|
||||||
|
// missing information
|
||||||
|
m.addAttribute("code", HttpStatus.BAD_REQUEST);
|
||||||
|
m.addAttribute("errorMessage", "Missing required component of resource registration request.");
|
||||||
|
return JsonErrorView.VIEWNAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceSet resourceSet = resourceSetService.getById(rsid);
|
||||||
|
|
||||||
|
// requested resource set doesn't exist
|
||||||
|
if (resourceSet == null) {
|
||||||
|
m.addAttribute("code", HttpStatus.NOT_FOUND);
|
||||||
|
m.addAttribute("errorMessage", "Requested resource set not found: " + rsid);
|
||||||
|
return JsonErrorView.VIEWNAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
// authorized user of the token doesn't match owner of the resource set
|
||||||
|
if (!resourceSet.getOwner().equals(auth.getName())) {
|
||||||
|
m.addAttribute("code", HttpStatus.FORBIDDEN);
|
||||||
|
m.addAttribute("errorMessage", "Party requesting permission is not owner of resource set, expected " + resourceSet.getOwner() + " got " + auth.getName());
|
||||||
|
return JsonErrorView.VIEWNAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the permission
|
||||||
|
Permission permission = permissionService.create(resourceSet, scopes);
|
||||||
|
|
||||||
|
if (permission != null) {
|
||||||
|
// we've created the permission, return the ticket
|
||||||
|
JsonObject out = new JsonObject();
|
||||||
|
out.addProperty("ticket", permission.getTicket());
|
||||||
|
m.addAttribute("entity", out);
|
||||||
|
|
||||||
|
m.addAttribute("code", HttpStatus.CREATED);
|
||||||
|
|
||||||
return JsonEntityView.VIEWNAME;
|
return JsonEntityView.VIEWNAME;
|
||||||
|
} else {
|
||||||
|
// there was a failure creating the permission object
|
||||||
|
|
||||||
|
m.addAttribute("code", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
m.addAttribute("errorMessage", "Unable to save permission and generate ticket.");
|
||||||
|
|
||||||
|
return JsonErrorView.VIEWNAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// malformed request
|
||||||
|
m.addAttribute("code", HttpStatus.BAD_REQUEST);
|
||||||
|
m.addAttribute("errorMessage", "Malformed JSON request.");
|
||||||
|
return JsonErrorView.VIEWNAME;
|
||||||
|
}
|
||||||
|
} catch (JsonParseException e) {
|
||||||
|
// malformed request
|
||||||
|
m.addAttribute("code", HttpStatus.BAD_REQUEST);
|
||||||
|
m.addAttribute("errorMessage", "Malformed JSON request.");
|
||||||
|
return JsonErrorView.VIEWNAME;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ public class ResourceSetRegistrationEndpoint {
|
||||||
|
|
||||||
if (!auth.getName().equals(rs.getOwner())) {
|
if (!auth.getName().equals(rs.getOwner())) {
|
||||||
|
|
||||||
logger.warn("Unauthorized resource set request from bad user; expected " + rs.getOwner() + " got " + auth.getName());
|
logger.warn("Unauthorized resource set request from wrong user; expected " + rs.getOwner() + " got " + auth.getName());
|
||||||
|
|
||||||
// it wasn't issued to this user
|
// it wasn't issued to this user
|
||||||
m.addAttribute("code", HttpStatus.FORBIDDEN);
|
m.addAttribute("code", HttpStatus.FORBIDDEN);
|
||||||
|
|
Loading…
Reference in New Issue