Skip to content

Commit 9863d1e

Browse files
authored
Improve the default OAuth page renderers (#1140)
1 parent a288ac8 commit 9863d1e

File tree

6 files changed

+85
-4
lines changed

6 files changed

+85
-4
lines changed

bolt/pom.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
<version>1.29.2-SNAPSHOT</version>
1414
<packaging>jar</packaging>
1515

16+
<properties>
17+
<commons-text.version>1.10.0</commons-text.version>
18+
</properties>
19+
1620
<dependencies>
1721
<dependency>
1822
<groupId>com.slack.api</groupId>
@@ -29,6 +33,11 @@
2933
<artifactId>slack-app-backend</artifactId>
3034
<version>${project.version}</version>
3135
</dependency>
36+
<dependency>
37+
<groupId>org.apache.commons</groupId>
38+
<artifactId>commons-text</artifactId>
39+
<version>${commons-text.version}</version>
40+
</dependency>
3241

3342
<dependency>
3443
<groupId>com.amazonaws</groupId>

bolt/src/main/java/com/slack/api/bolt/service/builtin/oauth/view/default_impl/OAuthDefaultInstallPageRenderer.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.slack.api.bolt.service.builtin.oauth.view.default_impl;
22

33
import com.slack.api.bolt.service.builtin.oauth.view.OAuthInstallPageRenderer;
4+
import org.apache.commons.text.StringEscapeUtils;
45

56
public class OAuthDefaultInstallPageRenderer implements OAuthInstallPageRenderer {
67

@@ -23,7 +24,8 @@ public class OAuthDefaultInstallPageRenderer implements OAuthInstallPageRenderer
2324

2425
@Override
2526
public String render(String authorizeUrl) {
26-
return PAGE_TEMPLATE.replaceAll("__URL__", authorizeUrl == null ? "" : authorizeUrl);
27+
String url = StringEscapeUtils.escapeHtml4(authorizeUrl);
28+
return PAGE_TEMPLATE.replaceAll("__URL__", url == null ? "" : url);
2729
}
2830

2931
}

bolt/src/main/java/com/slack/api/bolt/service/builtin/oauth/view/default_impl/OAuthDefaultRedirectUriPageRenderer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.slack.api.bolt.model.Installer;
44
import com.slack.api.bolt.service.builtin.oauth.view.OAuthRedirectUriPageRenderer;
5+
import org.apache.commons.text.StringEscapeUtils;
56

67
public class OAuthDefaultRedirectUriPageRenderer implements OAuthRedirectUriPageRenderer {
78

@@ -65,13 +66,18 @@ public String renderSuccessPage(Installer installer, String completionUrl) {
6566
String browserUrl = installer == null || installer.getTeamId() == null
6667
? "https://slack.com/"
6768
: "https://app.slack.com/client/" + installer.getTeamId();
69+
70+
url = StringEscapeUtils.escapeHtml4(url);
71+
browserUrl = StringEscapeUtils.escapeHtml4(browserUrl);
6872
return SUCCESS_PAGE_TEMPLATE
6973
.replaceAll("__URL__", url == null ? "" : url)
7074
.replaceAll("__BROWSER_URL__", browserUrl);
7175
}
7276

7377
@Override
7478
public String renderFailurePage(String installPath, String reason) {
79+
installPath = StringEscapeUtils.escapeHtml4(installPath);
80+
reason = StringEscapeUtils.escapeHtml4(reason);
7581
return FAILURE_PAGE_TEMPLATE
7682
.replaceAll("__INSTALL_PATH__", installPath == null ? "" : installPath)
7783
.replaceAll("__REASON__", reason == null ? "unknown_error" : reason);

bolt/src/test/java/test_locally/app/OAuthCallbacksTest.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@
77
import com.slack.api.bolt.AppConfig;
88
import com.slack.api.bolt.model.Bot;
99
import com.slack.api.bolt.model.Installer;
10+
import com.slack.api.bolt.model.builtin.DefaultInstaller;
1011
import com.slack.api.bolt.request.Request;
1112
import com.slack.api.bolt.request.RequestHeaders;
1213
import com.slack.api.bolt.request.builtin.OAuthCallbackRequest;
1314
import com.slack.api.bolt.response.Response;
1415
import com.slack.api.bolt.service.InstallationService;
1516
import com.slack.api.bolt.service.builtin.ClientOnlyOAuthStateService;
17+
import com.slack.api.bolt.service.builtin.oauth.view.OAuthRedirectUriPageRenderer;
18+
import com.slack.api.bolt.service.builtin.oauth.view.default_impl.OAuthDefaultRedirectUriPageRenderer;
1619
import lombok.extern.slf4j.Slf4j;
1720
import org.junit.After;
1821
import org.junit.Before;
@@ -151,4 +154,65 @@ public void oauthPersistenceErrorCallback() throws Exception {
151154
Response response = app.run(req);
152155
assertThat(response.getStatusCode(), is(expectedStatusCode));
153156
}
157+
158+
@Test
159+
public void testDefaultRenderer_renderSuccessPage() {
160+
OAuthRedirectUriPageRenderer renderer = new OAuthDefaultRedirectUriPageRenderer();
161+
{
162+
Installer installer = new DefaultInstaller();
163+
installer.setAppId("A123");
164+
installer.setTeamId("T123");
165+
String page = renderer.renderSuccessPage(installer, "https://www.example.com/?foo=bar&baz=123");
166+
assertThat(page.contains("https://www.example.com/?foo=bar&baz=123"), is(false));
167+
assertThat(page.contains("<meta http-equiv=\"refresh\" content=\"0; URL=https://www.example.com/?foo=bar&amp;baz=123\">"), is(true));
168+
assertThat(page.contains("<a href=\"https://www.example.com/?foo=bar&amp;baz=123\">here</a>"), is(true));
169+
assertThat(page.contains("<a href=\"https://app.slack.com/client/T123\" target=\"_blank\">"), is(true));
170+
}
171+
{
172+
Installer installer = new DefaultInstaller();
173+
installer.setAppId(null);
174+
installer.setTeamId(null);
175+
String page = renderer.renderSuccessPage(installer, null);
176+
assertThat(page.contains("<meta http-equiv=\"refresh\" content=\"0; URL=slack://open\">"), is(true));
177+
assertThat(page.contains("<a href=\"slack://open\">here</a>"), is(true));
178+
assertThat(page.contains("<a href=\"https://slack.com/\" target=\"_blank\">"), is(true));
179+
}
180+
{
181+
Installer installer = new DefaultInstaller();
182+
installer.setAppId("A123");
183+
installer.setTeamId("T123");
184+
String page = renderer.renderSuccessPage(installer, null);
185+
assertThat(page.contains("slack://app?team=T123&id=A123"), is(false));
186+
assertThat(page.contains("<meta http-equiv=\"refresh\" content=\"0; URL=slack://app?team=T123&amp;id=A123\">"), is(true));
187+
assertThat(page.contains("<a href=\"slack://app?team=T123&amp;id=A123\">here</a>"), is(true));
188+
assertThat(page.contains("<a href=\"https://app.slack.com/client/T123\" target=\"_blank\">"), is(true));
189+
}
190+
{
191+
Installer installer = new DefaultInstaller();
192+
installer.setAppId("A123");
193+
installer.setTeamId("T123");
194+
installer.setEnterpriseId("E123");
195+
installer.setIsEnterpriseInstall(true);
196+
installer.setEnterpriseUrl("https://test.enterprise.slack.com/");
197+
String page = renderer.renderSuccessPage(installer, null);
198+
assertThat(page.contains("<meta http-equiv=\"refresh\" content=\"0; URL=https://test.enterprise.slack.com/manage/organization/apps/profile/A123/workspaces/add\">"), is(true));
199+
assertThat(page.contains("<a href=\"https://test.enterprise.slack.com/manage/organization/apps/profile/A123/workspaces/add\">here</a>"), is(true));
200+
assertThat(page.contains("<a href=\"https://app.slack.com/client/T123\" target=\"_blank\">"), is(true));
201+
}
202+
}
203+
204+
@Test
205+
public void testDefaultRenderer_renderFailurePage() {
206+
OAuthRedirectUriPageRenderer renderer = new OAuthDefaultRedirectUriPageRenderer();
207+
{
208+
String page = renderer.renderFailurePage("/slack/install", "access_denied");
209+
assertThat(page.contains("<a href=\"/slack/install\">here</a> or contact the app owner (reason: access_denied)"), is(true));
210+
}
211+
{
212+
String page = renderer.renderFailurePage("/slack/install&team=T123&foo=bar", "<b>test</b>");
213+
assertThat(page.contains("/slack/install&team=T123&foo=bar"), is(false));
214+
assertThat(page.contains("<b>test</b>"), is(false));
215+
assertThat(page.contains("<a href=\"/slack/install&amp;team=T123&amp;foo=bar\">here</a> or contact the app owner (reason: &lt;b&gt;test&lt;/b&gt;)"), is(true));
216+
}
217+
}
154218
}

bolt/src/test/java/test_locally/app/OAuthStartTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public String issueNewState(Request request, Response response) {
4848
"</head>\n" +
4949
"<body>\n" +
5050
"<h2>Slack App Installation</h2>\n" +
51-
"<p><a href=\"https://slack.com/oauth/v2/authorize?client_id=111.222&scope=commands%2Cchat%3Awrite&user_scope=&state=generated-state-value\"><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></p>\n" +
51+
"<p><a href=\"https://slack.com/oauth/v2/authorize?client_id=111.222&amp;scope=commands%2Cchat%3Awrite&amp;user_scope=&amp;state=generated-state-value\"><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></p>\n" +
5252
"</body>\n" +
5353
"</html>", response.getBody());
5454
}
@@ -78,7 +78,7 @@ public void start_state_validation_disabled() throws Exception {
7878
"</head>\n" +
7979
"<body>\n" +
8080
"<h2>Slack App Installation</h2>\n" +
81-
"<p><a href=\"https://slack.com/oauth/v2/authorize?client_id=111.222&scope=commands%2Cchat%3Awrite&user_scope=&state=\"><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></p>\n" +
81+
"<p><a href=\"https://slack.com/oauth/v2/authorize?client_id=111.222&amp;scope=commands%2Cchat%3Awrite&amp;user_scope=&amp;state=\"><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></p>\n" +
8282
"</body>\n" +
8383
"</html>", response.getBody());
8484
}

bolt/src/test/java/test_locally/app/OpenIDConnectTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public void deleteNonceFromDatastore(String nonce) {
6666
"</head>\n" +
6767
"<body>\n" +
6868
"<h2>Slack App Installation</h2>\n" +
69-
"<p><a href=\"https://slack.com/openid/connect/authorize?client_id=111.222&response_type=code&scope=openid%2Cemail%2Cprofile&state=generated-state-value&nonce=generated-nonce-value\"><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></p>\n" +
69+
"<p><a href=\"https://slack.com/openid/connect/authorize?client_id=111.222&amp;response_type=code&amp;scope=openid%2Cemail%2Cprofile&amp;state=generated-state-value&amp;nonce=generated-nonce-value\"><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></p>\n" +
7070
"</body>\n" +
7171
"</html>";
7272

0 commit comments

Comments
 (0)