started claims service, added expiration to permissions
parent
a57c336e11
commit
2aadb09f49
|
@ -0,0 +1,147 @@
|
|||
/*******************************************************************************
|
||||
* 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.model;
|
||||
|
||||
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.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* @author jricher
|
||||
*
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "claim")
|
||||
public class Claim {
|
||||
|
||||
private Long id;
|
||||
private String name;
|
||||
private String friendlyName;
|
||||
private String claimType;
|
||||
private Set<String> claimTokenFormat;
|
||||
private Set<String> issuer;
|
||||
|
||||
/**
|
||||
* @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 name
|
||||
*/
|
||||
@Basic
|
||||
@Column(name = "name")
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
/**
|
||||
* @param name the name to set
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the friendlyName
|
||||
*/
|
||||
@Basic
|
||||
@Column(name = "friendly_name")
|
||||
public String getFriendlyName() {
|
||||
return friendlyName;
|
||||
}
|
||||
/**
|
||||
* @param friendlyName the friendlyName to set
|
||||
*/
|
||||
public void setFriendlyName(String friendlyName) {
|
||||
this.friendlyName = friendlyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the claimType
|
||||
*/
|
||||
@Basic
|
||||
@Column(name = "claim_type")
|
||||
public String getClaimType() {
|
||||
return claimType;
|
||||
}
|
||||
/**
|
||||
* @param claimType the claimType to set
|
||||
*/
|
||||
public void setClaimType(String claimType) {
|
||||
this.claimType = claimType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the claimTokenFormat
|
||||
*/
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@Column(name = "claim_token_format")
|
||||
@CollectionTable(
|
||||
name = "claim_token_format",
|
||||
joinColumns = @JoinColumn(name = "owner_id")
|
||||
)
|
||||
public Set<String> getClaimTokenFormat() {
|
||||
return claimTokenFormat;
|
||||
}
|
||||
/**
|
||||
* @param claimTokenFormat the claimTokenFormat to set
|
||||
*/
|
||||
public void setClaimTokenFormat(Set<String> claimTokenFormat) {
|
||||
this.claimTokenFormat = claimTokenFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the issuer
|
||||
*/
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@Column(name = "claim_issuer")
|
||||
@CollectionTable(
|
||||
name = "issuer",
|
||||
joinColumns = @JoinColumn(name = "owner_id")
|
||||
)
|
||||
public Set<String> getIssuer() {
|
||||
return issuer;
|
||||
}
|
||||
/**
|
||||
* @param issuer the issuer to set
|
||||
*/
|
||||
public void setIssuer(Set<String> issuer) {
|
||||
this.issuer = issuer;
|
||||
}
|
||||
|
||||
}
|
|
@ -17,9 +17,12 @@
|
|||
|
||||
package org.mitre.uma.model;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
|
@ -30,7 +33,12 @@ import javax.persistence.GenerationType;
|
|||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -41,12 +49,21 @@ import javax.persistence.Table;
|
|||
*/
|
||||
@Entity
|
||||
@Table(name = "permission")
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = Permission.QUERY_TICKET, query = "select p from Permission p where p.ticket = :" + Permission.PARAM_TICKET)
|
||||
})
|
||||
public class Permission {
|
||||
|
||||
public static final String QUERY_TICKET = "Permission.queryByTicket";
|
||||
public static final String PARAM_TICKET = "ticket";
|
||||
|
||||
|
||||
private Long id;
|
||||
private ResourceSet resourceSet;
|
||||
private Set<String> scopes;
|
||||
private String ticket;
|
||||
private Date expiration;
|
||||
private Collection<Claim> claimsSupplied;
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
|
@ -116,6 +133,39 @@ public class Permission {
|
|||
public void setTicket(String ticket) {
|
||||
this.ticket = ticket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the expiration
|
||||
*/
|
||||
@Basic
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "expiration")
|
||||
public Date getExpiration() {
|
||||
return expiration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param expiration the expiration to set
|
||||
*/
|
||||
public void setExpiration(Date expiration) {
|
||||
this.expiration = expiration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the claimsSupplied
|
||||
*/
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "permission_id")
|
||||
public Collection<Claim> getClaimsSupplied() {
|
||||
return claimsSupplied;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param claimsSupplied the claimsSupplied to set
|
||||
*/
|
||||
public void setClaimsSupplied(Collection<Claim> claimsSupplied) {
|
||||
this.claimsSupplied = claimsSupplied;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
*******************************************************************************/
|
||||
package org.mitre.uma.model;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
|
@ -30,6 +32,7 @@ import javax.persistence.Id;
|
|||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
|
@ -46,7 +49,6 @@ public class ResourceSet {
|
|||
public static final String PARAM_OWNER = "owner";
|
||||
public static final String PARAM_CLIENTID = "clientId";
|
||||
|
||||
|
||||
private Long id;
|
||||
private String name;
|
||||
private String uri;
|
||||
|
@ -57,6 +59,8 @@ public class ResourceSet {
|
|||
private String owner; // username of the person responsible for the registration (either directly or via OAuth token)
|
||||
private String clientId; // client id of the protected resource that registered this resource set via OAuth token
|
||||
|
||||
private Collection<Claim> claimsRequired;
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
*/
|
||||
|
@ -189,6 +193,22 @@ public class ResourceSet {
|
|||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the claimsRequired
|
||||
*/
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "resource_set_id")
|
||||
public Collection<Claim> getClaimsRequired() {
|
||||
return claimsRequired;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param claimsRequired the claimsRequired to set
|
||||
*/
|
||||
public void setClaimsRequired(Collection<Claim> claimsRequired) {
|
||||
this.claimsRequired = claimsRequired;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -31,4 +31,12 @@ public interface PermissionRepository {
|
|||
*/
|
||||
public Permission save(Permission p);
|
||||
|
||||
/**
|
||||
* Get the permission indicated by its ticket value.
|
||||
*
|
||||
* @param ticket
|
||||
* @return
|
||||
*/
|
||||
public Permission getByTicket(String ticket);
|
||||
|
||||
}
|
||||
|
|
|
@ -38,4 +38,13 @@ public interface PermissionService {
|
|||
*/
|
||||
public Permission create(ResourceSet resourceSet, Set<String> scopes);
|
||||
|
||||
/**
|
||||
*
|
||||
* Read the permission associated with the given ticket.
|
||||
*
|
||||
* @param the ticket value to search on
|
||||
* @return the permission object, or null if none is found
|
||||
*/
|
||||
public Permission getByTicket(String ticket);
|
||||
|
||||
}
|
||||
|
|
|
@ -238,10 +238,30 @@ CREATE TABLE IF NOT EXISTS resource_set_scope (
|
|||
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
|
||||
ticket VARCHAR(256) NOT NULL,
|
||||
expiration TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS permission_scope (
|
||||
owner_id BIGINT NOT NULL,
|
||||
scope VARCHAR(256) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS claim (
|
||||
id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY,
|
||||
name VARCHAR(256),
|
||||
friendly_name VARCHAR(1024),
|
||||
claim_type VARCHAR(1024),
|
||||
resource_set_id BIGINT,
|
||||
permission_id BIGINT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS claim_token_format (
|
||||
owner_id BIGINT NOT NULL,
|
||||
claim_token_format VARCHAR(1024)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS claim_issuer (
|
||||
owner_id BIGINT NOT NULL,
|
||||
issuer VARCHAR(1024)
|
||||
);
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.mitre.openid.connect.model.UserInfo;
|
|||
import org.mitre.openid.connect.service.UserInfoService;
|
||||
import org.mitre.openid.connect.view.HttpCodeView;
|
||||
import org.mitre.openid.connect.view.JsonEntityView;
|
||||
import org.mitre.uma.web.AuthorizationRequestEndpoint;
|
||||
import org.mitre.uma.web.PermissionRegistrationEndpoint;
|
||||
import org.mitre.uma.web.ResourceSetRegistrationEndpoint;
|
||||
import org.mitre.openid.connect.web.DynamicClientRegistrationEndpoint;
|
||||
|
@ -376,7 +377,7 @@ public class DiscoveryEndpoint {
|
|||
m.put("introspection_endpoint", issuer + "introspect");
|
||||
m.put("resource_set_registration_endpoint", issuer + ResourceSetRegistrationEndpoint.URL);
|
||||
m.put("permission_registration_endpoint", issuer + PermissionRegistrationEndpoint.URL);
|
||||
// m.put("rpt_endpoint", issuer + RPT_ENDPOINT);
|
||||
m.put("rpt_endpoint", issuer + issuer + AuthorizationRequestEndpoint.URL);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ package org.mitre.uma.repository.impl;
|
|||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
import org.mitre.uma.model.Permission;
|
||||
import org.mitre.uma.repository.PermissionRepository;
|
||||
|
@ -42,4 +43,14 @@ public class JpaPermissionRepository implements PermissionRepository {
|
|||
return JpaUtil.saveOrUpdate(p.getId(), em, p);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.mitre.uma.repository.PermissionRepository#getByTicket(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Permission getByTicket(String ticket) {
|
||||
TypedQuery<Permission> query = em.createNamedQuery(Permission.QUERY_TICKET, Permission.class);
|
||||
query.setParameter(Permission.PARAM_TICKET, ticket);
|
||||
return JpaUtil.getSingleResult(query.getResultList());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package org.mitre.uma.service.impl;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -42,6 +43,8 @@ public class DefaultPermissionService implements PermissionService {
|
|||
@Autowired
|
||||
private SystemScopeService scopeService;
|
||||
|
||||
private Long permissionExpirationSeconds = 60L * 60L; // 1 hr
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.mitre.uma.service.PermissionService#create(org.mitre.uma.model.ResourceSet, java.util.Set)
|
||||
*/
|
||||
|
@ -58,9 +61,18 @@ public class DefaultPermissionService implements PermissionService {
|
|||
p.setResourceSet(resourceSet);
|
||||
p.setScopes(scopes);
|
||||
p.setTicket(UUID.randomUUID().toString());
|
||||
p.setExpiration(new Date(System.currentTimeMillis() + permissionExpirationSeconds * 1000L));
|
||||
|
||||
return repository.save(p);
|
||||
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.mitre.uma.service.PermissionService#getByTicket(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Permission getByTicket(String ticket) {
|
||||
return repository.getByTicket(ticket);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/*******************************************************************************
|
||||
* 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.web;
|
||||
|
||||
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||
import org.mitre.oauth2.service.OAuth2TokenEntityService;
|
||||
import org.mitre.oauth2.service.SystemScopeService;
|
||||
import org.mitre.oauth2.web.AuthenticationUtilities;
|
||||
import org.mitre.openid.connect.view.HttpCodeView;
|
||||
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.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
/**
|
||||
* @author jricher
|
||||
*
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/" + AuthorizationRequestEndpoint.URL)
|
||||
public class AuthorizationRequestEndpoint {
|
||||
|
||||
public static final String RPT = "rpt";
|
||||
public static final String TICKET = "ticket";
|
||||
public static final String URL = "authz_request";
|
||||
|
||||
@Autowired
|
||||
private PermissionService permissionService;
|
||||
|
||||
@Autowired
|
||||
private OAuth2TokenEntityService tokenService;
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
|
||||
public String authorizationRequest(@RequestBody String jsonString, Model m, Authentication auth) {
|
||||
|
||||
AuthenticationUtilities.ensureOAuthScope(auth, SystemScopeService.UMA_AUTHORIZATION_SCOPE);
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonElement e = parser.parse(jsonString);
|
||||
|
||||
if (e.isJsonObject()) {
|
||||
JsonObject o = e.getAsJsonObject();
|
||||
|
||||
if (o.has(TICKET)) {
|
||||
|
||||
OAuth2AccessTokenEntity rpt = null;
|
||||
if (o.has(RPT)) {
|
||||
String rptValue = o.get(RPT).getAsString();
|
||||
rpt = tokenService.readAccessToken(rptValue);
|
||||
}
|
||||
|
||||
String ticketValue = o.get(TICKET).getAsString();
|
||||
|
||||
Permission perm = permissionService.getByTicket(ticketValue);
|
||||
|
||||
if (perm != null) {
|
||||
// found the ticket, see if it's any good
|
||||
|
||||
ResourceSet rs = perm.getResourceSet();
|
||||
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
// ticket wasn't found, return an error
|
||||
m.addAttribute(HttpStatus.BAD_REQUEST);
|
||||
m.addAttribute(JsonErrorView.ERROR, "invalid_ticket");
|
||||
return JsonErrorView.VIEWNAME;
|
||||
}
|
||||
|
||||
} else {
|
||||
m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
|
||||
m.addAttribute(JsonErrorView.ERROR_MESSAGE, "Missing JSON elements.");
|
||||
return JsonErrorView.VIEWNAME;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
m.addAttribute(HttpCodeView.CODE, HttpStatus.BAD_REQUEST);
|
||||
m.addAttribute(JsonErrorView.ERROR_MESSAGE, "Malformed JSON request.");
|
||||
return JsonErrorView.VIEWNAME;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue