Skip to content

Commit 23d402f

Browse files
feat(sentry apps): Update the refresh token docs to have manual refresh (#15390)
1 parent d05b6f3 commit 23d402f

File tree

1 file changed

+45
-1
lines changed

1 file changed

+45
-1
lines changed

docs/organization/integrations/integration-platform/public-integration.mdx

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ All public integrations can be installed via a fixed external url: `https://sent
6666
Public integrations generate [authentication tokens](/organization/integrations/integration-platform/#auth-tokens) after a successful [OAuth installation](#oauth-process).
6767
These tokens automatically expire every eight hours, meaning they must be refreshed manually.
6868

69-
### Refreshing Tokens
69+
### Refreshing Tokens via Refresh Token (preferred)
7070

7171
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:
7272

@@ -108,6 +108,50 @@ def refresh_token(install_id):
108108
return new_token
109109
```
110110

111+
### Refreshing Tokens Manually for Integrators
112+
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.
113+
114+
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
115+
`/api/0/sentry-app-installations/{}/authorizations/` endpoint with the below claims and payload.
116+
117+
```python
118+
def manual_token_refresh(install_id):
119+
url = u'https://sentry.io/api/0/sentry-app-installations/{}/authorizations/'
120+
url = url.format(install_id)
121+
122+
now = datetime.now(timezone.utc).timestamp()
123+
client_secret = "XXXX-XXXX-XXXX"
124+
client_id = "1234-5678-9999"
125+
iat = now
126+
exp = now + 60 # 1 minute validity period
127+
128+
claims = {
129+
'iss': client_id,
130+
'sub': client_id,
131+
'iat': iat,
132+
'exp': exp,
133+
'jti': str(uuid.uuid4()),
134+
}
135+
jwt_token = jwt.encode(claims, client_secret, algorithm="HS256")
136+
137+
headers = {
138+
'Authorization': f'Bearer {jwt_token}',
139+
'Content-Type': 'application/json'
140+
}
141+
payload = {
142+
'grant_type': 'urn:sentry:params:oauth:grant-type:jwt-bearer',
143+
}
144+
145+
resp = requests.post(url, json=payload, headers=headers)
146+
data = resp.json()
147+
148+
new_token = data['token']
149+
new_refresh_token = data['refreshToken']
150+
# ... Securely update the token and refresh_token in DB...
151+
152+
return new_token
153+
```
154+
111155
The data you can expect back for both the initial grant code exchange and subsequent token refreshes is as follows:
112156

113157
```json

0 commit comments

Comments
 (0)