First stages of getting the graylist portion to work. Currently no mechanism for telling the system NOT to remember your decision; that will come later. All approvals will be automatically stored with this code.
parent
db415bfa2b
commit
845976b8ac
|
@ -19,6 +19,7 @@ import java.util.Date;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.persistence.Basic;
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.CollectionTable;
|
||||||
import javax.persistence.ElementCollection;
|
import javax.persistence.ElementCollection;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.FetchType;
|
import javax.persistence.FetchType;
|
||||||
|
@ -162,6 +163,10 @@ public class ApprovedSite {
|
||||||
* @return the allowedScopes
|
* @return the allowedScopes
|
||||||
*/
|
*/
|
||||||
@ElementCollection(fetch = FetchType.EAGER)
|
@ElementCollection(fetch = FetchType.EAGER)
|
||||||
|
@CollectionTable(
|
||||||
|
name="allowed_scopes",
|
||||||
|
joinColumns=@JoinColumn(name="owner_id")
|
||||||
|
)
|
||||||
public Set<String> getAllowedScopes() {
|
public Set<String> getAllowedScopes() {
|
||||||
return allowedScopes;
|
return allowedScopes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
create table allowed_scopes(
|
||||||
|
owner_id VARCHAR(256),
|
||||||
|
allowedScopes VARCHAR(256)
|
||||||
|
);
|
|
@ -76,7 +76,7 @@ public class JpaApprovedSiteRepository implements ApprovedSiteRepository {
|
||||||
public Collection<ApprovedSite> getByUserInfo(UserInfo userInfo) {
|
public Collection<ApprovedSite> getByUserInfo(UserInfo userInfo) {
|
||||||
TypedQuery<ApprovedSite> query = manager.createNamedQuery(
|
TypedQuery<ApprovedSite> query = manager.createNamedQuery(
|
||||||
"ApprovedSite.getByUserInfo", ApprovedSite.class);
|
"ApprovedSite.getByUserInfo", ApprovedSite.class);
|
||||||
query.setParameter("approvedSiteUserInfo", userInfo.getUserId());
|
query.setParameter("approvedSiteUserInfo", userInfo);
|
||||||
|
|
||||||
List<ApprovedSite> found = query.getResultList();
|
List<ApprovedSite> found = query.getResultList();
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ import javax.persistence.TypedQuery;
|
||||||
import org.mitre.openid.connect.model.UserInfo;
|
import org.mitre.openid.connect.model.UserInfo;
|
||||||
import org.mitre.openid.connect.model.WhitelistedSite;
|
import org.mitre.openid.connect.model.WhitelistedSite;
|
||||||
import org.mitre.openid.connect.repository.WhitelistedSiteRepository;
|
import org.mitre.openid.connect.repository.WhitelistedSiteRepository;
|
||||||
|
import org.mitre.util.jpa.JpaUtil;
|
||||||
import org.springframework.security.oauth2.provider.ClientDetails;
|
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
@ -88,8 +89,7 @@ public class JpaWhitelistedSiteRepository implements WhitelistedSiteRepository {
|
||||||
public WhitelistedSite getByClientDetails(ClientDetails client) {
|
public WhitelistedSite getByClientDetails(ClientDetails client) {
|
||||||
TypedQuery<WhitelistedSite> query = manager.createNamedQuery("WhitelistedSite.getByClientDetails", WhitelistedSite.class);
|
TypedQuery<WhitelistedSite> query = manager.createNamedQuery("WhitelistedSite.getByClientDetails", WhitelistedSite.class);
|
||||||
query.setParameter("clientDetails", client);
|
query.setParameter("clientDetails", client);
|
||||||
|
return JpaUtil.getSingleResult(query.getResultList());
|
||||||
return query.getSingleResult();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -17,7 +17,9 @@ package org.mitre.openid.connect.token;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||||
import org.mitre.openid.connect.model.ApprovedSite;
|
import org.mitre.openid.connect.model.ApprovedSite;
|
||||||
import org.mitre.openid.connect.model.DefaultUserInfo;
|
import org.mitre.openid.connect.model.DefaultUserInfo;
|
||||||
import org.mitre.openid.connect.model.WhitelistedSite;
|
import org.mitre.openid.connect.model.WhitelistedSite;
|
||||||
|
@ -31,6 +33,9 @@ import org.springframework.security.oauth2.provider.ClientDetails;
|
||||||
import org.springframework.security.oauth2.provider.ClientDetailsService;
|
import org.springframework.security.oauth2.provider.ClientDetailsService;
|
||||||
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
|
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
|
||||||
|
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom User Approval Handler implementation which uses a concept of a whitelist,
|
* Custom User Approval Handler implementation which uses a concept of a whitelist,
|
||||||
* blacklist, and greylist.
|
* blacklist, and greylist.
|
||||||
|
@ -75,19 +80,22 @@ public class JdbcUserApprovalHandler implements UserApprovalHandler {
|
||||||
@Override
|
@Override
|
||||||
public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) {
|
public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) {
|
||||||
|
|
||||||
//Check database to see if the user identified by the userAuthentication has stored an approval decision
|
//First, check database to see if the user identified by the userAuthentication has stored an approval decision
|
||||||
|
|
||||||
String userId = userAuthentication.getName();
|
String userId = userAuthentication.getName();
|
||||||
|
|
||||||
ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId());
|
ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId());
|
||||||
|
|
||||||
//lookup ApprovedSites by userId
|
|
||||||
DefaultUserInfo user = (DefaultUserInfo)userInfoService.getByUserId(userId);
|
DefaultUserInfo user = (DefaultUserInfo)userInfoService.getByUserId(userId);
|
||||||
|
|
||||||
|
//lookup ApprovedSites by userId
|
||||||
Collection<ApprovedSite> approvedSites = approvedSiteService.getByUserInfo(user);
|
Collection<ApprovedSite> approvedSites = approvedSiteService.getByUserInfo(user);
|
||||||
|
|
||||||
for (ApprovedSite ap : approvedSites) {
|
for (ApprovedSite ap : approvedSites) {
|
||||||
if (ap.getClientDetails().getClientId() == client.getClientId()) {
|
if (sitesMatch(ap, authorizationRequest, user)) {
|
||||||
//TODO need to test more than just id
|
|
||||||
|
//We have a match; update the access date on the AP entry and return true.
|
||||||
|
ap.setAccessDate(new Date());
|
||||||
|
approvedSiteService.save(ap);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,15 +115,57 @@ public class JdbcUserApprovalHandler implements UserApprovalHandler {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authorizationRequest.isApproved() && !authorizationRequest.getApprovalParameters().isEmpty()) {
|
boolean approved = Boolean.parseBoolean(authorizationRequest.getApprovalParameters().get("user_oauth_approval"));
|
||||||
|
|
||||||
|
if (approved && !authorizationRequest.getApprovalParameters().isEmpty()) {
|
||||||
|
|
||||||
|
//TODO: check approval parameters to see if we should store this request or not
|
||||||
|
|
||||||
//Make a new AP
|
//Make a new AP
|
||||||
ApprovedSite newAP = new ApprovedSite();
|
ApprovedSite newAP = new ApprovedSite();
|
||||||
newAP.setAccessDate(new Date());
|
newAP.setAccessDate(new Date());
|
||||||
//Set<String> allowedScopes = authorizationRequest.getApprovalParameters().get("scope");
|
String scopes = authorizationRequest.getAuthorizationParameters().get("scope");
|
||||||
//newAP.setAllowedScopes(allowedScopes);
|
Set<String> allowedScopes = Sets.newHashSet(Splitter.on(" ").split(scopes));
|
||||||
|
newAP.setAllowedScopes(allowedScopes);
|
||||||
|
newAP.setClientDetails((ClientDetailsEntity)client);
|
||||||
|
newAP.setUserInfo((DefaultUserInfo)user);
|
||||||
|
newAP.setCreationDate(new Date());
|
||||||
|
approvedSiteService.save(newAP);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a given ApprovedSite entry matches the information about the current request.
|
||||||
|
*
|
||||||
|
* @param ap the ApprovedSite to compare
|
||||||
|
* @param authReq the AuthorizationRequest for this requst
|
||||||
|
* @param user the User making the request
|
||||||
|
* @return true if everything matches, false otherwise
|
||||||
|
*/
|
||||||
|
private boolean sitesMatch(ApprovedSite ap, AuthorizationRequest authReq, DefaultUserInfo user) {
|
||||||
|
|
||||||
|
ClientDetails client = clientDetailsService.loadClientByClientId(authReq.getClientId());
|
||||||
|
|
||||||
|
String scopes = authReq.getAuthorizationParameters().get("scope");
|
||||||
|
Set<String> allowedScopes = Sets.newHashSet(Splitter.on(" ").split(scopes));
|
||||||
|
|
||||||
|
if (!(ap.getClientDetails().getClientId()).equalsIgnoreCase(client.getClientId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(ap.getUserInfo().getUserId()).equalsIgnoreCase(user.getUserId())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (String scope : allowedScopes) {
|
||||||
|
if (!ap.getAllowedScopes().contains(scope)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
client-details-service-ref="defaultOAuth2ClientDetailsEntityService"
|
client-details-service-ref="defaultOAuth2ClientDetailsEntityService"
|
||||||
authorization-request-factory-ref="authorizationRequestFactory"
|
authorization-request-factory-ref="authorizationRequestFactory"
|
||||||
token-services-ref="defaultOAuth2ProviderTokenService"
|
token-services-ref="defaultOAuth2ProviderTokenService"
|
||||||
user-approval-handler-ref="userApprovalHandler"
|
user-approval-handler-ref="jdbcUserApprovalHandler"
|
||||||
authorization-endpoint-url="/authorize"
|
authorization-endpoint-url="/authorize"
|
||||||
token-endpoint-url="/token">
|
token-endpoint-url="/token">
|
||||||
|
|
||||||
|
@ -82,8 +82,7 @@
|
||||||
</constructor-arg>
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler" id="userApprovalHandler">
|
<bean class="org.mitre.openid.connect.token.JdbcUserApprovalHandler" id="jdbcUserApprovalHandler">
|
||||||
<property name="tokenServices" ref="defaultOAuth2ProviderTokenService" />
|
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="authCodeServices" class="org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices" />
|
<bean id="authCodeServices" class="org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices" />
|
||||||
|
|
|
@ -62,16 +62,16 @@
|
||||||
<div class="span4">
|
<div class="span4">
|
||||||
<fieldset style="text-align:left" class="well">
|
<fieldset style="text-align:left" class="well">
|
||||||
<legend style="margin-bottom: 0;">Access to:</legend>
|
<legend style="margin-bottom: 0;">Access to:</legend>
|
||||||
<label for="option1"></label>
|
|
||||||
<input type="checkbox" name="option1" id="option1" checked="checked"> basic profile information
|
<input type="checkbox" name="scope_profile" id="scope_profile" value="true" checked="checked"><label for="scope_profile">basic profile information</label>
|
||||||
<label for="option2"></label>
|
|
||||||
<input type="checkbox" name="option1" id="option2" checked="checked"> email address
|
<input type="checkbox" name="scope_email" id="scope_email" value="true" checked="checked"><label for="scope_email">email address</label>
|
||||||
<label for="option3"></label>
|
|
||||||
<input type="checkbox" name="option3" id="option3" checked="checked"> address
|
<input type="checkbox" name="scope_address" id="scope_address" value="true" checked="checked"><label for="scope_address">address</label>
|
||||||
<label for="option4"></label>
|
|
||||||
<input type="checkbox" name="option4" id="option4" checked="checked"> phone number
|
<input type="checkbox" name="scope_phone" id="scope_phone" value="true" checked="checked"><label for="scope_phone">phone number</label>
|
||||||
<label for="option5"></label>
|
|
||||||
<input type="checkbox" name="option5" id="option5" checked="checked"> offline access
|
<input type="checkbox" name="scope_offline" id="scope_offline" value="true" checked="checked"><label for="scope_offline">offline access</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue