Search in sources :

Example 11 with ScopePathType

use of org.orcid.jaxb.model.message.ScopePathType in project ORCID-Source by ORCID.

the class OrcidApiAuthorizationSecurityAspect method visibilityResponseFilter.

@AfterReturning(pointcut = "@annotation(accessControl)", returning = "response")
public void visibilityResponseFilter(Response response, AccessControl accessControl) {
    if (accessControl.requestComesFromInternalApi()) {
        return;
    }
    Object entity = response.getEntity();
    if (entity != null && OrcidMessage.class.isAssignableFrom(entity.getClass())) {
        OrcidMessage orcidMessage = (OrcidMessage) entity;
        //If it is search results, don't filter them, just return them
        if (orcidMessage.getOrcidSearchResults() != null) {
            return;
        }
        // get the client id
        Object authentication = getAuthentication();
        Set<Visibility> visibilities = new HashSet<Visibility>();
        if (allowAnonymousAccess((Authentication) authentication, accessControl)) {
            visibilities.add(Visibility.PUBLIC);
        } else {
            visibilities = permissionChecker.obtainVisibilitiesForAuthentication(getAuthentication(), accessControl.requiredScope(), orcidMessage);
        }
        //If the message contains a bio, and the given name is filtered, restore it as an empty space
        boolean setEmptyGivenNameIfFiltered = false;
        if (orcidMessage.getOrcidProfile() != null) {
            if (orcidMessage.getOrcidProfile() != null && orcidMessage.getOrcidProfile().getOrcidBio() != null) {
                setEmptyGivenNameIfFiltered = true;
            }
        }
        ScopePathType requiredScope = accessControl.requiredScope();
        // If the required scope is */read-limited or */update
        if (isUpdateOrReadScope(requiredScope)) {
            // if it should be able to
            if (OrcidOAuth2Authentication.class.isAssignableFrom(authentication.getClass())) {
                OrcidOAuth2Authentication orcidAuth = (OrcidOAuth2Authentication) getAuthentication();
                OAuth2Request authorization = orcidAuth.getOAuth2Request();
                String clientId = authorization.getClientId();
                // #1: Get the user orcid
                String userOrcid = getUserOrcidFromOrcidMessage(orcidMessage);
                // #2: Evaluate the scope to know which field to filter
                boolean allowWorks = false;
                boolean allowFunding = false;
                boolean allowAffiliations = false;
                // Get the update equivalent scope, if it is reading, but,
                // doesnt have the read permissions, check if it have the
                // update permissions
                ScopePathType equivalentUpdateScope = getEquivalentUpdateScope(requiredScope);
                if (requiredScope.equals(ScopePathType.READ_LIMITED)) {
                    if (hasScopeEnabled(clientId, userOrcid, ScopePathType.ORCID_WORKS_READ_LIMITED.getContent(), ScopePathType.ORCID_WORKS_UPDATE.getContent()))
                        allowWorks = true;
                    if (hasScopeEnabled(clientId, userOrcid, ScopePathType.FUNDING_READ_LIMITED.getContent(), ScopePathType.FUNDING_UPDATE.getContent()))
                        allowFunding = true;
                    if (hasScopeEnabled(clientId, userOrcid, ScopePathType.AFFILIATIONS_READ_LIMITED.getContent(), ScopePathType.AFFILIATIONS_UPDATE.getContent()))
                        allowAffiliations = true;
                } else if (requiredScope.equals(ScopePathType.ORCID_WORKS_UPDATE) || requiredScope.equals(ScopePathType.ORCID_WORKS_READ_LIMITED)) {
                    // works
                    if (hasScopeEnabled(clientId, userOrcid, requiredScope.getContent(), equivalentUpdateScope == null ? null : equivalentUpdateScope.getContent()))
                        // If so, allow him to see private works
                        allowWorks = true;
                } else if (requiredScope.equals(ScopePathType.FUNDING_UPDATE) || requiredScope.equals(ScopePathType.FUNDING_READ_LIMITED)) {
                    // funding
                    if (hasScopeEnabled(clientId, userOrcid, requiredScope.getContent(), equivalentUpdateScope == null ? null : equivalentUpdateScope.getContent()))
                        // If so, allow him to see private funding
                        allowFunding = true;
                } else if (requiredScope.equals(ScopePathType.AFFILIATIONS_UPDATE) || requiredScope.equals(ScopePathType.AFFILIATIONS_READ_LIMITED)) {
                    // affiliations
                    if (hasScopeEnabled(clientId, userOrcid, requiredScope.getContent(), equivalentUpdateScope == null ? null : equivalentUpdateScope.getContent()))
                        // If so, allow him to see private affiliations
                        allowAffiliations = true;
                }
                visibilityFilter.filter(orcidMessage, clientId, allowWorks, allowFunding, allowAffiliations, visibilities.toArray(new Visibility[visibilities.size()]));
            } else {
                visibilityFilter.filter(orcidMessage, null, false, false, false, visibilities.toArray(new Visibility[visibilities.size()]));
            }
        } else {
            visibilityFilter.filter(orcidMessage, null, false, false, false, visibilities.toArray(new Visibility[visibilities.size()]));
        }
        //If the given name was set at the beginning and now is filtered, it means we should restore it as an empty field
        if (setEmptyGivenNameIfFiltered) {
            if (orcidMessage.getOrcidProfile() != null) {
                if (orcidMessage.getOrcidProfile().getOrcidBio() == null) {
                    orcidMessage.getOrcidProfile().setOrcidBio(new OrcidBio());
                }
                if (orcidMessage.getOrcidProfile().getOrcidBio().getPersonalDetails() == null) {
                    orcidMessage.getOrcidProfile().getOrcidBio().setPersonalDetails(new PersonalDetails());
                }
            }
        }
        //Filter given or family names visibility 
        if (orcidMessage.getOrcidProfile() != null) {
            if (orcidMessage.getOrcidProfile().getOrcidBio() != null) {
                if (orcidMessage.getOrcidProfile().getOrcidBio().getPersonalDetails() != null) {
                    if (orcidMessage.getOrcidProfile().getOrcidBio().getPersonalDetails().getGivenNames() != null) {
                        orcidMessage.getOrcidProfile().getOrcidBio().getPersonalDetails().getGivenNames().setVisibility(null);
                    } else {
                        //Null given names could break client integrations, so, lets return an empty string
                        GivenNames empty = new GivenNames();
                        empty.setContent(StringUtils.EMPTY);
                        orcidMessage.getOrcidProfile().getOrcidBio().getPersonalDetails().setGivenNames(empty);
                    }
                    if (orcidMessage.getOrcidProfile().getOrcidBio().getPersonalDetails().getFamilyName() != null) {
                        orcidMessage.getOrcidProfile().getOrcidBio().getPersonalDetails().getFamilyName().setVisibility(null);
                    }
                }
            }
        }
        //replace section visibilities now we may have filtered items
        if (orcidMessage.getOrcidProfile() != null) {
            if (orcidMessage.getOrcidProfile().getOrcidBio() != null) {
                if (orcidMessage.getOrcidProfile().getOrcidBio().getPersonalDetails() != null) {
                    OtherNames n = orcidMessage.getOrcidProfile().getOrcidBio().getPersonalDetails().getOtherNames();
                    if (n != null) {
                        n.setVisibility(getMostFromCollection(n.getOtherName()));
                    }
                }
                ExternalIdentifiers ids = orcidMessage.getOrcidProfile().getOrcidBio().getExternalIdentifiers();
                if (ids != null) {
                    ids.setVisibility(getMostFromCollection(ids.getExternalIdentifier()));
                }
                Keywords kws = orcidMessage.getOrcidProfile().getOrcidBio().getKeywords();
                if (kws != null) {
                    kws.setVisibility(getMostFromCollection(kws.getKeyword()));
                }
                ResearcherUrls urls = orcidMessage.getOrcidProfile().getOrcidBio().getResearcherUrls();
                if (urls != null) {
                    urls.setVisibility(getMostFromCollection(urls.getResearcherUrl()));
                }
            }
        }
    }
}
Also used : Keywords(org.orcid.jaxb.model.message.Keywords) OrcidBio(org.orcid.jaxb.model.message.OrcidBio) OtherNames(org.orcid.jaxb.model.message.OtherNames) OrcidOAuth2Authentication(org.orcid.core.oauth.OrcidOAuth2Authentication) PersonalDetails(org.orcid.jaxb.model.message.PersonalDetails) OAuth2Request(org.springframework.security.oauth2.provider.OAuth2Request) ScopePathType(org.orcid.jaxb.model.message.ScopePathType) GivenNames(org.orcid.jaxb.model.message.GivenNames) OrcidMessage(org.orcid.jaxb.model.message.OrcidMessage) ResearcherUrls(org.orcid.jaxb.model.message.ResearcherUrls) Visibility(org.orcid.jaxb.model.message.Visibility) ExternalIdentifiers(org.orcid.jaxb.model.message.ExternalIdentifiers) HashSet(java.util.HashSet) AfterReturning(org.aspectj.lang.annotation.AfterReturning)

