Skip to content

Commit 6a45a69

Browse files
authored
Ignore port for loopback redirect URIs (#21293)
Following https://datatracker.ietf.org/doc/html/rfc8252#section-7.3 Fixes #21285
1 parent 0e83ab8 commit 6a45a69

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

models/auth/oauth2.go

+13
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"encoding/base32"
1111
"encoding/base64"
1212
"fmt"
13+
"net"
1314
"net/url"
1415
"strings"
1516

@@ -56,6 +57,18 @@ func (app *OAuth2Application) PrimaryRedirectURI() string {
5657

5758
// ContainsRedirectURI checks if redirectURI is allowed for app
5859
func (app *OAuth2Application) ContainsRedirectURI(redirectURI string) bool {
60+
uri, err := url.Parse(redirectURI)
61+
// ignore port for http loopback uris following https://datatracker.ietf.org/doc/html/rfc8252#section-7.3
62+
if err == nil && uri.Scheme == "http" && uri.Port() != "" {
63+
ip := net.ParseIP(uri.Hostname())
64+
if ip != nil && ip.IsLoopback() {
65+
// strip port
66+
uri.Host = uri.Hostname()
67+
if util.IsStringInSlice(uri.String(), app.RedirectURIs, true) {
68+
return true
69+
}
70+
}
71+
}
5972
return util.IsStringInSlice(redirectURI, app.RedirectURIs, true)
6073
}
6174

models/auth/oauth2_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,26 @@ func TestOAuth2Application_ContainsRedirectURI(t *testing.T) {
4343
assert.False(t, app.ContainsRedirectURI("d"))
4444
}
4545

46+
func TestOAuth2Application_ContainsRedirectURI_WithPort(t *testing.T) {
47+
app := &auth_model.OAuth2Application{
48+
RedirectURIs: []string{"http://127.0.0.1/", "http://::1/", "http://192.168.0.1/", "http://intranet/", "https://127.0.0.1/"},
49+
}
50+
51+
// http loopback uris should ignore port
52+
// https://datatracker.ietf.org/doc/html/rfc8252#section-7.3
53+
assert.True(t, app.ContainsRedirectURI("http://127.0.0.1:3456/"))
54+
assert.True(t, app.ContainsRedirectURI("http://127.0.0.1/"))
55+
assert.True(t, app.ContainsRedirectURI("http://[::1]:3456/"))
56+
57+
// not http
58+
assert.False(t, app.ContainsRedirectURI("https://127.0.0.1:3456/"))
59+
// not loopback
60+
assert.False(t, app.ContainsRedirectURI("http://192.168.0.1:9954/"))
61+
assert.False(t, app.ContainsRedirectURI("http://intranet:3456/"))
62+
// unparseable
63+
assert.False(t, app.ContainsRedirectURI(":"))
64+
}
65+
4666
func TestOAuth2Application_ValidateClientSecret(t *testing.T) {
4767
assert.NoError(t, unittest.PrepareTestDatabase())
4868
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})

0 commit comments

Comments
 (0)