diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java index 324a187af..796cdb1f7 100644 --- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java @@ -19,6 +19,7 @@ import java.util.Date; import java.util.Set; import javax.persistence.Basic; +import javax.persistence.CollectionTable; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.FetchType; @@ -162,6 +163,10 @@ public class ApprovedSite { * @return the allowedScopes */ @ElementCollection(fetch = FetchType.EAGER) + @CollectionTable( + name="allowed_scopes", + joinColumns=@JoinColumn(name="owner_id") + ) public Set getAllowedScopes() { return allowedScopes; } diff --git a/openid-connect-server/db/tables/allowed_scopes.sql b/openid-connect-server/db/tables/allowed_scopes.sql new file mode 100644 index 000000000..cdb952c32 --- /dev/null +++ b/openid-connect-server/db/tables/allowed_scopes.sql @@ -0,0 +1,4 @@ +create table allowed_scopes( + owner_id VARCHAR(256), + allowedScopes VARCHAR(256) +); diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java index 428a56ec8..b0959d851 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaApprovedSiteRepository.java @@ -76,7 +76,7 @@ public class JpaApprovedSiteRepository implements ApprovedSiteRepository { public Collection getByUserInfo(UserInfo userInfo) { TypedQuery query = manager.createNamedQuery( "ApprovedSite.getByUserInfo", ApprovedSite.class); - query.setParameter("approvedSiteUserInfo", userInfo.getUserId()); + query.setParameter("approvedSiteUserInfo", userInfo); List found = query.getResultList(); diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java index 00a51f3e1..22587d1f0 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java @@ -26,6 +26,7 @@ import javax.persistence.TypedQuery; import org.mitre.openid.connect.model.UserInfo; import org.mitre.openid.connect.model.WhitelistedSite; import org.mitre.openid.connect.repository.WhitelistedSiteRepository; +import org.mitre.util.jpa.JpaUtil; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; @@ -88,8 +89,7 @@ public class JpaWhitelistedSiteRepository implements WhitelistedSiteRepository { public WhitelistedSite getByClientDetails(ClientDetails client) { TypedQuery query = manager.createNamedQuery("WhitelistedSite.getByClientDetails", WhitelistedSite.class); query.setParameter("clientDetails", client); - - return query.getSingleResult(); + return JpaUtil.getSingleResult(query.getResultList()); } @Override diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/JdbcUserApprovalHandler.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/JdbcUserApprovalHandler.java index 717e8c9ac..8372bc8a5 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/JdbcUserApprovalHandler.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/JdbcUserApprovalHandler.java @@ -17,7 +17,9 @@ package org.mitre.openid.connect.token; import java.util.Collection; 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.DefaultUserInfo; 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.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, * blacklist, and greylist. @@ -75,19 +80,22 @@ public class JdbcUserApprovalHandler implements UserApprovalHandler { @Override 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(); - ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId()); - - //lookup ApprovedSites by userId DefaultUserInfo user = (DefaultUserInfo)userInfoService.getByUserId(userId); + //lookup ApprovedSites by userId Collection approvedSites = approvedSiteService.getByUserInfo(user); for (ApprovedSite ap : approvedSites) { - if (ap.getClientDetails().getClientId() == client.getClientId()) { - //TODO need to test more than just id + if (sitesMatch(ap, authorizationRequest, user)) { + + //We have a match; update the access date on the AP entry and return true. + ap.setAccessDate(new Date()); + approvedSiteService.save(ap); + return true; } } @@ -107,15 +115,57 @@ public class JdbcUserApprovalHandler implements UserApprovalHandler { 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 ApprovedSite newAP = new ApprovedSite(); newAP.setAccessDate(new Date()); - //Set allowedScopes = authorizationRequest.getApprovalParameters().get("scope"); - //newAP.setAllowedScopes(allowedScopes); + String scopes = authorizationRequest.getAuthorizationParameters().get("scope"); + Set 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; } + + /** + * 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 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; + } } diff --git a/openid-connect-server/src/main/webapp/WEB-INF/application-context.xml b/openid-connect-server/src/main/webapp/WEB-INF/application-context.xml index 143836cf8..1177e3b22 100644 --- a/openid-connect-server/src/main/webapp/WEB-INF/application-context.xml +++ b/openid-connect-server/src/main/webapp/WEB-INF/application-context.xml @@ -57,7 +57,7 @@ client-details-service-ref="defaultOAuth2ClientDetailsEntityService" authorization-request-factory-ref="authorizationRequestFactory" token-services-ref="defaultOAuth2ProviderTokenService" - user-approval-handler-ref="userApprovalHandler" + user-approval-handler-ref="jdbcUserApprovalHandler" authorization-endpoint-url="/authorize" token-endpoint-url="/token"> @@ -82,8 +82,7 @@ - - + diff --git a/openid-connect-server/src/main/webapp/WEB-INF/views/oauth/approve.jsp b/openid-connect-server/src/main/webapp/WEB-INF/views/oauth/approve.jsp index 8c4bbe13d..2f8b7d074 100644 --- a/openid-connect-server/src/main/webapp/WEB-INF/views/oauth/approve.jsp +++ b/openid-connect-server/src/main/webapp/WEB-INF/views/oauth/approve.jsp @@ -62,16 +62,16 @@
Access to: - - basic profile information - - email address - - address - - phone number - - offline access + + + + + + + + + +