Example 12 with ScopePathType

use of org.orcid.jaxb.model.message.ScopePathType in project ORCID-Source by ORCID.

the class DefaultPermissionChecker method removeUserGrantWriteScopePastValitity.

/*
     * Remove UserGrantWriteScope past the specified validity, returns true if
     * modified false otherwise
     */
public boolean removeUserGrantWriteScopePastValitity(OrcidOauth2TokenDetail tokenDetail) {
    boolean scopeRemoved = false;
    if (tokenDetail != null && tokenDetail.getScope() != null) {
        // Clean the scope if it is not a persistent token
        if (!tokenDetail.isPersistent()) {
            Set<String> scopes = OAuth2Utils.parseParameterList(tokenDetail.getScope());
            List<String> removeScopes = new ArrayList<String>();
            for (String scope : scopes) {
                if (scope != null && !scope.isEmpty()) {
                    ScopePathType scopePathType = ScopePathType.fromValue(scope);
                    if (scopePathType.isUserGrantWriteScope()) {
                        Date now = new Date();
                        if (now.getTime() > tokenDetail.getDateCreated().getTime() + (writeValiditySeconds * 1000)) {
                            removeScopes.add(scope);
                            scopeRemoved = true;
                        }
                    }
                }
            }
            if (scopeRemoved) {
                for (String scope : removeScopes) scopes.remove(scope);
                tokenDetail.setScope(OAuth2Utils.formatParameterList(scopes));
                orcidOauthTokenDetailService.saveOrUpdate(tokenDetail);
                return true;
            }
        }
    }
    return false;
}
Also used : ScopePathType(org.orcid.jaxb.model.message.ScopePathType) ArrayList(java.util.ArrayList) Date(java.util.Date)

