From 37db49a0daae93dd1d7eeab6af01cb08e72fad1e Mon Sep 17 00:00:00 2001 From: Angel Montenegro Date: Sun, 4 Aug 2024 14:01:58 -0600 Subject: [PATCH 1/9] Allow user revoked tokens to delete (#7060) * Deactivated records should get 409 on GET requests * On OBO, When a token is user disabled, it should be possible to use the short lived token to delete * More unit tests --- .../core/oauth/IETFExchangeTokenGranter.java | 13 ++++--- .../oauth/IETFExchangeTokenGranterTest.java | 36 +++++++++++++++++-- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/orcid-core/src/main/java/org/orcid/core/oauth/IETFExchangeTokenGranter.java b/orcid-core/src/main/java/org/orcid/core/oauth/IETFExchangeTokenGranter.java index 2e4f2381051..acf8139b2d5 100644 --- a/orcid-core/src/main/java/org/orcid/core/oauth/IETFExchangeTokenGranter.java +++ b/orcid-core/src/main/java/org/orcid/core/oauth/IETFExchangeTokenGranter.java @@ -50,7 +50,6 @@ */ public class IETFExchangeTokenGranter implements TokenGranter { - public static final String IETF_EXCHANGE = "urn:ietf:params:oauth:grant-type:token-exchange"; private AuthorizationServerTokenServices tokenServices; @Resource(name = "orcidOauth2AuthoriziationCodeDetailDao") @@ -75,7 +74,7 @@ public class IETFExchangeTokenGranter implements TokenGranter { @Resource OpenIDConnectTokenEnhancer openIDConnectTokenEnhancer; - private List doNotAllowDeleteOnTheseRevokeReasons = List.of(RevokeReason.CLIENT_REVOKED.name(), RevokeReason.STAFF_REVOKED.name()); + private final List doNotAllowDeleteOnTheseRevokeReasons = List.of(RevokeReason.CLIENT_REVOKED, RevokeReason.STAFF_REVOKED, RevokeReason.RECORD_DEACTIVATED, RevokeReason.AUTH_CODE_REUSED); public IETFExchangeTokenGranter(AuthorizationServerTokenServices tokenServices) { this.tokenServices = tokenServices; @@ -239,10 +238,12 @@ private OAuth2AccessToken generateAccessToken(TokenRequest tokenRequest, String Set inactiveScopesOBO = Sets.newHashSet(); boolean issueRevokedToken = false; RevokeReason revokeReason = null; + // Lets consider token expiration time anything that goes beyond this date + Date now = new Date(); for (OrcidOauth2TokenDetail d : details) { Set scopesInToken = ScopePathType.getScopesFromSpaceSeparatedString(d.getScope()); // If token is expired, we should ignore it - if (d.getTokenExpiration().after(new Date())) { + if (d.getTokenExpiration().after(now)) { // If token is disabled, we should know if it have the /activities/update scope on it if(d.getTokenDisabled() == null || !d.getTokenDisabled()) { activeScopesOBO.addAll(scopesInToken); @@ -257,8 +258,12 @@ private OAuth2AccessToken generateAccessToken(TokenRequest tokenRequest, String // Keep only the /activities/update scope if the token was not revoked by a client or staff member if(revokeReason == null || !doNotAllowDeleteOnTheseRevokeReasons.contains(revokeReason)) { inactiveScopesOBO.add(ScopePathType.ACTIVITIES_UPDATE); + } else { + throw new OrcidInvalidScopeException("The id_token is disabled and does not contain any valid scope"); } - } + } else { + throw new OrcidInvalidScopeException("The id_token is disabled and does not contain any valid scope"); + } } } } diff --git a/orcid-core/src/test/java/org/orcid/core/oauth/IETFExchangeTokenGranterTest.java b/orcid-core/src/test/java/org/orcid/core/oauth/IETFExchangeTokenGranterTest.java index 58308246b57..a277afcaa6f 100644 --- a/orcid-core/src/test/java/org/orcid/core/oauth/IETFExchangeTokenGranterTest.java +++ b/orcid-core/src/test/java/org/orcid/core/oauth/IETFExchangeTokenGranterTest.java @@ -289,14 +289,14 @@ public void grantDisabledTokenDoesntWorkTest() throws NoSuchAlgorithmException, tokenGranter.grant(GRANT_TYPE, getTokenRequest(ACTIVE_CLIENT_ID, List.of("/read-limited"))); fail(); } catch (OrcidInvalidScopeException oise) { - assertEquals("The id_token is not associated with a valid scope", oise.getMessage()); + assertEquals("The id_token is disabled and does not contain any valid scope", oise.getMessage()); } catch (Exception e) { fail(); } } @Test - public void grantDisabledTokenWithActivitiesReadLimitedGenerateDeactivatedTokenTest() + public void grantUserDisabledTokenWithActivitiesReadLimitedGenerateDeactivatedTokenTest() throws NoSuchAlgorithmException, IOException, ParseException, URISyntaxException, JOSEException { OrcidOauth2TokenDetail token1 = getOrcidOauth2TokenDetail(true, "/activities/update", System.currentTimeMillis() + 60000, true); token1.setRevokeReason(RevokeReason.USER_REVOKED.name()); @@ -309,6 +309,38 @@ public void grantDisabledTokenWithActivitiesReadLimitedGenerateDeactivatedTokenT verify(tokenServicesMock, never()).createAccessToken(any()); } + @Test + public void grantClientDisabledTokenWithActivitiesReadLimitedThrowExceptionTest() + throws NoSuchAlgorithmException, IOException, ParseException, URISyntaxException, JOSEException { + OrcidOauth2TokenDetail token1 = getOrcidOauth2TokenDetail(true, "/activities/update", System.currentTimeMillis() + 60000, true); + token1.setRevokeReason(RevokeReason.CLIENT_REVOKED.name()); + + when(orcidOauthTokenDetailServiceMock.findByClientIdAndUserName(any(), any())).thenReturn(List.of(token1)); + try { + tokenGranter.grant(GRANT_TYPE, getTokenRequest(ACTIVE_CLIENT_ID, List.of("/activities/update"))); + } catch(OrcidInvalidScopeException e) { + assertEquals("The id_token is disabled and does not contain any valid scope", e.getMessage()); + } catch(Exception e) { + fail("Unhandled exception:" + e.getMessage()); + } + } + + @Test + public void grantStaffDisabledTokenWithActivitiesReadLimitedThrowExceptionTest() + throws NoSuchAlgorithmException, IOException, ParseException, URISyntaxException, JOSEException { + OrcidOauth2TokenDetail token1 = getOrcidOauth2TokenDetail(true, "/activities/update", System.currentTimeMillis() + 60000, true); + token1.setRevokeReason(RevokeReason.STAFF_REVOKED.name()); + + when(orcidOauthTokenDetailServiceMock.findByClientIdAndUserName(any(), any())).thenReturn(List.of(token1)); + try { + tokenGranter.grant(GRANT_TYPE, getTokenRequest(ACTIVE_CLIENT_ID, List.of("/activities/update"))); + } catch(OrcidInvalidScopeException e) { + assertEquals("The id_token is disabled and does not contain any valid scope", e.getMessage()); + } catch(Exception e) { + fail("Unhandled exception:" + e.getMessage()); + } + } + @Test public void grantDisabledTokenWithActivitiesUpdateAndOtherActiveTokenWithOtherScopesGenerateDeactivatedTokenTest() throws NoSuchAlgorithmException, IOException, ParseException, URISyntaxException, JOSEException { From 64281a1418dacb945b806f59aedc07524263dd1d Mon Sep 17 00:00:00 2001 From: github actions Date: Sun, 4 Aug 2024 20:16:45 +0000 Subject: [PATCH 2/9] v2.62.6 changelog update --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dbc91d7d0f..381b557df84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v2.62.6 - 2024-08-04 + +[Full Changelog](https://github.com/ORCID/ORCID-Source/compare/v2.62.5...v2.62.6) + ## v2.62.5 - 2024-07-24 [Full Changelog](https://github.com/ORCID/ORCID-Source/compare/v2.62.4...v2.62.5) From 0d47f642e8e1e09b6e740e4ce0522306ef876a09 Mon Sep 17 00:00:00 2001 From: github actions Date: Sun, 4 Aug 2024 20:35:05 +0000 Subject: [PATCH 3/9] v2.63.0 changelog update --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 381b557df84..a3d1e8e93b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v2.63.0 - 2024-08-04 + +[Full Changelog](https://github.com/ORCID/ORCID-Source/compare/v2.62.6...v2.63.0) + ## v2.62.6 - 2024-08-04 [Full Changelog](https://github.com/ORCID/ORCID-Source/compare/v2.62.5...v2.62.6) From b3ee36423fc0836024b19e28f767b11a931bfe60 Mon Sep 17 00:00:00 2001 From: Camelia Dumitru <62257307+Camelia-Orcid@users.noreply.github.com> Date: Mon, 5 Aug 2024 17:46:57 +0100 Subject: [PATCH 4/9] added the notification view for panoply (#7059) Co-authored-by: Angel Montenegro --- .../src/main/resources/db-master.xml | 1 + .../db/updates/create_dw_notification.xml | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 orcid-persistence/src/main/resources/db/updates/create_dw_notification.xml diff --git a/orcid-persistence/src/main/resources/db-master.xml b/orcid-persistence/src/main/resources/db-master.xml index da9e14ed2b7..d0865c4510a 100644 --- a/orcid-persistence/src/main/resources/db-master.xml +++ b/orcid-persistence/src/main/resources/db-master.xml @@ -392,4 +392,5 @@ + diff --git a/orcid-persistence/src/main/resources/db/updates/create_dw_notification.xml b/orcid-persistence/src/main/resources/db/updates/create_dw_notification.xml new file mode 100644 index 00000000000..0af7616159d --- /dev/null +++ b/orcid-persistence/src/main/resources/db/updates/create_dw_notification.xml @@ -0,0 +1,20 @@ + + + + + + select notification_type, orcid, client_source_id, date_created, sent_date, read_date, actioned_date, archived_date, last_modified + from notification where notification_type='PERMISSION' and client_source_id is not null and last_modified > date_trunc('day',(now() - interval '12 months')) + + + + + + SELECT 1 FROM pg_roles WHERE rolname='dw_user' + + GRANT SELECT ON TABLE dw_notification to dw_user; + + + \ No newline at end of file From 4acffc31424a0c7031e3f2f3a0a7041cd4cd529d Mon Sep 17 00:00:00 2001 From: github actions Date: Mon, 5 Aug 2024 17:00:46 +0000 Subject: [PATCH 5/9] v2.63.1 changelog update --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3d1e8e93b5..811cf2df8c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v2.63.1 - 2024-08-05 + +[Full Changelog](https://github.com/ORCID/ORCID-Source/compare/v2.63.0...v2.63.1) + ## v2.63.0 - 2024-08-04 [Full Changelog](https://github.com/ORCID/ORCID-Source/compare/v2.62.6...v2.63.0) From fdde67ea67bb2c0e26bbda22df5514e341903728 Mon Sep 17 00:00:00 2001 From: Zoltan Date: Mon, 5 Aug 2024 16:28:05 -0400 Subject: [PATCH 6/9] Update refresh_tokens.md (#7058) Co-authored-by: Angel Montenegro --- orcid-api-web/tutorial/refresh_tokens.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orcid-api-web/tutorial/refresh_tokens.md b/orcid-api-web/tutorial/refresh_tokens.md index c8b815b01ad..00e089014a8 100644 --- a/orcid-api-web/tutorial/refresh_tokens.md +++ b/orcid-api-web/tutorial/refresh_tokens.md @@ -33,11 +33,11 @@ Example access token request response with access and refresh token: Create a new token with the same scopes and expiration and revoke the old token ``` -curl -d 'refresh_token=4470d1ff-c817-45c1-86d1-b9062669c7cb' -d 'grant_type=refresh_token' -d 'client_id=APP-5GG5N5YFOKGV5N0X' -d 'client_secret=ce4db92f-d535-4014-a250-b5cdc27c0984' -d 'revoke_old=true' https://api.sandbox.orcid.org/oauth/token +curl -d 'refresh_token=4470d1ff-c817-45c1-86d1-b9062669c7cb' -d 'grant_type=refresh_token' -d 'client_id=APP-5GG5N5YFOKGV5N0X' -d 'client_secret=ce4db92f-d535-4014-a250-b5cdc27c0984' -d 'revoke_old=true' https://sandbox.orcid.org/oauth/token ``` Create a new token with a subset of scopes, expiring in one day and do not revoke the old token ``` -curl -d 'refresh_token=4470d1ff-c817-45c1-86d1-b9062669c7cb' -d 'grant_type=refresh_token' -d 'client_id=APP-5GG5N5YFOKGV5N0X' -d 'client_secret=ce4db92f-d535-4014-a250-b5cdc27c0984' -d 'scope=/read-limited' -d 'expires_in=86400' https://api.sandbox.orcid.org/oauth/token +curl -d 'refresh_token=4470d1ff-c817-45c1-86d1-b9062669c7cb' -d 'grant_type=refresh_token' -d 'client_id=APP-5GG5N5YFOKGV5N0X' -d 'client_secret=ce4db92f-d535-4014-a250-b5cdc27c0984' -d 'scope=/read-limited' -d 'expires_in=86400' https://sandbox.orcid.org/oauth/token ``` From 168063cb5263f849845f0eb2478089e3231f2902 Mon Sep 17 00:00:00 2001 From: github actions Date: Mon, 5 Aug 2024 20:43:02 +0000 Subject: [PATCH 7/9] v2.63.2 changelog update --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 811cf2df8c9..ade30d81634 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v2.63.2 - 2024-08-05 + +[Full Changelog](https://github.com/ORCID/ORCID-Source/compare/v2.63.1...v2.63.2) + ## v2.63.1 - 2024-08-05 [Full Changelog](https://github.com/ORCID/ORCID-Source/compare/v2.63.0...v2.63.1) From ee144dab43310a70b24812f665b7bbf06c767c76 Mon Sep 17 00:00:00 2001 From: Angel Montenegro Date: Tue, 6 Aug 2024 15:16:00 -0600 Subject: [PATCH 8/9] Do not cache disabled tokens (#7061) * Deactivated records should get 409 on GET requests * Do not cache the token if it id disabled, since the token does not know its disabled state * Remove unused imports --- .../orcid/api/common/jaxb/OrcidExceptionMapper.java | 2 ++ .../OrcidClientCredentialEndPointDelegatorImpl.java | 7 ++++++- .../orcid/core/constants/OrcidOauth2Constants.java | 1 + .../orcid/core/oauth/IETFTokenExchangeResponse.java | 5 +++++ .../service/OrcidRandomValueTokenServicesImpl.java | 12 +++++------- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/orcid-api-common/src/main/java/org/orcid/api/common/jaxb/OrcidExceptionMapper.java b/orcid-api-common/src/main/java/org/orcid/api/common/jaxb/OrcidExceptionMapper.java index 418eceda83f..8819b3422f5 100644 --- a/orcid-api-common/src/main/java/org/orcid/api/common/jaxb/OrcidExceptionMapper.java +++ b/orcid-api-common/src/main/java/org/orcid/api/common/jaxb/OrcidExceptionMapper.java @@ -130,6 +130,8 @@ public Response toResponse(Throwable t) { logShortError(t, clientId); } else if (t instanceof InvalidPutCodeException) { logShortError(t, clientId); + } else if (t instanceof MismatchedPutCodeException) { + logShortError(t, clientId); } else { LOGGER.error("An exception has occured processing request from client " + clientId, t); } diff --git a/orcid-api-common/src/main/java/org/orcid/api/common/oauth/OrcidClientCredentialEndPointDelegatorImpl.java b/orcid-api-common/src/main/java/org/orcid/api/common/oauth/OrcidClientCredentialEndPointDelegatorImpl.java index 6d15fb7a930..db1c8e7ea83 100644 --- a/orcid-api-common/src/main/java/org/orcid/api/common/oauth/OrcidClientCredentialEndPointDelegatorImpl.java +++ b/orcid-api-common/src/main/java/org/orcid/api/common/oauth/OrcidClientCredentialEndPointDelegatorImpl.java @@ -162,8 +162,11 @@ public Response obtainOauth2Token(String authorization, MultivaluedMap additionalInformation = new HashMap(); @@ -47,6 +49,9 @@ public static IETFTokenExchangeResponse accessToken(OAuth2AccessToken accessTok if (accessToken.getAdditionalInformation().containsKey("name")) { token.additionalInformation.put("name",accessToken.getAdditionalInformation().get("name")); } + if(accessToken.getAdditionalInformation().containsKey(TOKEN_DISABLED)) { + token.additionalInformation.put(TOKEN_DISABLED, "true"); + } return token; } diff --git a/orcid-core/src/main/java/org/orcid/core/oauth/service/OrcidRandomValueTokenServicesImpl.java b/orcid-core/src/main/java/org/orcid/core/oauth/service/OrcidRandomValueTokenServicesImpl.java index 2f32a62ab3f..f9ec2d50b48 100644 --- a/orcid-core/src/main/java/org/orcid/core/oauth/service/OrcidRandomValueTokenServicesImpl.java +++ b/orcid-core/src/main/java/org/orcid/core/oauth/service/OrcidRandomValueTokenServicesImpl.java @@ -1,12 +1,6 @@ package org.orcid.core.oauth.service; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; import javax.annotation.Resource; import javax.persistence.PersistenceException; @@ -465,6 +459,10 @@ public OAuth2AccessToken createRevokedAccessToken(OAuth2Authentication authentic // create the regular token DefaultOAuth2AccessToken accessToken = generateAccessToken(authentication); try { + if(accessToken.getAdditionalInformation() == null) { + accessToken.setAdditionalInformation(Collections.emptyMap()); + } + accessToken.getAdditionalInformation().put(OrcidOauth2Constants.TOKEN_DISABLED, true); orcidTokenStore.storeRevokedAccessToken(accessToken, authentication, revokeReason); } catch (PersistenceException e) { // In the unlikely case that there is a constraint violation, lets From 3aec5ecd5a1d6f2be146bf7087e21f31a677afac Mon Sep 17 00:00:00 2001 From: github actions Date: Tue, 6 Aug 2024 21:29:58 +0000 Subject: [PATCH 9/9] v2.63.3 changelog update --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ade30d81634..3b8328dee49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v2.63.3 - 2024-08-06 + +[Full Changelog](https://github.com/ORCID/ORCID-Source/compare/v2.63.2...v2.63.3) + ## v2.63.2 - 2024-08-05 [Full Changelog](https://github.com/ORCID/ORCID-Source/compare/v2.63.1...v2.63.2)