Skip to content

Commit 8b7fe5b

Browse files
authored
Improve the default OAuth page content renderer not to embed external parameters as-is (#1352)
1 parent b085a4c commit 8b7fe5b

File tree

12 files changed

+51
-256
lines changed

12 files changed

+51
-256
lines changed

docs-src/oauth/index.rst

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ The code snippet below demonstrates how to build it using `Flask <https://flask.
3434
.. code-block:: python
3535
3636
import os
37+
import html
3738
from slack_sdk.oauth import AuthorizeUrlGenerator
3839
from slack_sdk.oauth.installation_store import FileInstallationStore, Installation
3940
from slack_sdk.oauth.state_store import FileOAuthStateStore
@@ -59,7 +60,7 @@ The code snippet below demonstrates how to build it using `Flask <https://flask.
5960
state = state_store.issue()
6061
# https://slack.com/oauth/v2/authorize?state=(generated value)&client_id={client_id}&scope=app_mentions:read,chat:write&user_scope=search:read
6162
url = authorize_url_generator.generate(state)
62-
return f'<a href="{url}">' \
63+
return f'<a href="{html.escape(url)}">' \
6364
f'<img alt=""Add to Slack"" height="40" width="139" src="https://platform.slack-edge.com/img/add_to_slack.png" srcset="https://platform.slack-edge.com/img/add_to_slack.png 1x, https://platform.slack-edge.com/img/[email protected] 2x" /></a>'
6465
6566
When accessing ``https://(your domain)/slack/install``, you will see "Add to Slack" button in the webpage. You can start the app's installation flow by clicking the button.
@@ -90,13 +91,11 @@ The redirection gives you a ``code`` parameter. You can exchange the value for a
9091
redirect_uri=redirect_uri,
9192
code=request.args["code"]
9293
)
93-
94-
installed_enterprise = oauth_response.get("enterprise", {})
94+
installed_enterprise = oauth_response.get("enterprise") or {}
9595
is_enterprise_install = oauth_response.get("is_enterprise_install")
96-
installed_team = oauth_response.get("team", {})
97-
installer = oauth_response.get("authed_user", {})
98-
incoming_webhook = oauth_response.get("incoming_webhook", {})
99-
96+
installed_team = oauth_response.get("team") or {}
97+
installer = oauth_response.get("authed_user") or {}
98+
incoming_webhook = oauth_response.get("incoming_webhook") or {}
10099
bot_token = oauth_response.get("access_token")
101100
# NOTE: oauth.v2.access doesn't include bot_id in response
102101
bot_id = None
@@ -137,7 +136,7 @@ The redirection gives you a ``code`` parameter. You can exchange the value for a
137136
return make_response(f"Try the installation again (the state value is already expired)", 400)
138137
139138
error = request.args["error"] if "error" in request.args else ""
140-
return make_response(f"Something is wrong with the installation (error: {error})", 400)
139+
return make_response(f"Something is wrong with the installation (error: {html.escape(error)})", 400)
141140
142141
Token Lookup
143142
*************************************************

integration_tests/samples/oauth/oauth_v2.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# ---------------------
22
# Flask App for Slack OAuth flow
33
# ---------------------
4+
import html
45

56
# pip3 install flask
67
from flask import Flask, request, make_response
@@ -41,7 +42,7 @@ def oauth_start():
4142
state = state_store.issue()
4243
url = authorization_url_generator.generate(state)
4344
return (
44-
f'<a href="{url}">'
45+
f'<a href="{html.escape(url)}">'
4546
f'<img alt=""Add to Slack"" height="40" width="139" src="https://platform.slack-edge.com/img/add_to_slack.png" srcset="https://platform.slack-edge.com/img/add_to_slack.png 1x, https://platform.slack-edge.com/img/[email protected] 2x" /></a>'
4647
)
4748

@@ -57,11 +58,11 @@ def oauth_callback():
5758
oauth_response = client.oauth_v2_access(client_id=client_id, client_secret=client_secret, code=code)
5859
logger.info(f"oauth.v2.access response: {oauth_response}")
5960

