From 5c56a3fc1a44af9382ef621749327e7443a9f01e Mon Sep 17 00:00:00 2001 From: Christinarlong Date: Mon, 3 Nov 2025 13:39:38 -0800 Subject: [PATCH 1/4] update the refresh token docs to have manual refresh --- .../public-integration.mdx | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/docs/organization/integrations/integration-platform/public-integration.mdx b/docs/organization/integrations/integration-platform/public-integration.mdx index c4611ee3c6dc1d..0de3a73fcdd1bb 100644 --- a/docs/organization/integrations/integration-platform/public-integration.mdx +++ b/docs/organization/integrations/integration-platform/public-integration.mdx @@ -108,6 +108,46 @@ def refresh_token(install_id): return new_token ``` +### Refreshing Tokens Manually for Integrators +Sometimes incidents or other technical anomalies can lead to token refreshing being committed on the Sentry side but then the token is lost in transmission on the way back. As a result, we've added a method for integrators to explicitly refresh and request a new token for their installers. + +This manual refresh method uses a different authorization scheme where you will need to send a JWT signed with your client secret to the previous +`/api/0/sentry-app-installations/{}/authorizations/` endpoint with the below claims and payload. + +```python +def manual_token_refresh(install_id): + url = u'https://sentry.io/api/0/sentry-app-installations/{}/authorizations/' + url = url.format(install_id) + + now = datetime.now(timezone.utc).timestamp() + client_secret = "XXXX-XXXX-XXXX" + client_id = "1234-5678-9999" + iat = now + exp = now + 60 # 1 minute validity period + + claims = { + 'iss': client_id, + 'sub': client_id, + 'iat': iat, + 'exp': exp, + 'jti': uuid.uuid4(), + } + jwt_token = jwt.encode(claims, client_secret, algorithm="HS256") + headers = jwt.authorization_header(jwt_token) + + payload = { + 'grant_type': 'urn:sentry:params:oauth:grant-type:jwt-bearer', + } + resp = requests.post(url, json=payload, headers=headers) + data = resp.json() + + new_token = data['token'] + new_refresh_token = data['refreshToken'] + # ... Securely update the token and refresh_token in DB... + + return new_token +``` + The data you can expect back for both the initial grant code exchange and subsequent token refreshes is as follows: ```json From ecf67894dd000eef365a7bd9350447ee3e56aa52 Mon Sep 17 00:00:00 2001 From: Christinarlong Date: Mon, 3 Nov 2025 13:48:42 -0800 Subject: [PATCH 2/4] fix sentry comments --- .../integration-platform/public-integration.mdx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/organization/integrations/integration-platform/public-integration.mdx b/docs/organization/integrations/integration-platform/public-integration.mdx index 0de3a73fcdd1bb..09ee7d78b7f5f2 100644 --- a/docs/organization/integrations/integration-platform/public-integration.mdx +++ b/docs/organization/integrations/integration-platform/public-integration.mdx @@ -130,10 +130,14 @@ def manual_token_refresh(install_id): 'sub': client_id, 'iat': iat, 'exp': exp, - 'jti': uuid.uuid4(), + 'jti': str(uuid.uuid4()), } jwt_token = jwt.encode(claims, client_secret, algorithm="HS256") - headers = jwt.authorization_header(jwt_token) + headers = { + 'Authorization': f'Bearer {jwt_token}', + 'Content-Type': 'application/json' + } + payload = { 'grant_type': 'urn:sentry:params:oauth:grant-type:jwt-bearer', From 2fce2105eee8714b5abbd7acc0ea7dde33d2cc61 Mon Sep 17 00:00:00 2001 From: Christinarlong Date: Mon, 3 Nov 2025 14:12:48 -0800 Subject: [PATCH 3/4] update headers --- .../integration-platform/public-integration.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/organization/integrations/integration-platform/public-integration.mdx b/docs/organization/integrations/integration-platform/public-integration.mdx index 09ee7d78b7f5f2..768d0e4965b6ba 100644 --- a/docs/organization/integrations/integration-platform/public-integration.mdx +++ b/docs/organization/integrations/integration-platform/public-integration.mdx @@ -133,15 +133,15 @@ def manual_token_refresh(install_id): 'jti': str(uuid.uuid4()), } jwt_token = jwt.encode(claims, client_secret, algorithm="HS256") + headers = { 'Authorization': f'Bearer {jwt_token}', 'Content-Type': 'application/json' - } - - + } payload = { 'grant_type': 'urn:sentry:params:oauth:grant-type:jwt-bearer', } + resp = requests.post(url, json=payload, headers=headers) data = resp.json() From 9394e136d0d71fa4682e8f43a594a7fe37b0f1f2 Mon Sep 17 00:00:00 2001 From: Christinarlong Date: Mon, 10 Nov 2025 15:17:47 -0800 Subject: [PATCH 4/4] nits --- .../integrations/integration-platform/public-integration.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/organization/integrations/integration-platform/public-integration.mdx b/docs/organization/integrations/integration-platform/public-integration.mdx index 768d0e4965b6ba..e49164e22a039f 100644 --- a/docs/organization/integrations/integration-platform/public-integration.mdx +++ b/docs/organization/integrations/integration-platform/public-integration.mdx @@ -66,7 +66,7 @@ All public integrations can be installed via a fixed external url: `https://sent Public integrations generate [authentication tokens](/organization/integrations/integration-platform/#auth-tokens) after a successful [OAuth installation](#oauth-process). These tokens automatically expire every eight hours, meaning they must be refreshed manually. -### Refreshing Tokens +### Refreshing Tokens via Refresh Token (preferred) In the initial installation, you'll need the grant code given to you in either the installation webhook request or the redirect URL, in addition to your integration's client ID and client Secret: @@ -109,7 +109,7 @@ def refresh_token(install_id): ``` ### Refreshing Tokens Manually for Integrators -Sometimes incidents or other technical anomalies can lead to token refreshing being committed on the Sentry side but then the token is lost in transmission on the way back. As a result, we've added a method for integrators to explicitly refresh and request a new token for their installers. +Sometimes technical anomalies can lead to token refreshing being committed on the Sentry side but then the token is lost in transmission on the way back. As a result, we've added a method for integrators to explicitly refresh and request a new token for their installers. This manual refresh method uses a different authorization scheme where you will need to send a JWT signed with your client secret to the previous `/api/0/sentry-app-installations/{}/authorizations/` endpoint with the below claims and payload.