Example 13 with ScopePathType

use of org.orcid.jaxb.model.message.ScopePathType in project ORCID-Source by ORCID.

the class TokenTargetFilterTest method setUpSecurityContext.

private void setUpSecurityContext(String userOrcid, String clientId, ScopePathType... scopePathTypes) {
    SecurityContextImpl securityContext = new SecurityContextImpl();
    OrcidOAuth2Authentication mockedAuthentication = mock(OrcidOAuth2Authentication.class);
    securityContext.setAuthentication(mockedAuthentication);
    SecurityContextHolder.setContext(securityContext);
    if (userOrcid != null) {
        ProfileEntity userProfileEntity = new ProfileEntity(userOrcid);
        when(mockedAuthentication.getPrincipal()).thenReturn(userProfileEntity);
        Authentication userAuthentication = mock(Authentication.class);
        when(userAuthentication.getPrincipal()).thenReturn(userProfileEntity);
        when(mockedAuthentication.getUserAuthentication()).thenReturn(userAuthentication);
    } else {
        when(mockedAuthentication.getPrincipal()).thenReturn(clientId);
    }
    Set<String> scopes = new HashSet<String>();
    if (scopePathTypes != null) {
        for (ScopePathType scopePathType : scopePathTypes) {
            scopes.add(scopePathType.value());
        }
    }
    OAuth2Request authorizationRequest = new OAuth2Request(Collections.<String, String>emptyMap(), clientId, Collections.<GrantedAuthority>emptyList(), true, scopes, Collections.<String>emptySet(), null, Collections.<String>emptySet(), Collections.<String, Serializable>emptyMap());
    when(mockedAuthentication.getOAuth2Request()).thenReturn(authorizationRequest);
    when(mockedAuthentication.isAuthenticated()).thenReturn(true);
}
Also used : SecurityContextImpl(org.springframework.security.core.context.SecurityContextImpl) OAuth2Request(org.springframework.security.oauth2.provider.OAuth2Request) ScopePathType(org.orcid.jaxb.model.message.ScopePathType) OrcidOAuth2Authentication(org.orcid.core.oauth.OrcidOAuth2Authentication) Authentication(org.springframework.security.core.Authentication) OrcidOAuth2Authentication(org.orcid.core.oauth.OrcidOAuth2Authentication) ProfileEntity(org.orcid.persistence.jpa.entities.ProfileEntity) HashSet(java.util.HashSet)

Example 14 with ScopePathType

use of org.orcid.jaxb.model.message.ScopePathType in project ORCID-Source by ORCID.

the class PublicClientTest method testAuthenticateIsTheOnlyScopeThatWorksForPublicClient.

@Test
public void testAuthenticateIsTheOnlyScopeThatWorksForPublicClient() throws JSONException, InterruptedException {
    String clientId = getPublicClientId();
    String clientRedirectUri = getPublicClientRedirectUri();
    String userId = getUser1OrcidId();
    String password = getUser1Password();
    WebDriver webDriver = getWebDriver();
    for (ScopePathType scope : ScopePathType.values()) {
        if (ScopePathType.AUTHENTICATE.equals(scope)) {
            String authCode = getAuthorizationCode(clientId, clientRedirectUri, scope.value(), userId, password, true);
            assertFalse(PojoUtil.isEmpty(authCode));
        } else {
            String authorizationPageUrl = String.format(OauthAuthorizationPageHelper.authorizationScreenUrl, getWebBaseUrl(), clientId, scope.value(), clientRedirectUri);
            webDriver.get(authorizationPageUrl);
            String authCodeUrl = webDriver.getCurrentUrl();
            assertFalse(PojoUtil.isEmpty(authCodeUrl));
            assertTrue(authCodeUrl.contains("error=invalid_scope"));
        }
    }
}
Also used : WebDriver(org.openqa.selenium.WebDriver) ScopePathType(org.orcid.jaxb.model.message.ScopePathType) Test(org.junit.Test)

