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.

pull/165/merge
Amanda Anganes 12 years ago
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…
Cancel
Save