summaryrefslogtreecommitdiff
path: root/internal/oauth
diff options
context:
space:
mode:
authorjwijenbergh <jeroenwijenbergh@protonmail.com>2023-09-27 16:07:15 +0200
committerJeroen Wijenbergh <46386452+jwijenbergh@users.noreply.github.com>2023-09-29 13:31:43 +0200
commit9af1abef900dc4100b0ac0b757a4afa73cd22583 (patch)
treefb2ea75d894d14208a21773b5b9cade081907c5e /internal/oauth
parentee38ef96dfa6409bca1edc37d9ab63c27d3adcec (diff)
OAuth: Correctly pass Redirect URI to token request
Diffstat (limited to 'internal/oauth')
-rw-r--r--internal/oauth/oauth.go57
1 files changed, 23 insertions, 34 deletions
diff --git a/internal/oauth/oauth.go b/internal/oauth/oauth.go
index 6de3ac7..3d5930b 100644
--- a/internal/oauth/oauth.go
+++ b/internal/oauth/oauth.go
@@ -110,6 +110,9 @@ type exchangeSession struct {
// Verifier is the preimage of the challenge
Verifier string
+ // RedirectURI is the passed redirect URI
+ RedirectURI string
+
// Listener is the listener where the servers 'listens' on
Listener net.Listener
@@ -132,14 +135,13 @@ func (oauth *OAuth) AccessToken(ctx context.Context) (string, error) {
// If it was unsuccessful it returns an error.
// @see https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-07.html#section-8.4.2
// "Loopback Interface Redirection".
-func (oauth *OAuth) setupListener() error {
+func (oauth *OAuth) setupListener() (net.Listener, error) {
// create a listener
lst, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
- return errors.WrapPrefix(err, "net.Listen failed", 0)
+ return nil, errors.WrapPrefix(err, "net.Listen failed", 0)
}
- oauth.session.Listener = lst
- return nil
+ return lst, nil
}
// tokensWithCallback gets the OAuth tokens using a local web server
@@ -228,17 +230,12 @@ func (oauth *OAuth) tokensWithAuthCode(ctx context.Context, authCode string) err
// so that the server can verify that we are the actual owner of the authorization code
u := oauth.TokenURL
- port, err := oauth.ListenerPort()
- if err != nil {
- return err
- }
-
data := url.Values{
"client_id": {oauth.ClientID},
"code": {authCode},
"code_verifier": {oauth.session.Verifier},
"grant_type": {"authorization_code"},
- "redirect_uri": {fmt.Sprintf("http://127.0.0.1:%d/callback", port)},
+ "redirect_uri": {oauth.session.RedirectURI},
}
h := http.Header{
"content-type": {"application/x-www-form-urlencoded"},
@@ -436,15 +433,6 @@ func (oauth *OAuth) Init(clientID string, iss string, baseAuthorizationURL strin
oauth.TokenURL = tokenURL
}
-// ListenerPort gets the listener for the OAuth web server
-// It returns the port as an integer and an error if there is any.
-func (oauth *OAuth) ListenerPort() (int, error) {
- if oauth.session.Listener == nil {
- return 0, errors.New("failed to get listener port")
- }
- return oauth.session.Listener.Addr().(*net.TCPAddr).Port, nil
-}
-
// AuthURL gets the authorization url to start the OAuth procedure.
func (oauth *OAuth) AuthURL(name string, postProcessAuth func(string) string, cr string) (string, error) {
// Update the client ID
@@ -466,27 +454,28 @@ func (oauth *OAuth) AuthURL(name string, postProcessAuth func(string) string, cr
oauth.UpdateTokens(Token{})
// Fill the struct with the necessary fields filled for the next call to getting the HTTP client
- oauth.session = exchangeSession{
- ISS: oauth.ISS,
- State: state,
- Verifier: v,
- ErrChan: make(chan error),
- }
-
- // set up the listener to get the redirect URI
- if err = oauth.setupListener(); err != nil {
- return "", errors.WrapPrefix(err, "oauth.setupListener error", 0)
- }
-
red := cr
+
+ // no custom redirect URI defined, we setup our own
+ var l net.Listener
if cr == "" {
- // Get the listener port
- port, err := oauth.ListenerPort()
+ // set up the listener to get the redirect URI
+ l, err = oauth.setupListener()
if err != nil {
- return "", errors.WrapPrefix(err, "oauth.ListenerPort error", 0)
+ return "", errors.WrapPrefix(err, "oauth.setupListener error", 0)
}
+ port := l.Addr().(*net.TCPAddr).Port
+ // see https://git.sr.ht/~fkooman/vpn-user-portal/tree/v3/item/src/OAuth/VpnClientDb.php
red = fmt.Sprintf("http://127.0.0.1:%d/callback", port)
}
+ oauth.session = exchangeSession{
+ ISS: oauth.ISS,
+ State: state,
+ Verifier: v,
+ ErrChan: make(chan error),
+ RedirectURI: red,
+ Listener: l,
+ }
params := map[string]string{
"client_id": name,