Example 15 with ScopePathType

use of org.orcid.jaxb.model.message.ScopePathType in project ORCID-Source by ORCID.

the class InternalClientCredentialEndPointDelegatorImpl method obtainOauth2Token.

@Override
@Transactional
public Response obtainOauth2Token(String authorization, MultivaluedMap<String, String> formParams) {
    String clientId = formParams.getFirst("client_id");
    String scopeList = formParams.getFirst("scope");
    String grantType = formParams.getFirst("grant_type");
    // Verify it is a client_credentials grant type request
    if (!OrcidOauth2Constants.GRANT_TYPE_CLIENT_CREDENTIALS.equals(grantType)) {
        Object[] params = { grantType };
        throw new UnsupportedGrantTypeException(localeManager.resolveMessage("apiError.unsupported_client_type.exception", params));
    }
    Authentication client = getClientAuthentication();
    if (!client.isAuthenticated()) {
        LOGGER.info("Not authenticated for OAuth2: clientId={}, grantType={}, scope={}", new Object[] { clientId, grantType, scopeList });
        throw new InsufficientAuthenticationException(localeManager.resolveMessage("apiError.client_not_authenticated.exception"));
    }
    Set<String> scopes = new HashSet<String>();
    if (StringUtils.isNotEmpty(scopeList)) {
        scopes = OAuth2Utils.parseParameterList(scopeList);
    }
    // Verify it is requesting an internal scope
    HashSet<String> filteredScopes = new HashSet<String>();
    for (String scope : scopes) {
        ScopePathType scopeType = ScopePathType.fromValue(scope);
        if (scopeType.isInternalScope()) {
            filteredScopes.add(scope);
        }
    }
    if (filteredScopes.isEmpty()) {
        String message = localeManager.resolveMessage("apiError.9015.developerMessage", new Object[] {});
        throw new OrcidInvalidScopeException(message);
    }
    OAuth2AccessToken token = generateToken(client, scopes, null, null, grantType, null, null, null, false, 0L);
    return getResponse(token);
}
Also used : ScopePathType(org.orcid.jaxb.model.message.ScopePathType) Authentication(org.springframework.security.core.Authentication) OrcidInvalidScopeException(org.orcid.core.exception.OrcidInvalidScopeException) OAuth2AccessToken(org.springframework.security.oauth2.common.OAuth2AccessToken) InsufficientAuthenticationException(org.springframework.security.authentication.InsufficientAuthenticationException) UnsupportedGrantTypeException(org.springframework.security.oauth2.common.exceptions.UnsupportedGrantTypeException) HashSet(java.util.HashSet) Transactional(org.springframework.transaction.annotation.Transactional)

Aggregations

ScopePathType (org.orcid.jaxb.model.message.ScopePathType)30 HashSet (java.util.HashSet)16 Test (org.junit.Test)9 OrcidOAuth2Authentication (org.orcid.core.oauth.OrcidOAuth2Authentication)9 ProfileEntity (org.orcid.persistence.jpa.entities.ProfileEntity)8 Transactional (org.springframework.transaction.annotation.Transactional)8 ClientDetailsEntity (org.orcid.persistence.jpa.entities.ClientDetailsEntity)6 GrantedAuthority (org.springframework.security.core.GrantedAuthority)6 SimpleGrantedAuthority (org.springframework.security.core.authority.SimpleGrantedAuthority)6 AuthorizationRequest (org.springframework.security.oauth2.provider.AuthorizationRequest)6 OAuth2Authentication (org.springframework.security.oauth2.provider.OAuth2Authentication)6 ArrayList (java.util.ArrayList)5 RedirectUri (org.orcid.jaxb.model.clientgroup.RedirectUri)5 OrcidMessage (org.orcid.jaxb.model.message.OrcidMessage)5 DBUnitTest (org.orcid.test.DBUnitTest)5 OAuth2Request (org.springframework.security.oauth2.provider.OAuth2Request)5 Date (java.util.Date)4 OrcidOauth2TokenDetail (org.orcid.persistence.jpa.entities.OrcidOauth2TokenDetail)4 Authentication (org.springframework.security.core.Authentication)4 Rollback (org.springframework.test.annotation.Rollback)4