60-
installed_enterprise = oauth_response.get("enterprise", {})
61+
installed_enterprise = oauth_response.get("enterprise") or {}
6162
is_enterprise_install = oauth_response.get("is_enterprise_install")
62-
installed_team = oauth_response.get("team", {})
63-
installer = oauth_response.get("authed_user", {})
64-
incoming_webhook = oauth_response.get("incoming_webhook", {})
63+
installed_team = oauth_response.get("team") or {}
64+
installer = oauth_response.get("authed_user") or {}
65+
incoming_webhook = oauth_response.get("incoming_webhook") or {}
6566

6667
bot_token = oauth_response.get("access_token")
6768
# NOTE: oauth.v2.access doesn't include bot_id in response
@@ -105,7 +106,7 @@ def oauth_callback():
105106
return redirect_page_renderer.render_failure_page("the state value is already expired")
106107

107108
error = request.args["error"] if "error" in request.args else ""
108-
return make_response(f"Something is wrong with the installation (error: {error})", 400)
109+
return redirect_page_renderer.render_failure_page(error)
109110

110111

111112
# ---------------------

integration_tests/samples/oauth/oauth_v2_async.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# ---------------------
22
# Sanic App for Slack OAuth flow
33
# ---------------------
4-
4+
import html
55
import logging
66
import os
77
from slack_sdk.web.async_client import AsyncWebClient
@@ -44,7 +44,7 @@ async def oauth_start(req: Request):
4444
url = authorization_url_generator.generate(state)
4545
return HTTPResponse(
4646
status=200,
47-
body=f'<a href="{url}">'
47+
body=f'<a href="{html.escape(url)}">'
4848
f'<img alt=""Add to Slack"" height="40" width="139" src="https://platform.slack-edge.com/img/add_to_slack.png" srcset="https://platform.slack-edge.com/img/add_to_slack.png 1x, https://platform.slack-edge.com/img/[email protected] 2x" /></a>',
4949
)
5050

@@ -61,6 +61,7 @@ async def oauth_callback(req: Request):
6161
logger.info(f"oauth.v2.access response: {oauth_response}")
6262

6363
installed_enterprise = oauth_response.get("enterprise") or {}
64+
is_enterprise_install = oauth_response.get("is_enterprise_install")
6465
installed_team = oauth_response.get("team") or {}
6566
installer = oauth_response.get("authed_user") or {}
6667
incoming_webhook = oauth_response.get("incoming_webhook") or {}
@@ -85,6 +86,8 @@ async def oauth_callback(req: Request):
8586
incoming_webhook_url=incoming_webhook.get("url"),
8687
incoming_webhook_channel_id=incoming_webhook.get("channel_id"),
8788
incoming_webhook_configuration_url=incoming_webhook.get("configuration_url"),
89+
is_enterprise_install=is_enterprise_install,
90+
token_type=oauth_response.get("token_type"),
8891
)
8992
installation_store.save(installation)
9093
html = redirect_page_renderer.render_success_page(
@@ -111,7 +114,11 @@ async def oauth_callback(req: Request):
111114
)
112115

113116
error = req.args.get("error") if "error" in req.args else ""
114-
return HTTPResponse(status=400, body=f"Something is wrong with the installation (error: {error})")
117+
return HTTPResponse(
118+
status=400,
119+
headers={"Content-Type": "text/html; charset=utf-8"},
120+
body=redirect_page_renderer.render_failure_page(error),
121+
)
115122

116123

117124
# ---------------------

integration_tests/samples/oauth/oauth_v2_legacy.py

Lines changed: 0 additions & 224 deletions
This file was deleted.

integration_tests/samples/openid_connect/flask_example.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def oauth_callback():
9191
return redirect_page_renderer.render_failure_page("The state value is already expired")
9292

9393
error = request.args["error"] if "error" in request.args else ""
94-
return make_response(f"Something is wrong with the installation (error: {error})", 400)
94+
return redirect_page_renderer.render_failure_page(error)
9595

9696

9797
if __name__ == "__main__":

0 commit comments

Comments
 (0)